* [RFC PATCH v2 4/8] Support remote helpers implementing smart transports
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
Documentation/git-remote-helpers.txt | 28 ++++++++++-
transport-helper.c | 96 +++++++++++++++++++++++++++++++++-
transport.c | 21 +++++++
transport.h | 5 ++
4 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 5cfdc0c..91cd9eb 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -90,6 +90,23 @@ Supported if the helper has the "push" capability.
+
Supported if the helper has the "import" capability.
+'connect' <service>::
+ Connects to given service. Stdin and stdout of helper are
+ connected to specified service (git prefix is included in service
+ name so e.g. fetching uses 'git-upload-pack' as service) on
+ remote side. Valid replies to this command are empty line
+ (connection established), 'FALLBACK' (no smart transport support,
+ fall back to dumb transports) and just exiting with error message
+ printed (can't connect, don't bother trying to fall back). After
+ line feed terminating the positive (empty) response, the output
+ of service starts. After the connection ends, the remote
+ helper exits. Note that to prevent deadlocking, all read data
+ should be immediately flushed to outgoing connection (excepting
+ remote initial advertisments, which should be flushed on first
+ flush packet (0000 as length) encountered.
++
+Supported if the helper has the "connect" capability.
+
If a fatal error occurs, the program writes the error message to
stderr and exits. The caller should expect that a suitable error
message has been printed if the child closes the connection without
@@ -123,6 +140,9 @@ CAPABILITIES
all, it must cover all refs reported by the list command; if
it is not used, it is effectively "*:*"
+'connect'::
+ This helper supports the 'connect' command.
+
REF LIST ATTRIBUTES
-------------------
@@ -165,9 +185,15 @@ OPTIONS
but don't actually change any repository data. For most
helpers this only applies to the 'push', if supported.
+'option servpath <c-style-quoted-path>'::
+ Set service path (--upload-pack, --receive-pack etc.) for
+ next connect. Remote helper MAY support this option. Remote
+ helper MUST NOT rely on this option being set before
+ connect request occurs.
+
Documentation
-------------
-Documentation by Daniel Barkalow.
+Documentation by Daniel Barkalow and Ilari Liusvaara
GIT
---
diff --git a/transport-helper.c b/transport-helper.c
index 5d17fb5..21aa4ab 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -16,7 +16,8 @@ struct helper_data
unsigned fetch : 1,
import : 1,
option : 1,
- push : 1;
+ push : 1,
+ connect : 1;
/* These go from remote name (as in "list") to private name */
struct refspec *refspecs;
int refspec_nr;
@@ -72,7 +73,10 @@ static struct child_process *get_helper(struct transport *transport)
helper->argv = xcalloc(4, sizeof(*helper->argv));
strbuf_addf(&buf, "remote-%s", data->name);
helper->argv[0] = strbuf_detach(&buf, NULL);
- helper->argv[1] = transport->remote->name;
+ if(transport->remote)
+ helper->argv[1] = transport->remote->name;
+ else
+ helper->argv[1] = "";
helper->argv[2] = remove_ext_force(transport->url);
helper->git_cmd = 1;
if (start_command(helper))
@@ -113,6 +117,8 @@ static struct child_process *get_helper(struct transport *transport)
refspec_alloc);
refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
}
+ if (!strcmp(buf.buf, "connect"))
+ data->connect = 1;
}
if (refspecs) {
int i;
@@ -331,12 +337,91 @@ static int fetch_with_import(struct transport *transport,
return 0;
}
+static int _process_connect(struct transport *transport,
+ const char *name, const char *exec)
+{
+ struct helper_data *data = transport->data;
+ struct strbuf cmdbuf = STRBUF_INIT;
+ struct child_process *helper;
+ int r;
+
+ helper = get_helper(transport);
+
+ /* Handle --upload-pack and friends. This is fire and forget...
+ just warn if it fails. */
+ if(exec && strcmp(name, exec)) {
+ r = set_helper_option(transport, "servpath", exec);
+ if(r > 0)
+ fprintf(stderr, "Warning: Setting remote service path "
+ "not supported by protocol.\n");
+ else if(r < 0)
+ fprintf(stderr, "Warning: Invalid remote service "
+ "path.\n");
+ }
+
+ if(data->connect) {
+ strbuf_addf(&cmdbuf, "connect %s\n", name);
+ } else
+ return 0;
+
+ write_in_full(helper->in, cmdbuf.buf, cmdbuf.len);
+ strbuf_reset(&cmdbuf);
+ if (strbuf_getline(&cmdbuf, data->out, '\n') == EOF)
+ exit(128); /* child died, message supplied already */
+ if(!strcmp(cmdbuf.buf, ""))
+ return 1;
+ else if(!strcmp(cmdbuf.buf, "FALLBACK"))
+ return 0;
+ else
+ die("Unknown response to connect: %s",
+ cmdbuf.buf);
+
+ return 0; /* Shouldn't be here. */
+}
+
+static int process_connect(struct transport* transport,
+ int for_push)
+{
+ struct helper_data *data = transport->data;
+ const char *name;
+ const char *exec;
+
+ name = for_push ? "git-receive-pack" : "git-upload-pack";
+ if(for_push)
+ exec = data->gitoptions.receivepack;
+ else
+ exec = data->gitoptions.uploadpack;
+
+ return _process_connect(transport, name, exec);
+}
+
+static int connect_helper(struct transport *transport, const char *name,
+ const char *exec, int fd[2])
+{
+ struct helper_data *data = transport->data;
+
+ /* Get_helper so connect is inited. */
+ get_helper(transport);
+ if(!data->connect)
+ die("Operation not supported by protocol.");
+
+ if(!_process_connect(transport, name, exec))
+ die("Can't connect to subservice %s.", name);
+
+ fd[0] = data->helper->out;
+ fd[1] = data->helper->in;
+ return 0;
+}
+
static int fetch(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct helper_data *data = transport->data;
int i, count;
+ if(process_connect(transport, 0))
+ return TRANSPORT_LAYER6_READY;
+
count = 0;
for (i = 0; i < nr_heads; i++)
if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
@@ -364,6 +449,9 @@ static int push_refs(struct transport *transport,
struct child_process *helper;
struct ref *ref;
+ if(process_connect(transport, 1))
+ return TRANSPORT_LAYER6_READY;
+
if (!remote_refs)
return 0;
@@ -507,6 +595,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
helper = get_helper(transport);
+ if(process_connect(transport, for_push))
+ return &special_transport_layer6_ready;
+
if (data->push && for_push)
write_str_in_full(helper->in, "list for-push\n");
else
@@ -559,6 +650,7 @@ int transport_helper_init(struct transport *transport, const char *name)
transport->fetch = fetch;
transport->push_refs = push_refs;
transport->disconnect = release_helper;
+ transport->connect = connect_helper;
transport->disown = helper_disown;
transport->smart_options = &(data->gitoptions);
return 0;
diff --git a/transport.c b/transport.c
index 7e6ef2b..1488cfe 100644
--- a/transport.c
+++ b/transport.c
@@ -762,6 +762,17 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
return ret;
}
+static int connect_git(struct transport *transport, const char* name,
+ const char* executable, int fd[2])
+{
+ struct git_transport_data *data = transport->data;
+ data->conn = git_connect(data->fd, transport->url,
+ executable, 0);
+ fd[0] = data->fd[0];
+ fd[1] = data->fd[1];
+ return 0;
+}
+
static int disconnect_git(struct transport *transport)
{
struct git_transport_data *data = transport->data;
@@ -926,6 +937,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->get_refs_list = get_refs_via_connect;
ret->fetch = fetch_refs_via_pack;
ret->push_refs = git_transport_push;
+ ret->connect = connect_git;
ret->disconnect = disconnect_git;
ret->smart_options = &(data->options);
ret->disown = NULL;
@@ -1109,6 +1121,15 @@ void transport_unlock_pack(struct transport *transport)
}
}
+int transport_connect(struct transport *transport, const char *name,
+ const char* exec, int fd[2])
+{
+ if(transport->connect) {
+ return transport->connect(transport, name, exec, fd);
+ } else
+ die("Operation not supported by protocol");
+}
+
int transport_disconnect(struct transport *transport)
{
int ret = 0;
diff --git a/transport.h b/transport.h
index f3ee890..c86329a 100644
--- a/transport.h
+++ b/transport.h
@@ -64,6 +64,8 @@ struct transport {
**/
int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
+ int (*connect)(struct transport *connection, const char* name, const char* executable,
+ int fd[2]);
/**
* Disown the transport helper. Releases all resources used
@@ -143,6 +145,9 @@ void transport_unlock_pack(struct transport *transport);
int transport_disconnect(struct transport *transport);
char *transport_anonymize_url(const char *url);
+int transport_connect(struct transport *transport, const char *name,
+ const char* exec, int fd[2]);
+
/* Transport methods defined outside transport.c */
int transport_helper_init(struct transport *transport, const char *name);
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 5/8] Support remote archive from external protocol helpers
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
Helpers which support invoke/connect also should support remote archive
snapshot (or at least there's only one way to attempt it). So support
remote snapshotting for protocol helpers.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
builtin-archive.c | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/builtin-archive.c b/builtin-archive.c
index 12351e9..d34b3fd 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -5,6 +5,7 @@
#include "cache.h"
#include "builtin.h"
#include "archive.h"
+#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
#include "sideband.h"
@@ -25,12 +26,16 @@ static void create_output_file(const char *output_file)
static int run_remote_archiver(int argc, const char **argv,
const char *remote, const char *exec)
{
- char *url, buf[LARGE_PACKET_MAX];
+ char buf[LARGE_PACKET_MAX];
int fd[2], i, len, rv;
- struct child_process *conn;
+ struct transport *transport;
+ struct remote *_remote;
- url = xstrdup(remote);
- conn = git_connect(fd, url, exec, 0);
+ _remote = remote_get(remote);
+ if (!_remote->url[0])
+ die("git archive: Remote with no URL");
+ transport = transport_get(_remote, _remote->url[0]);
+ transport_connect(transport, "git-upload-archive", exec, fd);
for (i = 1; i < argc; i++)
packet_write(fd[1], "argument %s\n", argv[i]);
@@ -53,9 +58,7 @@ static int run_remote_archiver(int argc, const char **argv,
/* Now, start reading from fd[0] and spit it out to stdout */
rv = recv_sideband("archive", fd[0], 1);
- close(fd[0]);
- close(fd[1]);
- rv |= finish_connect(conn);
+ rv |= transport_disconnect(transport);
return !!rv;
}
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 6/8] Remove special casing of http, https and ftp
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
HTTP, HTTPS and FTP are no longer special to transport code. Also
add support for FTPS (curl supports it so it is easy).
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
.gitignore | 4 ++++
Makefile | 24 ++++++++++++++++++++++--
transport.c | 8 --------
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7cc54b4..7c79f97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,6 +107,10 @@
/git-relink
/git-remote
/git-remote-curl
+/git-remote-http
+/git-remote-https
+/git-remote-ftp
+/git-remote-ftps
/git-repack
/git-replace
/git-repo-config
diff --git a/Makefile b/Makefile
index 42744a4..1332225 100644
--- a/Makefile
+++ b/Makefile
@@ -424,6 +424,13 @@ BUILT_INS += git-stage$X
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
+#ifdef NO_CURL
+REMOTE_CURL_NAMES =
+#else
+# Yes, this is missing git-remote-http intentionally!
+REMOTE_CURL_NAMES = git-remote-https git-remote-ftp git-remote-ftps
+#endif
+
# what 'all' will build and 'install' will install in gitexecdir,
# excluding programs for built-in commands
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
@@ -1097,7 +1104,7 @@ else
else
CURL_LIBCURL = -lcurl
endif
- PROGRAMS += git-remote-curl$X git-http-fetch$X
+ PROGRAMS += git-remote-http$X git-remote-https$X git-remote-ftp$X git-remote-ftps$X git-http-fetch$X
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
@@ -1676,7 +1683,13 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
-git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+$(REMOTE_CURL_NAMES): git-remote-http$X
+ $(QUIET_LNCP)$(RM) $@ && \
+ ln $< $@ 2>/dev/null || \
+ ln -s $< $@ 2>/dev/null || \
+ cp $< $@
+
+git-remote-http$X: remote-curl.o http.o http-walker.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
@@ -1853,6 +1866,7 @@ endif
ifneq (,$X)
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
endif
+
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
{ test "$$bindir/" = "$$execdir/" || \
@@ -1866,6 +1880,12 @@ endif
ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
done; } && \
+ { for p in $(REMOTE_CURL_NAMES); do \
+ $(RM) "$$execdir/$$p" && \
+ ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
+ done; } && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
install-doc:
diff --git a/transport.c b/transport.c
index 1488cfe..872cc30 100644
--- a/transport.c
+++ b/transport.c
@@ -944,14 +944,6 @@ struct transport *transport_get(struct remote *remote, const char *url)
data->conn = NULL;
data->virtual_connected = 0;
- } else if (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
- /* These three are just plain special. */
- transport_helper_init(ret, "curl");
-#ifdef NO_CURL
- error("git was compiled without libcurl support.");
-#endif
} else {
/* Unknown protocol in URL. Pass to external handler. */
int len = external_specification_len(url);
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 7/8] Add remote helper debug mode
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
Remote helpers deadlock easily, so support debug mode which shows the
interaction steps.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 96 ++++++++++++++++++++++++++++++++++++----------------
1 files changed, 67 insertions(+), 29 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 21aa4ab..03920bb 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -8,6 +8,8 @@
#include "quote.h"
#include "remote.h"
+static int debug = 0;
+
struct helper_data
{
const char *name;
@@ -24,6 +26,46 @@ struct helper_data
struct git_transport_options gitoptions;
};
+static void sendline(struct helper_data *helper, struct strbuf *buffer)
+{
+ if(debug)
+ fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
+ if(write_in_full(helper->helper->in, buffer->buf, buffer->len)
+ != buffer->len) {
+ die_errno("Full write to remote helper failed");
+ }
+}
+
+static int recvline(struct helper_data *helper, struct strbuf *buffer)
+{
+ strbuf_reset(buffer);
+ if(debug)
+ fprintf(stderr, "Debug: Remote helper: Waiting...\n");
+ if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
+ if(debug)
+ fprintf(stderr, "Debug: Remote helper quit.\n");
+ exit(128);
+ }
+
+ if(debug)
+ fprintf(stderr, "Debug: Remote helper: <- %s\n", buffer->buf);
+ return 0;
+}
+
+static void xchgline(struct helper_data *helper, struct strbuf *buffer)
+{
+ sendline(helper, buffer);
+ recvline(helper, buffer);
+}
+
+static void write_constant(int fd, const char *str)
+{
+ if(debug)
+ fprintf(stderr, "Debug: Remote helper: -> %s", str);
+ if(write_in_full(fd, str, strlen(str)) != strlen(str))
+ die_errno("Full write to remote helper failed");
+}
+
static struct child_process* helper_disown(struct transport *transport)
{
struct helper_data *data = transport->data;
@@ -95,14 +137,14 @@ static struct child_process *get_helper(struct transport *transport)
data->out = xfdopen(duped, "r");
setvbuf(data->out, NULL, _IONBF, 0);
- write_str_in_full(helper->in, "capabilities\n");
+ write_constant(helper->in, "capabilities\n");
while (1) {
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!*buf.buf)
break;
+ if(debug) fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
if (!strcmp(buf.buf, "fetch"))
data->fetch = 1;
if (!strcmp(buf.buf, "option"))
@@ -130,14 +172,19 @@ static struct child_process *get_helper(struct transport *transport)
free(refspecs);
}
strbuf_release(&buf);
+ if(debug) fprintf(stderr, "Debug: Capabilities complete.\n");
return data->helper;
}
static int disconnect_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
+ struct strbuf buf = STRBUF_INIT;
+
if (data->helper) {
- write_str_in_full(data->helper->in, "\n");
+ if(debug) fprintf(stderr, "Debug: Disconnecting.\n");
+ strbuf_addf(&buf, "\n");
+ sendline(data, &buf);
close(data->helper->in);
close(data->helper->out);
fclose(data->out);
@@ -166,10 +213,11 @@ static int set_helper_option(struct transport *transport,
const char *name, const char *value)
{
struct helper_data *data = transport->data;
- struct child_process *helper = get_helper(transport);
struct strbuf buf = STRBUF_INIT;
int i, ret, is_bool = 0;
+ get_helper(transport);
+
if (!data->option)
return 1;
@@ -192,12 +240,7 @@ static int set_helper_option(struct transport *transport,
quote_c_style(value, &buf, NULL, 0);
strbuf_addch(&buf, '\n');
- if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
- die_errno("cannot send option to %s", data->name);
-
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ xchgline(data, &buf);
if (!strcmp(buf.buf, "ok"))
ret = 0;
@@ -257,13 +300,10 @@ static int fetch_with_fetch(struct transport *transport,
}
strbuf_addch(&buf, '\n');
- if (write_in_full(data->helper->in, buf.buf, buf.len) != buf.len)
- die_errno("cannot send fetch to %s", data->name);
+ sendline(data, &buf);
while (1) {
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!prefixcmp(buf.buf, "lock ")) {
const char *name = buf.buf + 5;
@@ -298,12 +338,13 @@ static int fetch_with_import(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct child_process fastimport;
- struct child_process *helper = get_helper(transport);
struct helper_data *data = transport->data;
int i;
struct ref *posn;
struct strbuf buf = STRBUF_INIT;
+ get_helper(transport);
+
if (get_importer(transport, &fastimport))
die("Couldn't run fast-import");
@@ -313,7 +354,7 @@ static int fetch_with_import(struct transport *transport,
continue;
strbuf_addf(&buf, "import %s\n", posn->name);
- write_in_full(helper->in, buf.buf, buf.len);
+ sendline(data, &buf);
strbuf_reset(&buf);
}
disconnect_helper(transport);
@@ -364,10 +405,7 @@ static int _process_connect(struct transport *transport,
} else
return 0;
- write_in_full(helper->in, cmdbuf.buf, cmdbuf.len);
- strbuf_reset(&cmdbuf);
- if (strbuf_getline(&cmdbuf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ xchgline(data, &cmdbuf);
if(!strcmp(cmdbuf.buf, ""))
return 1;
else if(!strcmp(cmdbuf.buf, "FALLBACK"))
@@ -500,17 +538,14 @@ static int push_refs(struct transport *transport,
}
strbuf_addch(&buf, '\n');
- if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
- exit(128);
+ sendline(data, &buf);
ref = remote_refs;
while (1) {
char *refname, *msg;
int status;
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!buf.len)
break;
@@ -605,8 +640,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
while (1) {
char *eov, *eon;
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!*buf.buf)
break;
@@ -631,6 +665,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
}
tail = &((*tail)->next);
}
+ if(debug) fprintf(stderr, "Debug: Read ref listing.\n");
strbuf_release(&buf);
for (posn = ret; posn; posn = posn->next)
@@ -644,6 +679,9 @@ int transport_helper_init(struct transport *transport, const char *name)
struct helper_data *data = xcalloc(sizeof(*data), 1);
data->name = name;
+ if(getenv("GIT_TRANSPORT_HELPER_DEBUG"))
+ debug = 1;
+
transport->data = data;
transport->set_option = set_helper_option;
transport->get_refs_list = get_refs_list;
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 8/8] Support mandatory capabilities
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
Add support for marking capability as mandatory for hosting git version
to understand. This is useful for helpers which require various types
of assistance from main git binary.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
Documentation/git-remote-helpers.txt | 5 ++++-
transport-helper.c | 29 ++++++++++++++++++++++-------
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 91cd9eb..6af6824 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -25,7 +25,10 @@ Commands are given by the caller on the helper's standard input, one per line.
'capabilities'::
Lists the capabilities of the helper, one per line, ending
- with a blank line.
+ with a blank line. Each capability may be preceeded with '*'.
+ This marks them mandatory for git version using the remote
+ helper to understand (unknown mandatory capability is fatal
+ error).
'list'::
Lists the refs, one per line, in the format "<value> <name>
diff --git a/transport-helper.c b/transport-helper.c
index 03920bb..9ddcdc3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -140,27 +140,42 @@ static struct child_process *get_helper(struct transport *transport)
write_constant(helper->in, "capabilities\n");
while (1) {
+ const char* capname;
+ int mandatory = 0;
recvline(data, &buf);
if (!*buf.buf)
break;
- if(debug) fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
- if (!strcmp(buf.buf, "fetch"))
+
+ if(*buf.buf == '*') {
+ capname = buf.buf + 1;
+ mandatory = 1;
+ } else
+ capname = buf.buf;
+
+ if(debug) fprintf(stderr, "Debug: Got cap %s\n", capname);
+ if (!strcmp(capname, "fetch"))
data->fetch = 1;
- if (!strcmp(buf.buf, "option"))
+ else if (!strcmp(capname, "option"))
data->option = 1;
- if (!strcmp(buf.buf, "push"))
+ else if (!strcmp(capname, "push"))
data->push = 1;
- if (!strcmp(buf.buf, "import"))
+ else if (!strcmp(capname, "import"))
data->import = 1;
- if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) {
+ else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
ALLOC_GROW(refspecs,
refspec_nr + 1,
refspec_alloc);
refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
}
- if (!strcmp(buf.buf, "connect"))
+ else if (!strcmp(capname, "connect"))
data->connect = 1;
+ else if (mandatory) {
+ fflush(stderr);
+ die("Unknown madatory capability %s. This remote "
+ "helper probably needs newer version of Git.\n",
+ capname);
+ }
}
if (refspecs) {
int i;
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* Re: [PATCH] git-gui: suppress the X error on exit
From: Shawn O. Pearce @ 2009-12-04 15:57 UTC (permalink / raw)
To: Jindrich Makovicka; +Cc: git
In-Reply-To: <20091204102844.3c720b21@starbug.prg01.itonis.net>
Jindrich Makovicka <makovick@gmail.com> wrote:
> Due to a bug in Tk, git-gui almost always (unless git-gui is closed
> right after starting) produces an X window error message on exit,
> something like
Thanks. I've wrapped it up into the following commit. Can I get
a Signed-off-by line from you?
--8<--
[PATCH] git-gui: suppress RenderBadPicture X error caused by Tk bug
Due to a bug in Tk, git-gui almost always (unless git-gui is closed
right after starting) produces an X window error message on exit,
something like:
X Error of failed request: RenderBadPicture (invalid Picture parameter)
Major opcode of failed request: 150 (RENDER)
Minor opcode of failed request: 7 (RenderFreePicture)
Picture id in failed request: 0x3a000dc
Serial number of failed request: 1965
Current serial number in output stream: 1980
Respective Tk bug report is here:
http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997
This bug is triggered only when the send command is blocked via
rename send {} . The following patch re-enables send just before
quiting git-gui to suppress the error.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
git-gui.sh | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 037a1f2..718277a 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -2052,6 +2052,11 @@ proc do_quit {{rc {1}}} {
}
set ret_code $rc
+
+ # Briefly enable send again, working around Tk bug
+ # http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997
+ tk appname [appname]
+
destroy .
}
--
1.6.6.rc0.324.gb5bf2
--
Shawn.
^ permalink raw reply related
* Re: [RFC PATCH v2 1/8] Pass unknown protocols to external protocol handlers
From: Sverre Rabbelier @ 2009-12-04 16:01 UTC (permalink / raw)
To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-4-git-send-email-ilari.liusvaara@elisanet.fi>
Heya,
On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> Change URL handling to allow external protocol handlers to implement
> new protocols without the '::' syntax if helper name does not conflict
> with any built-in protocol.
Haven't looked at the patch itself, but I like the idea, a lot.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [RFC PATCH v2 7/8] Add remote helper debug mode
From: Sverre Rabbelier @ 2009-12-04 16:03 UTC (permalink / raw)
To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-10-git-send-email-ilari.liusvaara@elisanet.fi>
Heya,
On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> Remote helpers deadlock easily, so support debug mode which shows the
> interaction steps.
You should move this to the beginning of the series, so that it can be
merged even if your other patches are not :).
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [RFC PATCH v2 6/8] Remove special casing of http, https and ftp
From: Sverre Rabbelier @ 2009-12-04 16:05 UTC (permalink / raw)
To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-9-git-send-email-ilari.liusvaara@elisanet.fi>
Heya,
On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> HTTP, HTTPS and FTP are no longer special to transport code. Also
> add support for FTPS (curl supports it so it is easy).
As I said earlier, I like this idea, again, without having looked at
the patch itself so I cannot comment on the implementation :).
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* git-blame.el: what is format-spec?
From: Sergei Organov @ 2009-12-04 16:21 UTC (permalink / raw)
To: git
Hello,
What is format-spec function in current git-blame.el? Neither my GNU
Emacs 22.2.1 nor Google knows anything about it.
-- Sergei.
^ permalink raw reply
* Re: git-blame.el: what is format-spec?
From: Andreas Schwab @ 2009-12-04 16:38 UTC (permalink / raw)
To: Sergei Organov; +Cc: git
In-Reply-To: <87vdgm3e1k.fsf@osv.gnss.ru>
Sergei Organov <osv@javad.com> writes:
> What is format-spec function in current git-blame.el? Neither my GNU
> Emacs 22.2.1 nor Google knows anything about it.
It's part of Emacs since more than 9 years, imported from Gnus.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: [PATCH 1/3] Better document the original repository layout.
From: Johannes Schindelin @ 2009-12-04 16:51 UTC (permalink / raw)
To: Michael J Gruber; +Cc: Michael Haggerty, git, gitster
In-Reply-To: <4B192210.908@drmicha.warpmail.net>
Hi,
On Fri, 4 Dec 2009, Michael J Gruber wrote:
> Michael Haggerty venit, vidit, dixit 04.12.2009 15:36:
> > Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> > ---
> > t/t3404-rebase-interactive.sh | 9 +++++----
> > 1 files changed, 5 insertions(+), 4 deletions(-)
> >
> > diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> > index 3a37793..073674f 100755
> > --- a/t/t3404-rebase-interactive.sh
> > +++ b/t/t3404-rebase-interactive.sh
> > @@ -16,13 +16,14 @@ set_fake_editor
> >
> > # set up two branches like this:
> > #
> > -# A - B - C - D - E
> > +# A - B - C - D - E (master)
> > # \
> > -# F - G - H
> > +# F - G - H (branch1)
> > # \
> > -# I
> > +# I (branch2)
> > #
> > -# where B, D and G touch the same file.
> > +# where B, D and G touch the same file. In addition, set tags at
> > +# points A, F, and I.
> >
> > test_expect_success 'setup' '
> > : > file1 &&
>
> My first reaction to the subject was "Huh? What repository?". So I
> suggest something like
>
> t3404: Better document the original repository layout
>
> as a more descriptive subject.
That would be good, the patch itself is already good.
ACK
^ permalink raw reply
* Re: [PATCH 2/3] Set a couple more tags in the original repository.
From: Johannes Schindelin @ 2009-12-04 16:52 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster
In-Reply-To: <5482fe5eb1141d925dd4df20cc00416e09813ff7.1259934977.git.mhagger@alum.mit.edu>
Hi,
On Fri, 4 Dec 2009, Michael Haggerty wrote:
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Alternatively, one could use the test_commit function, I guess. But the
patch is good as it is.
ACK.
^ permalink raw reply
* Re: [PATCH 3/3] Add a command "fix" to rebase --interactive.
From: Johannes Schindelin @ 2009-12-04 16:57 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster
In-Reply-To: <6d779d2c244bf5d5b7924cdc5daf66a8186e4bc7.1259934977.git.mhagger@alum.mit.edu>
Hi,
On Fri, 4 Dec 2009, Michael Haggerty wrote:
> The command is like "squash", except that it discards the commit message
> of the corresponding commit.
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
The only part which made me a bit uneasy was this one:
> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index 0bd3bf7..539413d 100755
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -302,7 +302,7 @@ nth_string () {
>
> make_squash_message () {
> if test -f "$SQUASH_MSG"; then
> - COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
> + COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)\(th\|st\|nd\|rd\) commit message.*:/\1/p" \
> < "$SQUASH_MSG" | sed -ne '$p')+1))
> echo "# This is a combination of $COUNT commits."
> sed -e 1d -e '2,/^./{
But it is fine. (Took this idiot a couple of seconds to figure out why;
I'd have put "th" last, being a mathematician instead of a computer
scientist, so my natural numbers start with 1, not 0 ;-)
To be honest, I never thought of "fix" as something I want, but patiently
deleted the respective commit messages of my fixup commits (usually called
"amend" or "amend.<something helpful>").
This is brilliant.
ACK
^ permalink raw reply
* Re: git gsoc money
From: Brandon Casey @ 2009-12-04 16:57 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20091204121417.GA20682@coredump.intra.peff.net>
Jeff King wrote:
> On Thu, Dec 03, 2009 at 07:39:35AM -0800, Shawn O. Pearce wrote:
>
>>> 1. Become an affiliated project of an organization like The Software
>>> Freedom Conservancy or Software in the Public Interest.
>> Try to join the Software Freedom Conservancy and retain the funds
>> for Git's use? Maybe you can slide in before the Dec 31st deadline.
>
> Everybody who responded seems to think that is a good idea, so I've
> contacted the SFC about joining. I'll keep the list up to date as things
> develop there.
>
> I expect they'll need a liaison from the project. I can do that, but if
> somebody else is interested, let me know.
Now that I've read the links that you mentioned, I too think this is a
good idea. I haven't been involved in SoC (though I benefited and much
appreciated having my travel expenses reimbursed), so my opinion should
be weighted accordingly.
If there's anything I can do to help, Jeff, please let me know.
-brandon
^ permalink raw reply
* Re: git-blame.el: what is format-spec?
From: Sergei Organov @ 2009-12-04 16:59 UTC (permalink / raw)
To: Andreas Schwab; +Cc: git
In-Reply-To: <m2fx7qae49.fsf@igel.home>
Andreas Schwab <schwab@linux-m68k.org> writes:
> Sergei Organov <osv@javad.com> writes:
>
>> What is format-spec function in current git-blame.el? Neither my GNU
>> Emacs 22.2.1 nor Google knows anything about it.
>
> It's part of Emacs since more than 9 years, imported from Gnus.
>
Thanks, I now see it in Gnus on my own computer, in
lisp/gnus/format-spec.el.gz.
GNU Emacs 22.2.1 (i486-pc-linux-gnu, GTK+ Version 2.12.11) of 2008-11-10
on raven, modified by Debian
However, isn't it a bad idea to require Gnus(!) for git-blame to run? Gnus
is not installed on our server where I've encountered the problem. Was
format-spec actually moved to core emacs recently?
-- Sergei.
^ permalink raw reply
* [PATCH v8 0/7] fast-import: add new feature and option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
This reroll addressess comments from Shawn and the fast-import
mailing list. It also adds a new feature, "relative-marks", which
will be very useful for remote helpers.
Apologies for taking so long with the reroll, hopefully this version
is good for next and I can finish my git-remote-hg work :).
Sverre Rabbelier (7):
fast-import: put option parsing code in separate functions
fast-import: put marks reading in it's own function
fast-import: add feature command
fast-import: add option command
fast-import: test the new option command
fast-import: allow for multiple --import-marks= arguments
fast-import: add (non-)relative-marks feature
Documentation/git-fast-import.txt | 79 +++++++++
fast-import.c | 317 +++++++++++++++++++++++++++----------
t/t9300-fast-import.sh | 152 ++++++++++++++++++
3 files changed, 462 insertions(+), 86 deletions(-)
^ permalink raw reply
* [PATCH v8 2/7] fast-import: put marks reading in it's own function
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-2-git-send-email-srabbelier@gmail.com>
All options do nothing but set settings, with the exception of the
--input-marks option. Delay the reading of the marks file till after
all options have been parsed.
Also, rename mark_file to export_marks_file as it is now ambiguous.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
Renamed mark_fiel to export_marks_file and added import_marks_file as
per Shawn's comments.
fast-import.c | 93 +++++++++++++++++++++++++++++++-------------------------
1 files changed, 51 insertions(+), 42 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index fcd9e1e..0458b03 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -318,7 +318,8 @@ static unsigned int object_entry_alloc = 5000;
static struct object_entry_pool *blocks;
static struct object_entry *object_table[1 << 16];
static struct mark_set *marks;
-static const char *mark_file;
+static const char *export_marks_file;
+static const char *import_marks_file;
/* Our last blob */
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -455,8 +456,8 @@ static void write_crash_report(const char *err)
fputc('\n', rpt);
fputs("Marks\n", rpt);
fputs("-----\n", rpt);
- if (mark_file)
- fprintf(rpt, " exported to %s\n", mark_file);
+ if (export_marks_file)
+ fprintf(rpt, " exported to %s\n", export_marks_file);
else
dump_marks_helper(rpt, 0, marks);
@@ -1603,13 +1604,13 @@ static void dump_marks(void)
int mark_fd;
FILE *f;
- if (!mark_file)
+ if (!export_marks_file)
return;
- mark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0);
+ mark_fd = hold_lock_file_for_update(&mark_lock, export_marks_file, 0);
if (mark_fd < 0) {
failure |= error("Unable to write marks file %s: %s",
- mark_file, strerror(errno));
+ export_marks_file, strerror(errno));
return;
}
@@ -1618,7 +1619,7 @@ static void dump_marks(void)
int saved_errno = errno;
rollback_lock_file(&mark_lock);
failure |= error("Unable to write marks file %s: %s",
- mark_file, strerror(saved_errno));
+ export_marks_file, strerror(saved_errno));
return;
}
@@ -1634,7 +1635,7 @@ static void dump_marks(void)
int saved_errno = errno;
rollback_lock_file(&mark_lock);
failure |= error("Unable to write marks file %s: %s",
- mark_file, strerror(saved_errno));
+ export_marks_file, strerror(saved_errno));
return;
}
@@ -1642,11 +1643,47 @@ static void dump_marks(void)
int saved_errno = errno;
rollback_lock_file(&mark_lock);
failure |= error("Unable to commit marks file %s: %s",
- mark_file, strerror(saved_errno));
+ export_marks_file, strerror(saved_errno));
return;
}
}
+static void read_marks(void)
+{
+ char line[512];
+ FILE *f = fopen(import_marks_file, "r");
+ if (!f)
+ die_errno("cannot read '%s'", import_marks_file);
+ while (fgets(line, sizeof(line), f)) {
+ uintmax_t mark;
+ char *end;
+ unsigned char sha1[20];
+ struct object_entry *e;
+
+ end = strchr(line, '\n');
+ if (line[0] != ':' || !end)
+ die("corrupt mark line: %s", line);
+ *end = 0;
+ mark = strtoumax(line + 1, &end, 10);
+ if (!mark || end == line + 1
+ || *end != ' ' || get_sha1(end + 1, sha1))
+ die("corrupt mark line: %s", line);
+ e = find_object(sha1);
+ if (!e) {
+ enum object_type type = sha1_object_info(sha1, NULL);
+ if (type < 0)
+ die("object not found: %s", sha1_to_hex(sha1));
+ e = insert_object(sha1);
+ e->type = type;
+ e->pack_id = MAX_PACK_ID;
+ e->offset = 1; /* just not zero! */
+ }
+ insert_mark(mark, e);
+ }
+ fclose(f);
+}
+
+
static int read_next_command(void)
{
static int stdin_eof = 0;
@@ -2421,39 +2458,9 @@ static void parse_progress(void)
skip_optional_lf();
}
-static void option_import_marks(const char *input_file)
+static void option_import_marks(const char *marks)
{
- char line[512];
- FILE *f = fopen(input_file, "r");
- if (!f)
- die_errno("cannot read '%s'", input_file);
- while (fgets(line, sizeof(line), f)) {
- uintmax_t mark;
- char *end;
- unsigned char sha1[20];
- struct object_entry *e;
-
- end = strchr(line, '\n');
- if (line[0] != ':' || !end)
- die("corrupt mark line: %s", line);
- *end = 0;
- mark = strtoumax(line + 1, &end, 10);
- if (!mark || end == line + 1
- || *end != ' ' || get_sha1(end + 1, sha1))
- die("corrupt mark line: %s", line);
- e = find_object(sha1);
- if (!e) {
- enum object_type type = sha1_object_info(sha1, NULL);
- if (type < 0)
- die("object not found: %s", sha1_to_hex(sha1));
- e = insert_object(sha1);
- e->type = type;
- e->pack_id = MAX_PACK_ID;
- e->offset = 1; /* just not zero! */
- }
- insert_mark(mark, e);
- }
- fclose(f);
+ import_marks_file = xstrdup(marks);
}
static void option_date_format(const char *fmt)
@@ -2487,7 +2494,7 @@ static void option_active_branches(const char *branches)
static void option_export_marks(const char *marks)
{
- mark_file = xstrdup(marks);
+ export_marks_file = xstrdup(marks);
}
static void option_export_pack_edges(const char *edges)
@@ -2581,6 +2588,8 @@ int main(int argc, const char **argv)
}
if (i != argc)
usage(fast_import_usage);
+ if (import_marks_file)
+ read_marks();
rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
for (i = 0; i < (cmd_save - 1); i++)
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 1/7] fast-import: put option parsing code in separate functions
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-1-git-send-email-srabbelier@gmail.com>
Putting the options in their own functions increases readability of
the option parsing block and makes it easier to reuse the option
parsing code later on.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
Rebased against current master, no other changes.
fast-import.c | 115 +++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 75 insertions(+), 40 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index dd3c99d..fcd9e1e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -295,6 +295,7 @@ static unsigned long branch_count;
static unsigned long branch_load_count;
static int failure;
static FILE *pack_edges;
+static unsigned int show_stats = 1;
/* Memory pools */
static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -2420,7 +2421,7 @@ static void parse_progress(void)
skip_optional_lf();
}
-static void import_marks(const char *input_file)
+static void option_import_marks(const char *input_file)
{
char line[512];
FILE *f = fopen(input_file, "r");
@@ -2455,6 +2456,76 @@ static void import_marks(const char *input_file)
fclose(f);
}
+static void option_date_format(const char *fmt)
+{
+ if (!strcmp(fmt, "raw"))
+ whenspec = WHENSPEC_RAW;
+ else if (!strcmp(fmt, "rfc2822"))
+ whenspec = WHENSPEC_RFC2822;
+ else if (!strcmp(fmt, "now"))
+ whenspec = WHENSPEC_NOW;
+ else
+ die("unknown --date-format argument %s", fmt);
+}
+
+static void option_max_pack_size(const char *packsize)
+{
+ max_packsize = strtoumax(packsize, NULL, 0) * 1024 * 1024;
+}
+
+static void option_depth(const char *depth)
+{
+ max_depth = strtoul(depth, NULL, 0);
+ if (max_depth > MAX_DEPTH)
+ die("--depth cannot exceed %u", MAX_DEPTH);
+}
+
+static void option_active_branches(const char *branches)
+{
+ max_active_branches = strtoul(branches, NULL, 0);
+}
+
+static void option_export_marks(const char *marks)
+{
+ mark_file = xstrdup(marks);
+}
+
+static void option_export_pack_edges(const char *edges)
+{
+ if (pack_edges)
+ fclose(pack_edges);
+ pack_edges = fopen(edges, "a");
+ if (!pack_edges)
+ die_errno("Cannot open '%s'", edges);
+}
+
+static void parse_one_option(const char *option)
+{
+ if (!prefixcmp(option, "date-format=")) {
+ option_date_format(option + 12);
+ } else if (!prefixcmp(option, "max-pack-size=")) {
+ option_max_pack_size(option + 14);
+ } else if (!prefixcmp(option, "depth=")) {
+ option_depth(option + 6);
+ } else if (!prefixcmp(option, "active-branches=")) {
+ option_active_branches(option + 16);
+ } else if (!prefixcmp(option, "import-marks=")) {
+ option_import_marks(option + 13);
+ } else if (!prefixcmp(option, "export-marks=")) {
+ option_export_marks(option + 13);
+ } else if (!prefixcmp(option, "export-pack-edges=")) {
+ option_export_pack_edges(option + 18);
+ } else if (!prefixcmp(option, "force")) {
+ force_update = 1;
+ } else if (!prefixcmp(option, "quiet")) {
+ show_stats = 0;
+ } else if (!prefixcmp(option, "stats")) {
+ show_stats = 1;
+ } else {
+ die("Unsupported option: %s", option);
+ }
+}
+
static int git_pack_config(const char *k, const char *v, void *cb)
{
if (!strcmp(k, "pack.depth")) {
@@ -2481,7 +2552,7 @@ static const char fast_import_usage[] =
int main(int argc, const char **argv)
{
- unsigned int i, show_stats = 1;
+ unsigned int i;
git_extract_argv0_path(argv[0]);
@@ -2505,44 +2576,8 @@ int main(int argc, const char **argv)
if (*a != '-' || !strcmp(a, "--"))
break;
- else if (!prefixcmp(a, "--date-format=")) {
- const char *fmt = a + 14;
- if (!strcmp(fmt, "raw"))
- whenspec = WHENSPEC_RAW;
- else if (!strcmp(fmt, "rfc2822"))
- whenspec = WHENSPEC_RFC2822;
- else if (!strcmp(fmt, "now"))
- whenspec = WHENSPEC_NOW;
- else
- die("unknown --date-format argument %s", fmt);
- }
- else if (!prefixcmp(a, "--max-pack-size="))
- max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
- else if (!prefixcmp(a, "--depth=")) {
- max_depth = strtoul(a + 8, NULL, 0);
- if (max_depth > MAX_DEPTH)
- die("--depth cannot exceed %u", MAX_DEPTH);
- }
- else if (!prefixcmp(a, "--active-branches="))
- max_active_branches = strtoul(a + 18, NULL, 0);
- else if (!prefixcmp(a, "--import-marks="))
- import_marks(a + 15);
- else if (!prefixcmp(a, "--export-marks="))
- mark_file = a + 15;
- else if (!prefixcmp(a, "--export-pack-edges=")) {
- if (pack_edges)
- fclose(pack_edges);
- pack_edges = fopen(a + 20, "a");
- if (!pack_edges)
- die_errno("Cannot open '%s'", a + 20);
- } else if (!strcmp(a, "--force"))
- force_update = 1;
- else if (!strcmp(a, "--quiet"))
- show_stats = 0;
- else if (!strcmp(a, "--stats"))
- show_stats = 1;
- else
- die("unknown option %s", a);
+
+ parse_one_option(a + 2);
}
if (i != argc)
usage(fast_import_usage);
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 3/7] fast-import: add feature command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-3-git-send-email-srabbelier@gmail.com>
This allows the fronted to require a specific feature to be supported
by the frontend, or abort.
Also add support for four initial feature, date-format=, force=,
import-marks=, export-marks=.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
Updated documentation, reject feature commands after a data command,
as per Shawn's comments. Also factor out parse_one_feature from
parse_feature so that we can re-use it in patch 4/7.
This also has the previous 4/6 squashed in (which added tests)
Documentation/git-fast-import.txt | 25 +++++++++++++
fast-import.c | 38 ++++++++++++++++++++
t/t9300-fast-import.sh | 70 +++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 288032c..4357c21 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -303,6 +303,10 @@ and control the current import process. More detailed discussion
standard output. This command is optional and is not needed
to perform an import.
+`feature`::
+ Require that fast-import supports the specified feature, or
+ abort if it does not.
+
`commit`
~~~~~~~~
Create or update a branch with a new commit, recording one logical
@@ -846,6 +850,27 @@ Placing a `progress` command immediately after a `checkpoint` will
inform the reader when the `checkpoint` has been completed and it
can safely access the refs that fast-import updated.
+`feature`
+~~~~~~~~~
+Require that fast-import supports the specified feature, or abort if
+it does not.
+
+....
+ 'feature' SP <feature> LF
+....
+
+The <feature> part of the command may be any string matching
+^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.
+
+Feature work identical as their option counterparts.
+
+The following features are currently supported:
+
+* date-format
+* import-marks
+* export-marks
+* force
+
Crash Reports
-------------
If fast-import is supplied invalid input it will terminate with a
diff --git a/fast-import.c b/fast-import.c
index 0458b03..ce0cd4e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -353,6 +353,7 @@ static struct recent_command *rc_free;
static unsigned int cmd_save = 100;
static uintmax_t next_mark;
static struct strbuf new_data = STRBUF_INIT;
+static int seen_data_command;
static void write_branch_report(FILE *rpt, struct branch *b)
{
@@ -1704,6 +1705,11 @@ static int read_next_command(void)
if (stdin_eof)
return EOF;
+ if (!seen_data_command
+ && prefixcmp(command_buf.buf, "feature ")) {
+ seen_data_command = 1;
+ }
+
rc = rc_free;
if (rc)
rc_free = rc->next;
@@ -2533,6 +2539,36 @@ static void parse_one_option(const char *option)
}
}
+static int parse_one_feature(const char *feature)
+{
+ if (!prefixcmp(feature, "date-format=")) {
+ option_date_format(feature + 12);
+ } else if (!prefixcmp(feature, "import-marks=")) {
+ option_import_marks(feature + 13);
+ } else if (!prefixcmp(feature, "export-marks=")) {
+ option_export_marks(feature + 13);
+ } else if (!prefixcmp(feature, "force")) {
+ force_update = 1;
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void parse_feature(void)
+{
+ char *feature = command_buf.buf + 8;
+
+ if (seen_data_command)
+ die("Got feature command '%s' after data command", feature);
+
+ if (parse_one_feature(feature))
+ return;
+
+ die("This version of fast-import does not support feature %s.", feature);
+}
+
static int git_pack_config(const char *k, const char *v, void *cb)
{
if (!strcmp(k, "pack.depth")) {
@@ -2612,6 +2648,8 @@ int main(int argc, const char **argv)
parse_checkpoint();
else if (!prefixcmp(command_buf.buf, "progress "))
parse_progress();
+ else if (!prefixcmp(command_buf.buf, "feature "))
+ parse_feature();
else
die("Unsupported command: %s", command_buf.buf);
}
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b49815d..b2c521f 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1254,4 +1254,74 @@ test_expect_success \
'Q: verify note for third commit' \
'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
+###
+### series R (feature)
+###
+
+cat >input <<EOF
+feature no-such-feature-exists
+EOF
+
+test_expect_success 'R: abort on unsupported feature' '
+ test_must_fail git fast-import <input
+'
+
+cat >input <<EOF
+feature date-format=now
+EOF
+
+test_expect_success 'R: supported feature is accepted' '
+ git fast-import <input
+'
+
+cat >input << EOF
+blob
+data 3
+hi
+feature date-format=now
+EOF
+
+test_expect_success 'R: abort on receiving feature after data command' '
+ test_must_fail git fast-import <input
+'
+
+cat >input << EOF
+feature export-marks=git.marks
+blob
+mark :1
+data 3
+hi
+
+EOF
+
+test_expect_success \
+ 'R: export-marks feature results in a marks file being created' \
+ 'cat input | git fast-import &&
+ grep :1 git.marks'
+
+test_expect_success \
+ 'R: export-marks options can be overriden by commandline options' \
+ 'cat input | git fast-import --export-marks=other.marks &&
+ grep :1 other.marks'
+
+cat >input << EOF
+feature import-marks=marks.out
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+ 'R: import to output marks works without any content' \
+ 'cat input | git fast-import &&
+ test_cmp marks.out marks.new'
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+ 'R: import marks prefers commandline marks file over the stream' \
+ 'cat input | git fast-import --import-marks=marks.out &&
+ test_cmp marks.out marks.new'
+
test_done
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 4/7] fast-import: add option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-4-git-send-email-srabbelier@gmail.com>
This allows the frontend to specify any of the supported options as
long as no non-option command has been given. This way the
user does not have to include any frontend-specific options, but
instead she can rely on the frontend to tell fast-import what it
needs.
Also factor out parsing of argv and have it execute when we reach the
first non-option command, or after all commands have been read and
no non-option command has been encountered.
Non-git options are ignored, unrecognised options result in an error.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
Reject unknown options, update documentation, and some style fixes.
Documentation/git-fast-import.txt | 32 +++++++++++++
fast-import.c | 87 ++++++++++++++++++++++++++-----------
2 files changed, 94 insertions(+), 25 deletions(-)
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 4357c21..2d5f533 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -307,6 +307,11 @@ and control the current import process. More detailed discussion
Require that fast-import supports the specified feature, or
abort if it does not.
+`option`::
+ Specify any of the options listed under OPTIONS that do not
+ change stream semantic to suit the frontend's needs. This
+ command is optional and is not needed to perform an import.
+
`commit`
~~~~~~~~
Create or update a branch with a new commit, recording one logical
@@ -871,6 +876,33 @@ The following features are currently supported:
* export-marks
* force
+`option`
+~~~~~~~~
+Processes the specified option so that git fast-import behaves in a
+way that suits the frontend's needs.
+Note that options specified by the frontend are overridden by any
+options the user may specify to git fast-import itself.
+
+....
+ 'option' SP <option> LF
+....
+
+The `<option>` part of the command may contain any of the options
+listed in the OPTIONS section that do not change import semantics,
+without the leading '--' and is treated in the same way.
+
+Option commands must be the first commands on the input (not counting
+feature commands), to give an option command after any non-option
+command is an error.
+
+The following commandline options change import semantics and may therefore
+not be passed as option:
+
+* date-format
+* import-marks
+* export-marks
+* force
+
Crash Reports
-------------
If fast-import is supplied invalid input it will terminate with a
diff --git a/fast-import.c b/fast-import.c
index ce0cd4e..ab099b6 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -296,6 +296,8 @@ static unsigned long branch_load_count;
static int failure;
static FILE *pack_edges;
static unsigned int show_stats = 1;
+static int global_argc;
+static const char **global_argv;
/* Memory pools */
static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -355,6 +357,8 @@ static uintmax_t next_mark;
static struct strbuf new_data = STRBUF_INIT;
static int seen_data_command;
+static void parse_argv(void);
+
static void write_branch_report(FILE *rpt, struct branch *b)
{
fprintf(rpt, "%s:\n", b->name);
@@ -1706,8 +1710,9 @@ static int read_next_command(void)
return EOF;
if (!seen_data_command
- && prefixcmp(command_buf.buf, "feature ")) {
- seen_data_command = 1;
+ && prefixcmp(command_buf.buf, "feature ")
+ && prefixcmp(command_buf.buf, "option ")) {
+ parse_argv();
}
rc = rc_free;
@@ -2512,31 +2517,25 @@ static void option_export_pack_edges(const char *edges)
die_errno("Cannot open '%s'", edges);
}
-static void parse_one_option(const char *option)
+static int parse_one_option(const char *option)
{
- if (!prefixcmp(option, "date-format=")) {
- option_date_format(option + 12);
- } else if (!prefixcmp(option, "max-pack-size=")) {
+ if (!prefixcmp(option, "max-pack-size=")) {
option_max_pack_size(option + 14);
} else if (!prefixcmp(option, "depth=")) {
option_depth(option + 6);
} else if (!prefixcmp(option, "active-branches=")) {
option_active_branches(option + 16);
- } else if (!prefixcmp(option, "import-marks=")) {
- option_import_marks(option + 13);
- } else if (!prefixcmp(option, "export-marks=")) {
- option_export_marks(option + 13);
} else if (!prefixcmp(option, "export-pack-edges=")) {
option_export_pack_edges(option + 18);
- } else if (!prefixcmp(option, "force")) {
- force_update = 1;
} else if (!prefixcmp(option, "quiet")) {
show_stats = 0;
} else if (!prefixcmp(option, "stats")) {
show_stats = 1;
} else {
- die("Unsupported option: %s", option);
+ return 0;
}
+
+ return 1;
}
static int parse_one_feature(const char *feature)
@@ -2569,6 +2568,19 @@ static void parse_feature(void)
die("This version of fast-import does not support feature %s.", feature);
}
+static void parse_option(void)
+{
+ char *option = command_buf.buf + 11;
+
+ if (seen_data_command)
+ die("Got option command '%s' after data command", option);
+
+ if (parse_one_option(option))
+ return;
+
+ die("This version of fast-import does not support option: %s", option);
+}
+
static int git_pack_config(const char *k, const char *v, void *cb)
{
if (!strcmp(k, "pack.depth")) {
@@ -2593,6 +2605,32 @@ static int git_pack_config(const char *k, const char *v, void *cb)
static const char fast_import_usage[] =
"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
+static void parse_argv(void)
+{
+ unsigned int i;
+
+ for (i = 1; i < global_argc; i++) {
+ const char *a = global_argv[i];
+
+ if (*a != '-' || !strcmp(a, "--"))
+ break;
+
+ if (parse_one_option(a + 2))
+ continue;
+
+ if (parse_one_feature(a + 2))
+ continue;
+
+ die("unknown option %s", a);
+ }
+ if (i != global_argc)
+ usage(fast_import_usage);
+
+ seen_data_command = 1;
+ if (import_marks_file)
+ read_marks();
+}
+
int main(int argc, const char **argv)
{
unsigned int i;
@@ -2614,18 +2652,8 @@ int main(int argc, const char **argv)
avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
marks = pool_calloc(1, sizeof(struct mark_set));
- for (i = 1; i < argc; i++) {
- const char *a = argv[i];
-
- if (*a != '-' || !strcmp(a, "--"))
- break;
-
- parse_one_option(a + 2);
- }
- if (i != argc)
- usage(fast_import_usage);
- if (import_marks_file)
- read_marks();
+ global_argc = argc;
+ global_argv = argv;
rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
for (i = 0; i < (cmd_save - 1); i++)
@@ -2650,9 +2678,18 @@ int main(int argc, const char **argv)
parse_progress();
else if (!prefixcmp(command_buf.buf, "feature "))
parse_feature();
+ else if (!prefixcmp(command_buf.buf, "option git "))
+ parse_option();
+ else if (!prefixcmp(command_buf.buf, "option "))
+ /* ignore non-git options*/;
else
die("Unsupported command: %s", command_buf.buf);
}
+
+ /* argv hasn't been parsed yet, do so */
+ if (!seen_data_command)
+ parse_argv();
+
end_packfile();
dump_branches();
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 5/7] fast-import: test the new option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-5-git-send-email-srabbelier@gmail.com>
Test the quiet option and verify that the commandline options
override it.
Also make sure that an unknown option command is rejected and that
non-git options are ignored.
Lastly, show that unknown options are rejected when parsed on the
commandline.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
Tests updated to match the new behavior.
t/t9300-fast-import.sh | 37 ++++++++++++++++++++++++++++++++++++-
1 files changed, 36 insertions(+), 1 deletions(-)
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b2c521f..74dff11 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1255,7 +1255,7 @@ test_expect_success \
'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
###
-### series R (feature)
+### series R (feature and option)
###
cat >input <<EOF
@@ -1324,4 +1324,39 @@ test_expect_success \
'cat input | git fast-import --import-marks=marks.out &&
test_cmp marks.out marks.new'
+cat >input << EOF
+option git quiet
+blob
+data 3
+hi
+
+EOF
+
+touch empty
+
+test_expect_success 'R: quiet option results in no stats being output' '
+ cat input | git fast-import 2> output &&
+ test_cmp empty output
+'
+
+cat >input <<EOF
+option git non-existing-option
+EOF
+
+test_expect_success 'R: die on unknown option' '
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'R: unknown commandline options are rejected' '\
+ test_must_fail git fast-import --non-existing-option < /dev/null
+'
+
+cat >input <<EOF
+option non-existing-vcs non-existing-option
+EOF
+
+test_expect_success 'R: ignore non-git options' '
+ git fast-import <input
+'
+
test_done
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 6/7] fast-import: allow for multiple --import-marks= arguments
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-6-git-send-email-srabbelier@gmail.com>
The --import-marks= option may be specified multiple times on the
commandline and should result in all marks being read in. Only one
import-marks feature may be specified in the stream, which is
overriden by any --import-marks= commandline options.
If one wishes to specify import-marks files in addition to the one
specified in the stream, it is easy to repeat the stream option as a
--import-marks= commandline option.
Also verify this behavior with tests.
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
New in this series. Without this it is no longer possible to specify
multiple --import-marks= options on the commandline.
Documentation/git-fast-import.txt | 8 +++++++-
fast-import.c | 21 ++++++++++++++++-----
t/t9300-fast-import.sh | 22 ++++++++++++++++++++++
3 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 2d5f533..752f85c 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -867,7 +867,8 @@ it does not.
The <feature> part of the command may be any string matching
^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.
-Feature work identical as their option counterparts.
+Feature work identical as their option counterparts with the
+exception of the import-marks feature, see below.
The following features are currently supported:
@@ -876,6 +877,11 @@ The following features are currently supported:
* export-marks
* force
+The import-marks behaves differently from when it is specified as
+commandline option in that only one "feature import-marks" is allowed
+per stream. Also, any --import-marks= specified on the commandline
+will override those from the stream (if any).
+
`option`
~~~~~~~~
Processes the specified option so that git fast-import behaves in a
diff --git a/fast-import.c b/fast-import.c
index ab099b6..4c3406e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -322,6 +322,7 @@ static struct object_entry *object_table[1 << 16];
static struct mark_set *marks;
static const char *export_marks_file;
static const char *import_marks_file;
+static int import_marks_file_from_stream;
/* Our last blob */
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -2469,9 +2470,19 @@ static void parse_progress(void)
skip_optional_lf();
}
-static void option_import_marks(const char *marks)
+static void option_import_marks(const char *marks, int from_stream)
{
+ if (import_marks_file) {
+ if (from_stream)
+ die("Only one import-marks command allowed per stream");
+
+ /* read previous mark file */
+ if(!import_marks_file_from_stream)
+ read_marks();
+ }
+
import_marks_file = xstrdup(marks);
+ import_marks_file_from_stream = from_stream;
}
static void option_date_format(const char *fmt)
@@ -2538,12 +2549,12 @@ static int parse_one_option(const char *option)
return 1;
}
-static int parse_one_feature(const char *feature)
+static int parse_one_feature(const char *feature, int from_stream)
{
if (!prefixcmp(feature, "date-format=")) {
option_date_format(feature + 12);
} else if (!prefixcmp(feature, "import-marks=")) {
- option_import_marks(feature + 13);
+ option_import_marks(feature + 13, from_stream);
} else if (!prefixcmp(feature, "export-marks=")) {
option_export_marks(feature + 13);
} else if (!prefixcmp(feature, "force")) {
@@ -2562,7 +2573,7 @@ static void parse_feature(void)
if (seen_data_command)
die("Got feature command '%s' after data command", feature);
- if (parse_one_feature(feature))
+ if (parse_one_feature(feature, 1))
return;
die("This version of fast-import does not support feature %s.", feature);
@@ -2618,7 +2629,7 @@ static void parse_argv(void)
if (parse_one_option(a + 2))
continue;
- if (parse_one_feature(a + 2))
+ if (parse_one_feature(a + 2, 0))
continue;
die("unknown option %s", a);
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 74dff11..ba92775 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1286,6 +1286,15 @@ test_expect_success 'R: abort on receiving feature after data command' '
'
cat >input << EOF
+feature import-marks=git.marks
+feature import-marks=git2.marks
+EOF
+
+test_expect_success 'R: only one import-marks feature allowed per stream' '
+ test_must_fail git fast-import <input
+'
+
+cat >input << EOF
feature export-marks=git.marks
blob
mark :1
@@ -1324,6 +1333,19 @@ test_expect_success \
'cat input | git fast-import --import-marks=marks.out &&
test_cmp marks.out marks.new'
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=combined.marks
+EOF
+
+test_expect_success 'R: multiple --import-marks= should be honoured' '
+ head -n2 marks.out > one.marks &&
+ tail -n +3 marks.out > two.marks &&
+ git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
+ test_cmp marks.out combined.marks
+'
+
cat >input << EOF
option git quiet
blob
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* [PATCH v8 7/7] fast-import: add (non-)relative-marks feature
From: Sverre Rabbelier @ 2009-12-04 17:07 UTC (permalink / raw)
To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
vcs-fast-import-devs
Cc: Sverre Rabbelier, Daniel Barkalow
In-Reply-To: <1259946420-8845-7-git-send-email-srabbelier@gmail.com>
After specifying 'feature relative-marks' the paths specified with
'feature import-marks' and 'feature export-marks' are relative to an
internal directory in the current repository.
In git-fast-import this means that the paths are relative to the
'.git/info/fast-import' directory. However, other importers may use a
different location.
Add 'feature non-relative-marks' to disable this behavior, this way
it is possible to, for example, specify the import-marks location as
relative, and the export-marks location as non-relative.
Also add tests to verify this behavior.
Cc: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---
As requested by Daniel, it is now possible to have the marks be
relative to a constant directory. We might want to consider making
this the default at some point.
This patch opens the way for remote-helpers to use the marks feature
without poluting the work tree, which I think is very important.
Documentation/git-fast-import.txt | 16 ++++++++++++++++
fast-import.c | 19 +++++++++++++++++--
t/t9300-fast-import.sh | 25 +++++++++++++++++++++++++
3 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 752f85c..1a63835 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -75,6 +75,20 @@ OPTIONS
set of marks. If a mark is defined to different values,
the last file wins.
+--relative-marks::
+ After specifying --relative-marks= the paths specified
+ with --import-marks= and --export-marks= are relative
+ to an internal directory in the current repository.
+ In git-fast-import this means that the paths are relative
+ to the .git/info/fast-import directory. However, other
+ importers may use a different location.
+
+--no-relative-marks::
+ Negates a previous --relative-marks. Allows for combining
+ relative and non-relative marks by interweaving
+ --(no-)-relative-marks= with the --(import|export)-marks=
+ options.
+
--export-pack-edges=<file>::
After creating a packfile, print a line of data to
<file> listing the filename of the packfile and the last
@@ -875,6 +889,8 @@ The following features are currently supported:
* date-format
* import-marks
* export-marks
+* relative-marks
+* no-relative-marks
* force
The import-marks behaves differently from when it is specified as
diff --git a/fast-import.c b/fast-import.c
index 4c3406e..8d50a1e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -323,6 +323,7 @@ static struct mark_set *marks;
static const char *export_marks_file;
static const char *import_marks_file;
static int import_marks_file_from_stream;
+static int relative_marks_paths;
/* Our last blob */
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -2470,6 +2471,16 @@ static void parse_progress(void)
skip_optional_lf();
}
+static char* make_fast_import_path(const char *path)
+{
+ if (!relative_marks_paths || is_absolute_path(path))
+ return xstrdup(path);
+
+ struct strbuf abs_path = STRBUF_INIT;
+ strbuf_addf(&abs_path, "%s/info/fast-import/%s", get_git_dir(), path);
+ return strbuf_detach(&abs_path, NULL);
+}
+
static void option_import_marks(const char *marks, int from_stream)
{
if (import_marks_file) {
@@ -2481,7 +2492,7 @@ static void option_import_marks(const char *marks, int from_stream)
read_marks();
}
- import_marks_file = xstrdup(marks);
+ import_marks_file = make_fast_import_path(marks);
import_marks_file_from_stream = from_stream;
}
@@ -2516,7 +2527,7 @@ static void option_active_branches(const char *branches)
static void option_export_marks(const char *marks)
{
- export_marks_file = xstrdup(marks);
+ export_marks_file = make_fast_import_path(marks);
}
static void option_export_pack_edges(const char *edges)
@@ -2557,6 +2568,10 @@ static int parse_one_feature(const char *feature, int from_stream)
option_import_marks(feature + 13, from_stream);
} else if (!prefixcmp(feature, "export-marks=")) {
option_export_marks(feature + 13);
+ } else if (!prefixcmp(feature, "relative-marks")) {
+ relative_marks_paths = 1;
+ } else if (!prefixcmp(feature, "no-relative-marks")) {
+ relative_marks_paths = 0;
} else if (!prefixcmp(feature, "force")) {
force_update = 1;
} else {
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index ba92775..a1b8c2b 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1346,6 +1346,31 @@ test_expect_success 'R: multiple --import-marks= should be honoured' '
test_cmp marks.out combined.marks
'
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature export-marks=relative.out
+EOF
+
+test_expect_success 'R: feature relative-marks should be honoured' '
+ mkdir -p .git/info/fast-import/ &&
+ cp marks.new .git/info/fast-import/relative.in &&
+ git fast-import <input &&
+ test_cmp marks.new .git/info/fast-import/relative.out
+'
+
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature no-relative-marks
+feature export-marks=non-relative.out
+EOF
+
+test_expect_success 'R: feature no-relative-marks should be honoured' '
+ git fast-import <input &&
+ test_cmp marks.new non-relative.out
+'
+
cat >input << EOF
option git quiet
blob
--
1.6.5.3.164.g07b0c
^ permalink raw reply related
* Re: [ANNOUNCE] Git 1.6.5.4
From: Junio C Hamano @ 2009-12-04 17:10 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Todd Zullinger, Michael J Gruber, git
In-Reply-To: <m2r5rb9hes.fsf@igel.home>
Andreas Schwab <schwab@linux-m68k.org> writes:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> I think it depends on the likelihood that a distro has xmlto so old that
>> it does not understand --stringparam yet it uses stylesheet so new that
>> setting the parameter makes a positive difference (either it gives the
>> full URL or at least squelches the "You should define the parameter"
>> noise) in the output.
>
> openSUSE 11.2, for example. Its xmlto has a non-standard --xsltopts
> option that passes its argument down to xsltproc.
Ok, as I said that I've been wrong before in this area ;-)
I don't think I will have much time for git today, and it would be
appreciated if somebody can work on this and send a tested patch that
applies cleanly on top of 'maint' to implement the @@MAN_BASE_URL@@
replacement from manpage-base.xsl.in to manpage-base.xsl as Todd suggested
earlier.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox