* [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 3/8] Support taking over 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>
Add support for taking over transports that turn out to be smart.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 12 +++++++
transport.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++----
transport.h | 15 +++++++++
3 files changed, 109 insertions(+), 7 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index d3aad5c..5d17fb5 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -20,8 +20,18 @@ struct helper_data
/* These go from remote name (as in "list") to private name */
struct refspec *refspecs;
int refspec_nr;
+ struct git_transport_options gitoptions;
};
+static struct child_process* helper_disown(struct transport *transport)
+{
+ struct helper_data *data = transport->data;
+ struct child_process *child = data->helper;
+ fclose(data->out);
+ free(data);
+ return child;
+}
+
const char* remove_ext_force(const char* url)
{
const char* url2 = url;
@@ -549,5 +559,7 @@ int transport_helper_init(struct transport *transport, const char *name)
transport->fetch = fetch;
transport->push_refs = push_refs;
transport->disconnect = release_helper;
+ transport->disown = helper_disown;
+ transport->smart_options = &(data->gitoptions);
return 0;
}
diff --git a/transport.c b/transport.c
index 21310c5..7e6ef2b 100644
--- a/transport.c
+++ b/transport.c
@@ -9,6 +9,8 @@
#include "dir.h"
#include "refs.h"
+struct ref special_transport_layer6_ready;
+
/* rsync support */
/*
@@ -398,6 +400,8 @@ struct git_transport_data {
struct git_transport_options options;
struct child_process *conn;
int fd[2];
+ /* Connection is fully up. */
+ unsigned virtual_connected : 1;
struct extra_have_objects extra_have;
};
@@ -432,10 +436,21 @@ static int set_git_option(struct git_transport_options *opts,
static int connect_setup(struct transport *transport, int for_push, int verbose)
{
struct git_transport_data *data = transport->data;
+
+ if(!data->virtual_connected && data->conn) {
+ /* Just mark it connected. */
+ data->virtual_connected = 1;
+ return 0;
+ }
+
data->conn = git_connect(data->fd, transport->url,
for_push ? data->options.receivepack :
data->options.uploadpack,
verbose ? CONNECT_VERBOSE : 0);
+
+ if(data->conn)
+ data->virtual_connected = 1;
+
return 0;
}
@@ -477,7 +492,7 @@ static int fetch_refs_via_pack(struct transport *transport,
for (i = 0; i < nr_heads; i++)
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
- if (!data->conn) {
+ if (!data->virtual_connected) {
connect_setup(transport, 0, 0);
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
}
@@ -490,6 +505,7 @@ static int fetch_refs_via_pack(struct transport *transport,
if (finish_connect(data->conn))
refs = NULL;
data->conn = NULL;
+ data->virtual_connected = 0;
free_refs(refs_tmp);
@@ -718,7 +734,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
struct send_pack_args args;
int ret;
- if (!data->conn) {
+ if (!data->virtual_connected) {
struct ref *tmp_refs;
connect_setup(transport, 1, 0);
@@ -741,6 +757,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
close(data->fd[0]);
ret |= finish_connect(data->conn);
data->conn = NULL;
+ data->virtual_connected = 0;
return ret;
}
@@ -749,7 +766,8 @@ static int disconnect_git(struct transport *transport)
{
struct git_transport_data *data = transport->data;
if (data->conn) {
- packet_flush(data->fd[1]);
+ if(data->virtual_connected)
+ packet_flush(data->fd[1]);
close(data->fd[0]);
close(data->fd[1]);
finish_connect(data->conn);
@@ -759,6 +777,35 @@ static int disconnect_git(struct transport *transport)
return 0;
}
+static void git_take_over_transport(struct transport *transport)
+{
+ struct git_transport_data *data;
+
+ if(!transport->disown)
+ die("Bug detected: Taking over transport requires non-NULL "
+ "disown method.");
+ if(!transport->smart_options)
+ die("Bug detected: Taking over transport requires non-NULL "
+ "smart_options field.");
+
+ data = xcalloc(1, sizeof(*data));
+ data->options = *transport->smart_options;
+ data->conn = transport->disown(transport);
+ data->fd[0] = data->conn->out;
+ data->fd[1] = data->conn->in;
+ data->virtual_connected = 0;
+ transport->data = data;
+
+ transport->set_option = NULL;
+ transport->get_refs_list = get_refs_via_connect;
+ transport->fetch = fetch_refs_via_pack;
+ transport->push = NULL;
+ transport->push_refs = git_transport_push;
+ transport->disconnect = disconnect_git;
+ transport->smart_options = &(data->options);
+ transport->disown = NULL;
+}
+
static int is_local(const char *url)
{
const char *colon = strchr(url, ':');
@@ -857,6 +904,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
ret->smart_options = NULL;
+ ret->disown = NULL;
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
@@ -864,6 +912,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;
ret->smart_options = NULL;
+ ret->disown = NULL;
} else if(!is_url(url)
|| !prefixcmp(url, "file://")
|| !prefixcmp(url, "git://")
@@ -879,8 +928,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->push_refs = git_transport_push;
ret->disconnect = disconnect_git;
ret->smart_options = &(data->options);
+ ret->disown = NULL;
data->conn = NULL;
+ data->virtual_connected = 0;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
@@ -938,14 +989,25 @@ int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
int *nonfastforward)
{
+ int rc = 0;
*nonfastforward = 0;
verify_remote_names(refspec_nr, refspec);
- if (transport->push)
- return transport->push(transport, refspec_nr, refspec, flags);
- if (transport->push_refs) {
+retry:
+ if (transport->push) {
+ rc = transport->push(transport, refspec_nr, refspec, flags);
+ if(rc == TRANSPORT_LAYER6_READY) {
+ git_take_over_transport(transport);
+ goto retry;
+ }
+ return rc;
+ } else if (transport->push_refs) {
struct ref *remote_refs =
transport->get_refs_list(transport, 1);
+ if(remote_refs == &special_transport_layer6_ready) {
+ git_take_over_transport(transport);
+ goto retry;
+ }
struct ref *local_refs = get_local_heads();
int match_flags = MATCH_REFS_NONE;
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
@@ -985,8 +1047,15 @@ int transport_push(struct transport *transport,
const struct ref *transport_get_remote_refs(struct transport *transport)
{
- if (!transport->remote_refs)
+ if (!transport->remote_refs) {
+retry:
transport->remote_refs = transport->get_refs_list(transport, 0);
+ if(transport->remote_refs == &special_transport_layer6_ready) {
+ git_take_over_transport(transport);
+ goto retry;
+ }
+ }
+
return transport->remote_refs;
}
@@ -1020,7 +1089,13 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
heads[nr_heads++] = rm;
}
+retry:
rc = transport->fetch(transport, nr_heads, heads);
+ if(rc == TRANSPORT_LAYER6_READY) {
+ git_take_over_transport(transport);
+ goto retry;
+ }
+
free(heads);
return rc;
}
diff --git a/transport.h b/transport.h
index 5949132..f3ee890 100644
--- a/transport.h
+++ b/transport.h
@@ -65,6 +65,15 @@ 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);
+ /**
+ * Disown the transport helper. Releases all resources used
+ * by field pointed by member data, except that the child
+ * process is not released but returned and whatever is pointed
+ * by smart transport options structure is not freed (but the
+ * smart transport options structure itself is).
+ **/
+ struct child_process* (*disown)(struct transport* connection);
+
/** get_refs_list(), fetch(), and push_refs() can keep
* resources (such as a connection) reserved for futher
* use. disconnect() releases these resources.
@@ -79,6 +88,12 @@ struct transport {
struct git_transport_options* smart_options;
};
+/* Returned by get_refs_list, fetch or push methods of struct transport: Layer 6 is ready,
+ take over the transport and retry operation. */
+#define TRANSPORT_LAYER6_READY -42
+extern struct ref special_transport_layer6_ready;
+
+
#define TRANSPORT_PUSH_ALL 1
#define TRANSPORT_PUSH_FORCE 2
#define TRANSPORT_PUSH_DRY_RUN 4
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 2/8] Refactor git transport options parsing
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>
Refactor the transport options parsing so that protocols that aren't
directly smart transports (file://, git://, ssh:// & co) can record
the smart transport options for the case if it turns that transport
can actually be smart.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport.c | 78 +++++++++++++++++++++++++++++++++++-----------------------
transport.h | 12 +++++++++
2 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/transport.c b/transport.c
index 162d022..21310c5 100644
--- a/transport.c
+++ b/transport.c
@@ -395,41 +395,35 @@ static int close_bundle(struct transport *transport)
}
struct git_transport_data {
- unsigned thin : 1;
- unsigned keep : 1;
- unsigned followtags : 1;
- int depth;
+ struct git_transport_options options;
struct child_process *conn;
int fd[2];
- const char *uploadpack;
- const char *receivepack;
struct extra_have_objects extra_have;
};
-static int set_git_option(struct transport *connection,
+static int set_git_option(struct git_transport_options *opts,
const char *name, const char *value)
{
- struct git_transport_data *data = connection->data;
if (!strcmp(name, TRANS_OPT_UPLOADPACK)) {
- data->uploadpack = value;
+ opts->uploadpack = value;
return 0;
} else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) {
- data->receivepack = value;
+ opts->receivepack = value;
return 0;
} else if (!strcmp(name, TRANS_OPT_THIN)) {
- data->thin = !!value;
+ opts->thin = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
- data->followtags = !!value;
+ opts->followtags = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_KEEP)) {
- data->keep = !!value;
+ opts->keep = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
if (!value)
- data->depth = 0;
+ opts->depth = 0;
else
- data->depth = atoi(value);
+ opts->depth = atoi(value);
return 0;
}
return 1;
@@ -439,7 +433,8 @@ static int connect_setup(struct transport *transport, int for_push, int verbose)
{
struct git_transport_data *data = transport->data;
data->conn = git_connect(data->fd, transport->url,
- for_push ? data->receivepack : data->uploadpack,
+ for_push ? data->options.receivepack :
+ data->options.uploadpack,
verbose ? CONNECT_VERBOSE : 0);
return 0;
}
@@ -469,15 +464,15 @@ static int fetch_refs_via_pack(struct transport *transport,
struct ref *refs_tmp = NULL;
memset(&args, 0, sizeof(args));
- args.uploadpack = data->uploadpack;
- args.keep_pack = data->keep;
+ args.uploadpack = data->options.uploadpack;
+ args.keep_pack = data->options.keep;
args.lock_pack = 1;
- args.use_thin_pack = data->thin;
- args.include_tag = data->followtags;
+ args.use_thin_pack = data->options.thin;
+ args.include_tag = data->options.followtags;
args.verbose = (transport->verbose > 0);
args.quiet = (transport->verbose < 0);
args.no_progress = args.quiet || (!transport->progress && !isatty(1));
- args.depth = data->depth;
+ args.depth = data->options.depth;
for (i = 0; i < nr_heads; i++)
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
@@ -734,7 +729,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
memset(&args, 0, sizeof(args));
args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
- args.use_thin_pack = data->thin;
+ args.use_thin_pack = data->options.thin;
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
@@ -861,12 +856,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
+ ret->smart_options = NULL;
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;
+ ret->smart_options = NULL;
} else if(!is_url(url)
|| !prefixcmp(url, "file://")
|| !prefixcmp(url, "git://")
@@ -876,20 +873,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
/* These are builtin smart transports. */
struct git_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
- ret->set_option = set_git_option;
+ ret->set_option = NULL;
ret->get_refs_list = get_refs_via_connect;
ret->fetch = fetch_refs_via_pack;
ret->push_refs = git_transport_push;
ret->disconnect = disconnect_git;
+ ret->smart_options = &(data->options);
- data->thin = 1;
data->conn = NULL;
- data->uploadpack = "git-upload-pack";
- if (remote->uploadpack)
- data->uploadpack = remote->uploadpack;
- data->receivepack = "git-receive-pack";
- if (remote->receivepack)
- data->receivepack = remote->receivepack;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
@@ -907,14 +898,39 @@ struct transport *transport_get(struct remote *remote, const char *url)
transport_helper_init(ret, handler);
}
+ if(ret->smart_options) {
+ ret->smart_options->thin = 1;
+ ret->smart_options->uploadpack = "git-upload-pack";
+ if (remote->uploadpack)
+ ret->smart_options->uploadpack = remote->uploadpack;
+ ret->smart_options->receivepack = "git-receive-pack";
+ if (remote->receivepack)
+ ret->smart_options->receivepack = remote->receivepack;
+ }
+
return ret;
}
int transport_set_option(struct transport *transport,
const char *name, const char *value)
{
+ int git_reports = 1, protocol_reports = 1;
+
+ if (transport->smart_options)
+ git_reports = set_git_option(transport->smart_options,
+ name, value);
+
if (transport->set_option)
- return transport->set_option(transport, name, value);
+ protocol_reports = transport->set_option(transport, name,
+ value);
+
+ /* If either report is 0, report 0 (success). */
+ if(!git_reports || !protocol_reports)
+ return 0;
+ /* If either reports -1 (invalid value), report -1. */
+ if((git_reports == -1) || (protocol_reports == -1))
+ return -1;
+ /* Otherwise if both report unknown, report unknown. */
return 1;
}
diff --git a/transport.h b/transport.h
index 9e74406..5949132 100644
--- a/transport.h
+++ b/transport.h
@@ -4,6 +4,15 @@
#include "cache.h"
#include "remote.h"
+struct git_transport_options {
+ unsigned thin : 1;
+ unsigned keep : 1;
+ unsigned followtags : 1;
+ int depth;
+ const char *uploadpack;
+ const char *receivepack;
+};
+
struct transport {
struct remote *remote;
const char *url;
@@ -65,6 +74,9 @@ struct transport {
signed verbose : 3;
/* Force progress even if the output is not a tty */
unsigned progress : 1;
+ /* If transport is at least potentially smart, this points to git_transport_options
+ structure to use in case transport actually turns out to be smart. */
+ struct git_transport_options* smart_options;
};
#define TRANSPORT_PUSH_ALL 1
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 1/8] Pass unknown protocols to external protocol handlers
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>
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.
foo:// now invokes git-remote-foo with foo:// URL.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 37 ++++++++++++++++++++++-
transport.c | 82 +++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 106 insertions(+), 13 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 11f3d7e..d3aad5c 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -22,6 +22,26 @@ struct helper_data
int refspec_nr;
};
+const char* remove_ext_force(const char* url)
+{
+ const char* url2 = url;
+ const char* first_colon = NULL;
+
+ if(!url)
+ return NULL;
+
+ while(*url2 && !first_colon)
+ if(*url2 == ':')
+ first_colon = url2;
+ else
+ url2++;
+
+ if(first_colon && first_colon[1] == ':')
+ return first_colon + 2;
+ else
+ return url;
+}
+
static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
@@ -30,6 +50,7 @@ static struct child_process *get_helper(struct transport *transport)
const char **refspecs = NULL;
int refspec_nr = 0;
int refspec_alloc = 0;
+ int duped;
if (data->helper)
return data->helper;
@@ -42,15 +63,26 @@ static struct child_process *get_helper(struct transport *transport)
strbuf_addf(&buf, "remote-%s", data->name);
helper->argv[0] = strbuf_detach(&buf, NULL);
helper->argv[1] = transport->remote->name;
- helper->argv[2] = transport->url;
+ helper->argv[2] = remove_ext_force(transport->url);
helper->git_cmd = 1;
if (start_command(helper))
die("Unable to run helper: git %s", helper->argv[0]);
data->helper = helper;
+ /* Open the output as FILE* so strbuf_getline() can be used.
+ Do this with duped fd because fclose() will close the fd,
+ and stuff like disowning will require the fd to remain.
+
+ Set the stream to unbuffered because some reads are critical
+ in sense that any overreading will cause deadlocks.
+ */
+ if((duped = dup(helper->out)) < 0)
+ die_errno("Can't dup helper output fd");
+ data->out = xfdopen(duped, "r");
+ setvbuf(data->out, NULL, _IONBF, 0);
+
write_str_in_full(helper->in, "capabilities\n");
- data->out = xfdopen(helper->out, "r");
while (1) {
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
@@ -91,6 +123,7 @@ static int disconnect_helper(struct transport *transport)
if (data->helper) {
write_str_in_full(data->helper->in, "\n");
close(data->helper->in);
+ close(data->helper->out);
fclose(data->out);
finish_command(data->helper);
free((char *)data->helper->argv[0]);
diff --git a/transport.c b/transport.c
index 3eea836..162d022 100644
--- a/transport.c
+++ b/transport.c
@@ -780,6 +780,55 @@ static int is_file(const char *url)
return S_ISREG(buf.st_mode);
}
+static const char* strchrc(const char* str, int c)
+{
+ while(*str)
+ if(*str == c)
+ return str;
+ else
+ str++;
+ return NULL;
+}
+
+static int is_url(const char* url)
+{
+ if(!url)
+ return 0;
+
+ const char* url2 = url;
+ const char* first_slash = strchrc(url, '/');
+
+ /* Input with no slash at all or slash first can't be URL. */
+ if(!first_slash || first_slash == url)
+ return 0;
+ /* Character before must be : and next must be /. */
+ if(first_slash[-1] != ':' || first_slash[1] != '/')
+ return 0;
+ /* There must be something before the :// */
+ if(first_slash == url + 1)
+ return 0;
+ /* Check all characters up to first slash. Only alpha, num and
+ : are allowed. : must be followed by : or / */
+ url2 = url;
+ while(url2 < first_slash) {
+ if(*url2 != ':' && !isalnum((unsigned char)*url2))
+ return 0;
+ if(*url2 == ':' && url2[1] != ':' && url2[1] != '/')
+ return 0;
+ if(*url2 == ':')
+ url2++; /* Skip second : */
+ url2++;
+ }
+
+ /* Valid enough. */
+ return 1;
+}
+
+static int external_specification_len(const char* url)
+{
+ return strchrc(url, ':') - url;
+}
+
struct transport *transport_get(struct remote *remote, const char *url)
{
struct transport *ret = xcalloc(1, sizeof(*ret));
@@ -812,23 +861,19 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
-
- } else if (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
- transport_helper_init(ret, "curl");
-#ifdef NO_CURL
- error("git was compiled without libcurl support.");
-#endif
-
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;
-
- } else {
+ } else if(!is_url(url)
+ || !prefixcmp(url, "file://")
+ || !prefixcmp(url, "git://")
+ || !prefixcmp(url, "ssh://")
+ || !prefixcmp(url, "git+ssh://")
+ || !prefixcmp(url, "ssh+git://")) {
+ /* These are builtin smart transports. */
struct git_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->set_option = set_git_option;
@@ -845,6 +890,21 @@ struct transport *transport_get(struct remote *remote, const char *url)
data->receivepack = "git-receive-pack";
if (remote->receivepack)
data->receivepack = remote->receivepack;
+ } 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);
+ char* handler = xmalloc(len + 1);
+ handler[len] = 0;
+ strncpy(handler, url, len);
+ transport_helper_init(ret, handler);
}
return ret;
--
1.6.6.rc1.288.g40e67
^ permalink raw reply related
* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
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>
This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.
Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to invoking helpers (see known issues)
Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.
Ilari Liusvaara (8):
Pass unknown protocols to external protocol handlers
Refactor git transport options parsing
Support taking over transports
Support remote helpers implementing smart transports
Support remote archive from external protocol helpers
Remove special casing of http, https and ftp
Add remote helper debug mode
Support mandatory capabilities
.gitignore | 4 +
Documentation/git-remote-helpers.txt | 36 +++++-
Makefile | 24 +++-
builtin-archive.c | 17 ++-
transport-helper.c | 261 +++++++++++++++++++++++++++++-----
transport.c | 258 +++++++++++++++++++++++++++------
transport.h | 32 ++++
7 files changed, 540 insertions(+), 92 deletions(-)
^ permalink raw reply
* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-04 15:55 UTC (permalink / raw)
To: git
This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.
Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to way helpers are invoked.[1]
- Actually test the intermediate states for gross errors.
[1] The current way seems to have all sorts of funky failure cases, but
I'm not touching it without fixing it properly.
Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.
Ilari Liusvaara (8):
Pass unknown protocols to external protocol handlers
Refactor git transport options parsing
Support taking over transports
Support remote helpers implementing smart transports
Support remote archive from external protocol helpers
Remove special casing of http, https and ftp
Add remote helper debug mode
Support mandatory capabilities
.gitignore | 4 +
Documentation/git-remote-helpers.txt | 33 ++++-
Makefile | 24 +++-
builtin-archive.c | 17 ++-
transport-helper.c | 258 +++++++++++++++++++++++++++++-----
transport.c | 258 +++++++++++++++++++++++++++------
transport.h | 32 ++++
7 files changed, 534 insertions(+), 92 deletions(-)
^ permalink raw reply
* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-04 15:55 UTC (permalink / raw)
To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>
This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.
Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to way helpers are invoked.[1]
- Actually test that all intermediate states compile.
[1] The current way seems to have all sorts of funky failure cases, but
I'm not touching it without fixing it properly.
Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.
Ilari Liusvaara (8):
Pass unknown protocols to external protocol handlers
Refactor git transport options parsing
Support taking over transports
Support remote helpers implementing smart transports
Support remote archive from external protocol helpers
Remove special casing of http, https and ftp
Add remote helper debug mode
Support mandatory capabilities
.gitignore | 4 +
Documentation/git-remote-helpers.txt | 33 ++++-
Makefile | 24 +++-
builtin-archive.c | 17 ++-
transport-helper.c | 257 +++++++++++++++++++++++++++++-----
transport.c | 258 +++++++++++++++++++++++++++------
transport.h | 32 ++++
7 files changed, 533 insertions(+), 92 deletions(-)
^ permalink raw reply
* Re: [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Shawn O. Pearce @ 2009-12-04 15:50 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>
Michael Haggerty <mhagger@alum.mit.edu> wrote:
> This patch series adds "fix" to the commands that can be used within
> the "rebase --interactive" patch editor. "fix" is like "squash"
> except that it discards the log message of the corresponding commit.
...
> But sometimes I don't have my head-slapping moments until a few
> commits later. In this case, my usual practice is to commit the
> trivial typo change on top of the current branch, then "rebase
> --interactive" to move the typo fix on top of the erroneous commit and
> squash it:
...
> pick 05d3b81 Commit with typo
> squash 5eb3299 Fix for typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2
+1 for fix. Totally.
When developing I *often* have not just 1 to squash, but 10 or so
in a single rebase -i session, all with useless commit messages like
"a", "s", or "foo". Given that I also have a commit-msg hook which
injects additional lines into each of those messages, squash can be
annoying to use...
fix would be really cool. To be honest, its my most common use
of squash... to use the first commit's message, but combine in the
misc. idiot fixes I've collected since I wrote that commit.
--
Shawn.
^ permalink raw reply
* rev-parse --show-cdup in .git
From: Michael J Gruber @ 2009-12-04 15:45 UTC (permalink / raw)
To: Git Mailing List
I'm sure this was discussed somewhere, but I can't find it:
When called from within .git, git rev-parse --show-cdup returns nothing
rather than "..", not even an error code. Is this intended?
This is all the more disturbing since the cwd of hooks seems to be
GIT_DIR. Is that something one can rely upon? In that case one can
simply use ".." for cdup.
Michael
P.S.: The use case is a simple post-receive-hook that fast forwards a
checked out branch on receiving refs in refs/remotes/incoming/, but
needs to check the worktree against the index etc. 1.7.0 may be an
opportunity to encourage usage of this rather than restoring the old
behavior through options.
^ permalink raw reply
* Re: [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Michael J Gruber @ 2009-12-04 15:13 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>
Michael Haggerty venit, vidit, dixit 04.12.2009 15:36:
> This patch series adds "fix" to the commands that can be used within
> the "rebase --interactive" patch editor. "fix" is like "squash"
> except that it discards the log message of the corresponding commit.
>
> Why I would like this feature:
>
> One of my favorite aliases is
>
> fix = commit --amend -C HEAD
>
> which I use in those all-too-frequent head-slapping "I just committed
> something with a minor typo" moments. It amends the last commit with
> whatever is staged, reusing the same commit message. It can also be
> used with the "-a" option, a list of filenames, etc.
>
> But sometimes I don't have my head-slapping moments until a few
> commits later. In this case, my usual practice is to commit the
> trivial typo change on top of the current branch, then "rebase
> --interactive" to move the typo fix on top of the erroneous commit and
> squash it:
>
> pick 05d3b81 Commit with typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2
> pick 5eb3299 Fix for typo
>
> |
> V
>
> pick 05d3b81 Commit with typo
> squash 5eb3299 Fix for typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2
>
> But then it is necessary to go into the commit message editor, move
> the cursor down past the first commit message, delete the "Fix for
> typo" commit message, save, and quit.
>
> This patch implements a "fix" command, similar to "squash", except
> that the corresponding log message is not included in the log message
> suggested for the combined commit. (In fact, it includes the log
> message, but commented out.) It therefore saves the editor chores.
>
> "fix" and "squash" can be used in the same group, in which case the
> "squash" commit messages are preserved and the "fix" commit messages
> are skipped.
>
> If the idea of a "fix" command is acceptable, then I would like to
> implement a further convenience: if a group of commits to be folded
> together includes *only* "fix" commits, then the first log message
> should be used without even opening an editor. But I would like to
> get a reaction to the "fix" command in general before doing so.
I'd say that would make a useful command ("fix") even more useful, being
just the right counterpart to "reword" for trivial commit message fixes.
OTOH, it would not be possible any more to squash in a few fixes and
then edit the message. Maybe having to quit the editor is not that much
work after all.
As a bike-shedding side note: So far, all commands are verbs which
describe actions to take on that commit. In that sense a "fix deadbeef"
would be confusing: You don't fix deadbeef, you fix the predecessor
using deadbeef.
A bit of brainstorming (suck/use/smash/apply/join) does not convince me
of any of my alternatives, but maybe they convince someone else :)
Michael
P.S.: I thought there's some heavy rb-i rewrite in progress (sequencer
based or not?), but you cc'ed Dscho anyway who knows best.
> Michael Haggerty (3):
> Better document the original repository layout.
> Set a couple more tags in the original repository.
> Add a command "fix" to rebase --interactive.
>
> Documentation/git-rebase.txt | 13 ++++++++-----
> git-rebase--interactive.sh | 39 +++++++++++++++++++++++++++++----------
> t/lib-rebase.sh | 7 ++++---
> t/t3404-rebase-interactive.sh | 41 +++++++++++++++++++++++++++++++++++++----
> 4 files changed, 78 insertions(+), 22 deletions(-)
>
^ permalink raw reply
* Re: [PATCH 1/3] Better document the original repository layout.
From: Michael J Gruber @ 2009-12-04 14:52 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <91462ec5e4409e558ec5158b7dea33ebf0081d3e.1259934977.git.mhagger@alum.mit.edu>
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.
Michael
^ permalink raw reply
* [PATCH 2/3] Set a couple more tags in the original repository.
From: Michael Haggerty @ 2009-12-04 14:36 UTC (permalink / raw)
To: git; +Cc: gitster, Johannes.Schindelin, Michael Haggerty
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
t/t3404-rebase-interactive.sh | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 073674f..236d698 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -23,7 +23,7 @@ set_fake_editor
# I (branch2)
#
# where B, D and G touch the same file. In addition, set tags at
-# points A, F, and I.
+# points A, E, F, H, and I.
test_expect_success 'setup' '
: > file1 &&
@@ -45,6 +45,7 @@ test_expect_success 'setup' '
git add file3 &&
test_tick &&
git commit -m E &&
+ git tag E &&
git checkout -b branch1 A &&
: > file4 &&
git add file4 &&
@@ -58,6 +59,7 @@ test_expect_success 'setup' '
git add file5 &&
test_tick &&
git commit -m H &&
+ git tag H &&
git checkout -b branch2 F &&
: > file6 &&
git add file6 &&
--
1.6.5.4
^ permalink raw reply related
* [PATCH 3/3] Add a command "fix" to rebase --interactive.
From: Michael Haggerty @ 2009-12-04 14:36 UTC (permalink / raw)
To: git; +Cc: gitster, Johannes.Schindelin, Michael Haggerty
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>
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>
---
Documentation/git-rebase.txt | 13 ++++++++-----
git-rebase--interactive.sh | 39 +++++++++++++++++++++++++++++----------
t/lib-rebase.sh | 7 ++++---
t/t3404-rebase-interactive.sh | 30 ++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 18 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index ca5e1e8..eafab57 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the
command "pick" with the command "reword".
If you want to fold two or more commits into one, replace the command
-"pick" with "squash" for the second and subsequent commit. If the
-commits had different authors, it will attribute the squashed commit to
-the author of the first commit.
+"pick" for the second and subsequent commits with "squash" or "fix".
+If the commits had different authors, the folded commit will be
+attributed to the author of the first commit. The suggested commit
+message for the folded commit is the concatenation of the commit
+messages of the first commit and of those with the "squash" command,
+but omits the commit messages of commits with the "fix" command.
'git-rebase' will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done editing
@@ -512,8 +515,8 @@ Easy case: The changes are literally the same.::
Hard case: The changes are not the same.::
This happens if the 'subsystem' rebase had conflicts, or used
- `\--interactive` to omit, edit, or squash commits; or if the
- upstream used one of `commit \--amend`, `reset`, or
+ `\--interactive` to omit, edit, squash, or fix commits; or if
+ the upstream used one of `commit \--amend`, `reset`, or
`filter-branch`.
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,/^./{
@@ -315,10 +315,20 @@ make_squash_message () {
echo
git cat-file commit HEAD | sed -e '1,/^$/d'
fi
- echo
- echo "# This is the $(nth_string $COUNT) commit message:"
- echo
- git cat-file commit $1 | sed -e '1,/^$/d'
+ case $1 in
+ squash)
+ echo
+ echo "# This is the $(nth_string $COUNT) commit message:"
+ echo
+ git cat-file commit $2 | sed -e '1,/^$/d'
+ ;;
+ fix)
+ echo
+ echo "# The $(nth_string $COUNT) commit message will be skipped:"
+ echo
+ git cat-file commit $2 | sed -e '1,/^$/d' -e 's/^/#/'
+ ;;
+ esac
}
peek_next_command () {
@@ -367,20 +377,28 @@ do_next () {
warn
exit 0
;;
- squash|s)
- comment_for_reflog squash
+ squash|s|fix|f)
+ case "$command" in
+ squash|s)
+ squash_style=squash
+ ;;
+ fix|f)
+ squash_style=fix
+ ;;
+ esac
+ comment_for_reflog $squash_style
test -f "$DONE" && has_action "$DONE" ||
- die "Cannot 'squash' without a previous commit"
+ die "Cannot '$squash_style' without a previous commit"
mark_action_done
- make_squash_message $sha1 > "$MSG"
+ make_squash_message $squash_style $sha1 > "$MSG"
failed=f
author_script=$(get_author_ident_from_commit HEAD)
output git reset --soft HEAD^
pick_one -n $sha1 || failed=t
case "$(peek_next_command)" in
- squash|s)
+ squash|s|fix|f)
USE_OUTPUT=output
MSG_OPT=-F
EDIT_OR_FILE="$MSG"
@@ -768,6 +786,7 @@ first and then run 'git rebase --continue' again."
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
+# f, fix = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 62f452c..8b42f23 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -9,8 +9,9 @@
#
# "[<lineno1>] [<lineno2>]..."
#
-# If a line number is prefixed with "squash", "edit", or "reword", the
-# respective line's command will be replaced with the specified one.
+# If a line number is prefixed with "squash", "fix", "edit", or
+# "reword", the respective line's command will be replaced with the
+# specified one.
set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
@@ -32,7 +33,7 @@ cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
- squash|edit|reword)
+ squash|fix|edit|reword)
action="$line";;
*)
echo sed -n "${line}s/^pick/$action/p"
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 236d698..27645c4 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -264,6 +264,36 @@ test_expect_success 'multi-squash only fires up editor once' '
test 1 = $(git show | grep ONCE | wc -l)
'
+test_expect_success 'multi-fix only fires up editor once' '
+ git checkout -b multi-fix E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fix 2 fix 3 fix 4" \
+ git rebase -i $base &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 1 = $(git show | grep ONCE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D multi-fix
+'
+
+cat > expect-squash-fix << EOF
+B
+
+D
+
+ONCE
+EOF
+
+test_expect_success 'squash and fix generate correct log messages' '
+ git checkout -b squash-fix E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fix 2 squash 3 fix 4" \
+ git rebase -i $base &&
+ git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fix &&
+ test_cmp expect-squash-fix actual-squash-fix &&
+ git checkout to-be-rebased &&
+ git branch -D squash-fix
+'
+
test_expect_success 'squash works as expected' '
for n in one two three four
do
--
1.6.5.4
^ permalink raw reply related
* [PATCH 1/3] Better document the original repository layout.
From: Michael Haggerty @ 2009-12-04 14:36 UTC (permalink / raw)
To: git; +Cc: gitster, Johannes.Schindelin, Michael Haggerty
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>
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 &&
--
1.6.5.4
^ permalink raw reply related
* [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Michael Haggerty @ 2009-12-04 14:36 UTC (permalink / raw)
To: git; +Cc: gitster, Johannes.Schindelin, Michael Haggerty
This patch series adds "fix" to the commands that can be used within
the "rebase --interactive" patch editor. "fix" is like "squash"
except that it discards the log message of the corresponding commit.
Why I would like this feature:
One of my favorite aliases is
fix = commit --amend -C HEAD
which I use in those all-too-frequent head-slapping "I just committed
something with a minor typo" moments. It amends the last commit with
whatever is staged, reusing the same commit message. It can also be
used with the "-a" option, a list of filenames, etc.
But sometimes I don't have my head-slapping moments until a few
commits later. In this case, my usual practice is to commit the
trivial typo change on top of the current branch, then "rebase
--interactive" to move the typo fix on top of the erroneous commit and
squash it:
pick 05d3b81 Commit with typo
pick c29114a Good commit 1
pick 250b013 Good commit 2
pick 5eb3299 Fix for typo
|
V
pick 05d3b81 Commit with typo
squash 5eb3299 Fix for typo
pick c29114a Good commit 1
pick 250b013 Good commit 2
But then it is necessary to go into the commit message editor, move
the cursor down past the first commit message, delete the "Fix for
typo" commit message, save, and quit.
This patch implements a "fix" command, similar to "squash", except
that the corresponding log message is not included in the log message
suggested for the combined commit. (In fact, it includes the log
message, but commented out.) It therefore saves the editor chores.
"fix" and "squash" can be used in the same group, in which case the
"squash" commit messages are preserved and the "fix" commit messages
are skipped.
If the idea of a "fix" command is acceptable, then I would like to
implement a further convenience: if a group of commits to be folded
together includes *only* "fix" commits, then the first log message
should be used without even opening an editor. But I would like to
get a reaction to the "fix" command in general before doing so.
Michael Haggerty (3):
Better document the original repository layout.
Set a couple more tags in the original repository.
Add a command "fix" to rebase --interactive.
Documentation/git-rebase.txt | 13 ++++++++-----
git-rebase--interactive.sh | 39 +++++++++++++++++++++++++++++----------
t/lib-rebase.sh | 7 ++++---
t/t3404-rebase-interactive.sh | 41 +++++++++++++++++++++++++++++++++++++----
4 files changed, 78 insertions(+), 22 deletions(-)
^ permalink raw reply
* Re: git gsoc money
From: Jeff King @ 2009-12-04 12:14 UTC (permalink / raw)
To: git
In-Reply-To: <20091203153935.GB23281@spearce.org>
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.
-Peff
^ permalink raw reply
* Re: git reset --hard in .git causes a checkout in that directory
From: Jeff King @ 2009-12-04 11:11 UTC (permalink / raw)
To: Maarten Lankhorst; +Cc: Junio C Hamano, git
In-Reply-To: <4B17A166.60306@gmail.com>
On Thu, Dec 03, 2009 at 12:30:46PM +0100, Maarten Lankhorst wrote:
> When I was working on my code and made a mess that I wanted to undo,
> I accidentally did it in the .git directory, and had a whole clone of
> my last committed tree there.
>
> It can be triggered easily:
>
> mkdir test; cd test; git init; touch foo; git add foo; git commit -m
> 'add foo'; cd .git; git reset --hard; [ -f foo ] && echo hello beauty
>
> Other parts of git could be affected, I haven't checked where exactly
> the bug hides, so I was afraid to send in a patch
Yuck. Thanks for the bug report. This is due to a too-loose check on my
part in 49b9362 (git-reset: refuse to do hard reset in a bare
repository, 2007-12-31).
Junio, I think the following should go to maint (I didn't bother
splitting the --merge and --hard code; --merge is in v1.6.2. I assumed
we don't care about maint releases that far back).
-- >8 --
Subject: [PATCH] reset: improve worktree safety valves
The existing code checked to make sure we were not in a bare
repository when doing a hard reset. However, we should take
this one step further, and make sure we are in a worktree.
Otherwise, we can end up munging files inside of '.git'.
Furthermore, we should do the same check for --merge resets,
which have the same properties. Actually, a merge reset of
HEAD^ would already complain, since further down in the code
we want a worktree. However, it is nicer to check up-front;
then we are sure we cover all cases ("git reset --merge"
would run, even though it wasn't doing anything) and we can
give a more specific message.
Signed-off-by: Jeff King <peff@peff.net>
---
builtin-reset.c | 6 ++++--
t/t7103-reset-bare.sh | 14 ++++++++++++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/builtin-reset.c b/builtin-reset.c
index 73e6022..11d1c6e 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -286,8 +286,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (reset_type == NONE)
reset_type = MIXED; /* by default */
- if (reset_type == HARD && is_bare_repository())
- die("hard reset makes no sense in a bare repository");
+ if ((reset_type == HARD || reset_type == MERGE)
+ && !is_inside_work_tree())
+ die("%s reset requires a work tree",
+ reset_type_names[reset_type]);
/* Soft reset does not touch the index file nor the working tree
* at all, but requires them in a good order. Other resets reset
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index 42bf518..3ddf0ac 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -11,6 +11,16 @@ test_expect_success 'setup non-bare' '
git commit -a -m two
'
+test_expect_success 'hard reset requires a worktree' '
+ (cd .git &&
+ test_must_fail git reset --hard)
+'
+
+test_expect_success 'merge reset requires a worktree' '
+ (cd .git &&
+ test_must_fail git reset --merge)
+'
+
test_expect_success 'setup bare' '
git clone --bare . bare.git &&
cd bare.git
@@ -20,6 +30,10 @@ test_expect_success 'hard reset is not allowed' '
test_must_fail git reset --hard HEAD^
'
+test_expect_success 'merge reset is not allowed' '
+ test_must_fail git reset --merge HEAD^
+'
+
test_expect_success 'soft reset is allowed' '
git reset --soft HEAD^ &&
test "`git show --pretty=format:%s | head -n 1`" = "one"
--
1.6.6.rc1.18.ga777f.dirty
^ permalink raw reply related
* Re: Running commands in wrong environment
From: Jeff King @ 2009-12-04 10:44 UTC (permalink / raw)
To: Marinescu Paul dan; +Cc: Junio C Hamano, git@vger.kernel.org
In-Reply-To: <D6F784B72498304C93A8A4691967698E8EE2C44FE5@REX2.intranet.epfl.ch>
On Thu, Dec 03, 2009 at 08:19:05PM +0100, Marinescu Paul dan wrote:
> git's start_command (run_command.c) executes a command (e.g. hook) but
> does not verify that it has properly set up the environment. It seems
> that in the unlikely case where putenv (run_command.c:117) fails, the
> command may have undesirable effects e.g. GIT_INDEX_FILE should have
> been set (interactive pre-commit hooks) but the default index will be
> used instead. It would be safer not to run the command but just exit
> in that case.--
Hmm. It is simple enough to patch the one use of putenv, but there are
34 other calls to setenv, which has the same problem. I am tempted to
ignore it, as it is extremely unlikely for this ever to happen, and
adding error checking everywhere reduces the code readability.
But the consequences, as you mention, could include data loss, which
argues for being on the safe side. In that case, we would probably want
an "xsetenv" to die() if we fail to avoid cluttering the code
everywhere.
I dunno. If we're going to do it, it is probably maint-worthy. Junio?
-Peff
^ permalink raw reply
* Re: [RFC PATCH 2/2] MSVC: Fix an "incompatible pointer types" compiler warning
From: Johannes Schindelin @ 2009-12-04 10:47 UTC (permalink / raw)
To: Ramsay Jones
Cc: Junio C Hamano, Marius Storm-Olsen, Johannes Sixt,
GIT Mailing-list
In-Reply-To: <4B1806FB.2050401@ramsay1.demon.co.uk>
Hi,
On Thu, 3 Dec 2009, Ramsay Jones wrote:
> compat/mingw.h | 27 ++++++++++++++++++++++++++-
> compat/msvc.h | 25 +------------------------
> 2 files changed, 27 insertions(+), 25 deletions(-)
I'd prefer to have the MSVC-specific definitions in msvc.h, along with a
definition of, say, ALREADY_DEFINED_STATI64 or some such (which tells
mingw.h not to do anything about those types). There is no need to
clutter mingw.h with stuff for MSVC.
Ciao,
Dscho
^ permalink raw reply
* Re: [BUG] crash on make test
From: Jeff King @ 2009-12-04 10:35 UTC (permalink / raw)
To: Marinescu Paul dan; +Cc: Junio C Hamano, git@vger.kernel.org
In-Reply-To: <D6F784B72498304C93A8A4691967698E8EE2C44FE2@REX2.intranet.epfl.ch>
On Thu, Dec 03, 2009 at 04:38:58PM +0100, Marinescu Paul dan wrote:
> I got a crash on git's make test with and a core file in ./t/trash
> directory.t4200-rerere/ The problem seems to be in garbage_collect
> (builtin-rerere.c) where readdir can be called with a null pointer
Hmm. The problematic code is pretty straightforward to see, but what I
don't understand is how you managed to trigger it. The code path to get
there makes sure that the rr-cache directory exists (because we check
whether rerere is enabled, which means either rr-cache exists, or
rerere.enabled is set, and in the latter case we mkdir the directory).
I can see how it might happen if rr-cache exists but isn't readable. I
can easily trigger a segfault with:
mkdir .git/rr-cache
sudo chown root .git/rr-cache
sudo chmod 0700 .git/rr-cache
git gc
and we should definitely fix that (patch below).
But how do you end up with this situation in the middle of the test
suite? And if it is not a permissions problem, but that the directory is
missing, that would indicate something randomly deleting files while
you're running the test.
I think we should apply the patch below to maint, as this is something
that can come up due to permissions problems. But I fear it won't
actually fix the test failure you are seeing; you will just see it die()
instead of segfaulting. However, the value of errno should give us a
clue about what is happening, so please try running the test again with
this patch.
-- >8 --
Subject: [PATCH] rerere: don't segfault on failure to open rr-cache
The rr-cache directory should always exist if we are doing
garbage collection (earlier code paths check this
explicitly), but we may not necessarily succeed in opening
it (for example, due to permissions problems). In that case,
we should print an error message rather than simply
segfaulting.
Signed-off-by: Jeff King <peff@peff.net>
---
builtin-rerere.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 343d6cd..2be9ffb 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -48,6 +48,8 @@ static void garbage_collect(struct string_list *rr)
git_config(git_rerere_gc_config, NULL);
dir = opendir(git_path("rr-cache"));
+ if (!dir)
+ die_errno("unable to open rr-cache directory");
while ((e = readdir(dir))) {
if (is_dot_or_dotdot(e->d_name))
continue;
--
1.6.6.rc1.18.ga777f.dirty
^ permalink raw reply related
* Re: [PATCH resend 3/3] transport.c::transport_push(): make ref status affect return value
From: Jeff King @ 2009-12-04 10:20 UTC (permalink / raw)
To: Tay Ray Chuan
Cc: git, Shawn O. Pearce, Daniel Barkalow, Sverre Rabbelier,
Clemens Buchacher, Junio C Hamano
In-Reply-To: <20091204145842.57c3c51c.rctay89@gmail.com>
On Fri, Dec 04, 2009 at 02:58:42PM +0800, Tay Ray Chuan wrote:
> - if (!quiet || push_had_errors(remote_refs))
> - print_push_status(transport->url, remote_refs,
> - verbose | porcelain, porcelain,
> - nonfastforward);
> + if (!quiet)
> + if (push_had_errors(remote_refs)) {
> + ret = -1;
> + print_push_status(transport->url, remote_refs,
> + verbose | porcelain, porcelain,
> + nonfastforward);
> + }
Er, this doesn't seem right. It will no longer print anything under
non-quiet mode unless there are errors, and it will only set a return
value in non-quiet mode.
I think you want:
if (push_had_errors(remote_refs)) {
ret = -1;
if (!quiet)
print_push_status(...)
}
else if (!quiet)
print_push_status(...)
Actually, it may simply be more readable by storing the error result:
int err = push_had_errors(remote_refs);
if (err)
ret = -1;
if (!quiet || err)
print_push_status(...);
-Peff
^ permalink raw reply
* Re: [ANNOUNCE] Git 1.6.5.4
From: Andreas Schwab @ 2009-12-04 10:12 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Todd Zullinger, Michael J Gruber, git
In-Reply-To: <7vbpif4rn2.fsf@alter.siamese.dyndns.org>
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.
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
* [PATCH] git-gui: suppress the X error on exit
From: Jindrich Makovicka @ 2009-12-04 9:28 UTC (permalink / raw)
To: git
Hi,
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.
--- git-gui~ 2009-11-17 23:28:30.000000000 +0100
+++ git-gui 2009-12-03 23:32:50.848588924 +0100
@@ -2023,6 +2023,10 @@
}
set ret_code $rc
+
+ # briefly re-enable send to suppress the RenderBadPicture error
+ tk appname [appname]
+
destroy .
}
^ permalink raw reply
* Re: How do you best store structured data in git repositories?
From: jamesmikedupont @ 2009-12-04 8:00 UTC (permalink / raw)
To: git
In-Reply-To: <32541b130912031745i60dc918dk3e510ef1a3b28526@mail.gmail.com>
On Thu, Dec 3, 2009 at 7:14 PM, David Aguilar <davvid@gmail.com> wrote:
> JSON's not too bad for data structures and is known to
> be friendly to XML expats.
>
> http://json.org/
I am currently working on two projects in this direction :
1. mediawiki on git, using mediawiki markup files. I apologise that I
have not made progress on that lately, because I have had inspiration
on my older project
2. the gcc rdf introspector, storage of the files in rdf. It is
working now with a mysql database, using the librdf mysql driver, and
running on a catalyst framework using jquery/jstree on the front end.
None of those formats are perfect, the sizing of the files is
important. I am returning individual nodes in json on the cataylst
server and that works to deliver the AST nodes from the compiler to
the jstree front end. But these fetches to the front end should be
longer and contain direct components of the fetched node. I think that
a cluster of nodes should be pulled together to make a more optimal
system.
here is just my two cents:
if you are using a distributed git data repository as your central
repository, then think about a database page. Imagine that you would have
pages of data being retrieved and compared.
Would it not make sense to split your pages something that would be swapped
into memory directly, or with very little parsing, and then used?
So, in effect, you would design the sizing of the pages and the page
contents around the usage model, since git is a low level storage system.
I dont know what would be available if some database manager system like
mysql or postgres could be taught to store table pages in git.
just some ideas,
mike
^ permalink raw reply
* Re: [RFC PATCH 2/2] MSVC: Fix an "incompatible pointer types" compiler warning
From: Johannes Sixt @ 2009-12-04 7:44 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Junio C Hamano, Marius Storm-Olsen, GIT Mailing-list
In-Reply-To: <4B1806FB.2050401@ramsay1.demon.co.uk>
Ramsay Jones schrieb:
> In order to avoid the compiler warning, we use the appropriate
> structure type names (and function names) from the msvc headers.
> This allows us to compile with -D_USE_32BIT_TIME_T if necessary.
"if necessary"? Who defines when -D_USE_32BIT_TIME_T is necessary?
> Also, I added the "&& defined(_stati64)" in the hope that it would work with
> older msvc/sdk versions.
I think that this is an unnecessary complication and I did wonder why you
added this extra check. Anybody doing some serious development with MS's
tools is using VS2005 at least. But isn't the .vcproj file made for VS2008
anyway?
> The reason for the RFC is:
>
> - maybe we don't need the flexibility of compiling with/without the 32-bit
> time_t definition (which *works* BTW) and can revert to the original patch?
Indeed I'm wondering why we should cater for 64 bit time_t. It is an
unnessary complication as long as MinGW gcc supports only 32 bit time_t
and the old MSVCRT.DLL.
> - I *think* this will work with older msvc, but I can't test it!
This should not be a concern, IMHO.
> - I've tried to be careful not to break the MinGW build, but again I can't
> test it. (I will be shocked if I have ;-)
It compiles without warnings and doesn't break t/t[01]* ;)
-- Hannes
^ 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