From 19de5d6913b9681d2bde533bccc8445c9236a648 Mon Sep 17 00:00:00 2001 From: Kjetil Barvik Date: Wed, 4 Mar 2009 18:47:39 +0100 Subject: [PATCH 01/95] stat_tracking_info(): only count real commits stat_tracking_info() in remote.c is used to collect the statistics to be able to say (for instance) from the output of "git checkout': Your branch and 'foo' have diverged, and have X and Y different commit(s) each, respectively. Currently X and Y also includes the count of merges. This patch excludes the merges from being counted. Signed-off-by: Kjetil Barvik Signed-off-by: Junio C Hamano --- remote.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/remote.c b/remote.c index d7079c6dd8..06c414e118 100644 --- a/remote.c +++ b/remote.c @@ -1310,9 +1310,10 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs) if (theirs == ours) return 0; - /* Run "rev-list --left-right ours...theirs" internally... */ + /* Run "rev-list --no-merges --left-right ours...theirs" internally... */ rev_argc = 0; rev_argv[rev_argc++] = NULL; + rev_argv[rev_argc++] = "--no-merges"; rev_argv[rev_argc++] = "--left-right"; rev_argv[rev_argc++] = symmetric; rev_argv[rev_argc++] = "--"; From a9c37a72c4fbc8537de294d66b05bdfd7f9a4016 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 8 Mar 2009 21:06:05 -0400 Subject: [PATCH 02/95] Use a common function to get the pretty name of refs The result should be consistent between fetch and push, so we ought to use the same code in both cases, even though it's short. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-fetch.c | 6 +----- builtin-send-pack.c | 10 ---------- refs.c | 10 ++++++++++ refs.h | 2 ++ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 1e4a3d9c51..f3bdeda059 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -197,11 +197,7 @@ static int update_local_ref(struct ref *ref, struct commit *current = NULL, *updated; enum object_type type; struct branch *current_branch = branch_get(NULL); - const char *pretty_ref = ref->name + ( - !prefixcmp(ref->name, "refs/heads/") ? 11 : - !prefixcmp(ref->name, "refs/tags/") ? 10 : - !prefixcmp(ref->name, "refs/remotes/") ? 13 : - 0); + const char *pretty_ref = prettify_ref(ref); *display = 0; type = sha1_object_info(ref->new_sha1, NULL); diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 9072905f10..43b89ece36 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -172,16 +172,6 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) } } -static const char *prettify_ref(const struct ref *ref) -{ - const char *name = ref->name; - return name + ( - !prefixcmp(name, "refs/heads/") ? 11 : - !prefixcmp(name, "refs/tags/") ? 10 : - !prefixcmp(name, "refs/remotes/") ? 13 : - 0); -} - #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg) diff --git a/refs.c b/refs.c index b2a37e1185..8f968b51a1 100644 --- a/refs.c +++ b/refs.c @@ -736,6 +736,16 @@ int check_ref_format(const char *ref) } } +const char *prettify_ref(const struct ref *ref) +{ + const char *name = ref->name; + return name + ( + !prefixcmp(name, "refs/heads/") ? 11 : + !prefixcmp(name, "refs/tags/") ? 10 : + !prefixcmp(name, "refs/remotes/") ? 13 : + 0); +} + const char *ref_rev_parse_rules[] = { "%.*s", "refs/%.*s", diff --git a/refs.h b/refs.h index 29bdcecd4e..68c2d16d53 100644 --- a/refs.h +++ b/refs.h @@ -79,6 +79,8 @@ extern int for_each_reflog(each_ref_fn, void *); #define CHECK_REF_FORMAT_WILDCARD (-3) extern int check_ref_format(const char *target); +extern const char *prettify_ref(const struct ref *ref); + /** rename ref, return 0 on success **/ extern int rename_ref(const char *oldref, const char *newref, const char *logmsg); From 64fcef2daa03f6093b480142c6ab2a4173b0b43e Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 8 Mar 2009 21:06:07 -0400 Subject: [PATCH 03/95] Move push matching and reporting logic into transport.c For native-protocol pushes (and other protocols as they are converted to the new method), this moves the refspec match, tracking update, and report message out of send-pack() and into transport_push(), where it can be shared completely with other protocols. This also makes fetch and push more similar in terms of what code is in what file. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 143 +++++++++++----------- send-pack.h | 6 +- transport.c | 283 +++++++++++++++++++++++++++++++++++++++++--- transport.h | 3 +- 4 files changed, 343 insertions(+), 92 deletions(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 43b89ece36..91c36512a8 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -11,7 +11,6 @@ static const char send_pack_usage[] = " --all and explicit specification are mutually exclusive."; static struct send_pack_args args = { - /* .receivepack = */ "git-receive-pack", }; static int feed_object(const unsigned char *sha1, int fd, int negative) @@ -31,7 +30,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative) /* * Make a pack stream and spit it out into file descriptor fd */ -static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra) +static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args) { /* * The child becomes pack-objects --revs; we feed @@ -49,7 +48,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext struct child_process po; int i; - if (args.use_thin_pack) + if (args->use_thin_pack) argv[4] = "--thin"; memset(&po, 0, sizeof(po)); po.argv = argv; @@ -83,8 +82,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext return 0; } -static struct ref *remote_refs, **remote_tail; - static int receive_status(int in, struct ref *refs) { struct ref *hint; @@ -300,27 +297,19 @@ static int refs_pushed(struct ref *ref) return 0; } -static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec) +int send_pack(struct send_pack_args *args, + int fd[], struct child_process *conn, + struct ref *remote_refs, + struct extra_have_objects *extra_have) { - struct ref *ref, *local_refs; + int in = fd[0]; + int out = fd[1]; + struct ref *ref; int new_refs; int ask_for_status_report = 0; int allow_deleting_refs = 0; int expect_status_report = 0; - int flags = MATCH_REFS_NONE; int ret; - struct extra_have_objects extra_have; - - memset(&extra_have, 0, sizeof(extra_have)); - if (args.send_all) - flags |= MATCH_REFS_ALL; - if (args.send_mirror) - flags |= MATCH_REFS_MIRROR; - - /* No funny business with the matcher */ - remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL, - &extra_have); - local_refs = get_local_heads(); /* Does the other end support the reporting? */ if (server_supports("report-status")) @@ -328,19 +317,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest if (server_supports("delete-refs")) allow_deleting_refs = 1; - /* match them up */ - if (!remote_tail) - remote_tail = &remote_refs; - if (match_refs(local_refs, remote_refs, &remote_tail, - nr_refspec, refspec, flags)) { - close(out); - return -1; - } - if (!remote_refs) { fprintf(stderr, "No refs in common and none specified; doing nothing.\n" "Perhaps you should specify a branch such as 'master'.\n"); - close(out); return 0; } @@ -352,7 +331,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest if (ref->peer_ref) hashcpy(ref->new_sha1, ref->peer_ref->new_sha1); - else if (!args.send_mirror) + else if (!args->send_mirror) continue; ref->deletion = is_null_sha1(ref->new_sha1); @@ -391,7 +370,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest (!has_sha1_file(ref->old_sha1) || !ref_newer(ref->new_sha1, ref->old_sha1)); - if (ref->nonfastforward && !ref->force && !args.force_update) { + if (ref->nonfastforward && !ref->force && !args->force_update) { ref->status = REF_STATUS_REJECT_NONFASTFORWARD; continue; } @@ -399,7 +378,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest if (!ref->deletion) new_refs++; - if (!args.dry_run) { + if (!args->dry_run) { char *old_hex = sha1_to_hex(ref->old_sha1); char *new_hex = sha1_to_hex(ref->new_sha1); @@ -420,27 +399,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest } packet_flush(out); - if (new_refs && !args.dry_run) { - if (pack_objects(out, remote_refs, &extra_have) < 0) + if (new_refs && !args->dry_run) { + if (pack_objects(out, remote_refs, extra_have, args) < 0) { + for (ref = remote_refs; ref; ref = ref->next) + ref->status = REF_STATUS_NONE; return -1; + } } - else - close(out); if (expect_status_report) ret = receive_status(in, remote_refs); else ret = 0; - print_push_status(dest, remote_refs); - - if (!args.dry_run && remote) { - for (ref = remote_refs; ref; ref = ref->next) - update_tracking_ref(remote, ref); - } - - if (!refs_pushed(remote_refs)) - fprintf(stderr, "Everything up-to-date\n"); if (ret < 0) return ret; for (ref = remote_refs; ref; ref = ref->next) { @@ -489,11 +460,19 @@ static void verify_remote_names(int nr_heads, const char **heads) int cmd_send_pack(int argc, const char **argv, const char *prefix) { - int i, nr_heads = 0; - const char **heads = NULL; + int i, nr_refspecs = 0; + const char **refspecs = NULL; const char *remote_name = NULL; struct remote *remote = NULL; const char *dest = NULL; + int fd[2]; + struct child_process *conn; + struct extra_have_objects extra_have; + struct ref *remote_refs, **remote_tail, *local_refs; + int ret; + int send_all = 0; + const char *receivepack = "git-receive-pack"; + int flags; argv++; for (i = 1; i < argc; i++, argv++) { @@ -501,11 +480,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) if (*arg == '-') { if (!prefixcmp(arg, "--receive-pack=")) { - args.receivepack = arg + 15; + receivepack = arg + 15; continue; } if (!prefixcmp(arg, "--exec=")) { - args.receivepack = arg + 7; + receivepack = arg + 7; continue; } if (!prefixcmp(arg, "--remote=")) { @@ -513,7 +492,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--all")) { - args.send_all = 1; + send_all = 1; continue; } if (!strcmp(arg, "--dry-run")) { @@ -542,8 +521,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) dest = arg; continue; } - heads = (const char **) argv; - nr_heads = argc - i; + refspecs = (const char **) argv; + nr_refspecs = argc - i; break; } if (!dest) @@ -552,8 +531,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) * --all and --mirror are incompatible; neither makes sense * with any refspecs. */ - if ((heads && (args.send_all || args.send_mirror)) || - (args.send_all && args.send_mirror)) + if ((refspecs && (send_all || args.send_mirror)) || + (send_all && args.send_mirror)) usage(send_pack_usage); if (remote_name) { @@ -564,24 +543,50 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) } } - return send_pack(&args, dest, remote, nr_heads, heads); -} + conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0); -int send_pack(struct send_pack_args *my_args, - const char *dest, struct remote *remote, - int nr_heads, const char **heads) -{ - int fd[2], ret; - struct child_process *conn; + memset(&extra_have, 0, sizeof(extra_have)); - memcpy(&args, my_args, sizeof(args)); + get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL, + &extra_have); - verify_remote_names(nr_heads, heads); + verify_remote_names(nr_refspecs, refspecs); - conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); - ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads); + local_refs = get_local_heads(); + + flags = MATCH_REFS_NONE; + + if (send_all) + flags |= MATCH_REFS_ALL; + if (args.send_mirror) + flags |= MATCH_REFS_MIRROR; + + /* match them up */ + remote_tail = &remote_refs; + while (*remote_tail) + remote_tail = &((*remote_tail)->next); + if (match_refs(local_refs, remote_refs, &remote_tail, + nr_refspecs, refspecs, flags)) { + return -1; + } + + ret = send_pack(&args, fd, conn, remote_refs, &extra_have); + + close(fd[1]); close(fd[0]); - /* do_send_pack always closes fd[1] */ + ret |= finish_connect(conn); - return !!ret; + + print_push_status(dest, remote_refs); + + if (!args.dry_run && remote) { + struct ref *ref; + for (ref = remote_refs; ref; ref = ref->next) + update_tracking_ref(remote, ref); + } + + if (!ret && !refs_pushed(remote_refs)) + fprintf(stderr, "Everything up-to-date\n"); + + return ret; } diff --git a/send-pack.h b/send-pack.h index 8ff1dc3539..83d76c7e35 100644 --- a/send-pack.h +++ b/send-pack.h @@ -2,9 +2,7 @@ #define SEND_PACK_H struct send_pack_args { - const char *receivepack; unsigned verbose:1, - send_all:1, send_mirror:1, force_update:1, use_thin_pack:1, @@ -12,7 +10,7 @@ struct send_pack_args { }; int send_pack(struct send_pack_args *args, - const char *dest, struct remote *remote, - int nr_heads, const char **heads); + int fd[], struct child_process *conn, + struct ref *remote_refs, struct extra_have_objects *extra_have); #endif diff --git a/transport.c b/transport.c index 9ad4a16c31..73bb9b50be 100644 --- a/transport.c +++ b/transport.c @@ -138,7 +138,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) } } -static struct ref *get_refs_via_rsync(struct transport *transport) +static struct ref *get_refs_via_rsync(struct transport *transport, int for_push) { struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT; struct ref dummy, *tail = &dummy; @@ -146,6 +146,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport) const char *args[5]; int temp_dir_len; + if (for_push) + return NULL; + /* copy the refs to the temporary directory */ strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX")); @@ -422,7 +425,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons return !!err; } -static struct ref *get_refs_via_curl(struct transport *transport) +static struct ref *get_refs_via_curl(struct transport *transport, int for_push) { struct strbuf buffer = STRBUF_INIT; char *data, *start, *mid; @@ -439,6 +442,9 @@ static struct ref *get_refs_via_curl(struct transport *transport) struct walker *walker; + if (for_push) + return NULL; + if (!transport->data) transport->data = get_http_walker(transport->url, transport->remote); @@ -525,12 +531,15 @@ struct bundle_transport_data { struct bundle_header header; }; -static struct ref *get_refs_from_bundle(struct transport *transport) +static struct ref *get_refs_from_bundle(struct transport *transport, int for_push) { struct bundle_transport_data *data = transport->data; struct ref *result = NULL; int i; + if (for_push) + return NULL; + if (data->fd > 0) close(data->fd); data->fd = read_bundle_header(transport->url, &data->header); @@ -571,6 +580,7 @@ struct git_transport_data { int fd[2]; const char *uploadpack; const char *receivepack; + struct extra_have_objects extra_have; }; static int set_git_option(struct transport *connection, @@ -602,20 +612,23 @@ static int set_git_option(struct transport *connection, return 1; } -static int connect_setup(struct transport *transport) +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, data->uploadpack, 0); + data->conn = git_connect(data->fd, transport->url, + for_push ? data->receivepack : data->uploadpack, + verbose ? CONNECT_VERBOSE : 0); return 0; } -static struct ref *get_refs_via_connect(struct transport *transport) +static struct ref *get_refs_via_connect(struct transport *transport, int for_push) { struct git_transport_data *data = transport->data; struct ref *refs; - connect_setup(transport); - get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL); + connect_setup(transport, for_push, 0); + get_remote_heads(data->fd[0], &refs, 0, NULL, + for_push ? REF_NORMAL : 0, &data->extra_have); return refs; } @@ -647,7 +660,7 @@ static int fetch_refs_via_pack(struct transport *transport, origh[i] = heads[i] = xstrdup(to_fetch[i]->name); if (!data->conn) { - connect_setup(transport); + connect_setup(transport, 0, 0); get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL); } @@ -670,20 +683,216 @@ static int fetch_refs_via_pack(struct transport *transport, return (refs ? 0 : -1); } -static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) +static int refs_pushed(struct ref *ref) +{ + for (; ref; ref = ref->next) { + switch(ref->status) { + case REF_STATUS_NONE: + case REF_STATUS_UPTODATE: + break; + default: + return 1; + } + } + return 0; +} + +static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) +{ + struct refspec rs; + + if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) + return; + + rs.src = ref->name; + rs.dst = NULL; + + if (!remote_find_tracking(remote, &rs)) { + if (verbose) + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); + if (ref->deletion) { + delete_ref(rs.dst, NULL, 0); + } else + update_ref("update by push", rs.dst, + ref->new_sha1, NULL, 0, 0); + free(rs.dst); + } +} + +#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) + +static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg) +{ + fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary); + if (from) + fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to)); + else + fputs(prettify_ref(to), stderr); + if (msg) { + fputs(" (", stderr); + fputs(msg, stderr); + fputc(')', stderr); + } + fputc('\n', stderr); +} + +static const char *status_abbrev(unsigned char sha1[20]) +{ + return find_unique_abbrev(sha1, DEFAULT_ABBREV); +} + +static void print_ok_ref_status(struct ref *ref) +{ + if (ref->deletion) + print_ref_status('-', "[deleted]", ref, NULL, NULL); + else if (is_null_sha1(ref->old_sha1)) + print_ref_status('*', + (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" : + "[new branch]"), + ref, ref->peer_ref, NULL); + else { + char quickref[84]; + char type; + const char *msg; + + strcpy(quickref, status_abbrev(ref->old_sha1)); + if (ref->nonfastforward) { + strcat(quickref, "..."); + type = '+'; + msg = "forced update"; + } else { + strcat(quickref, ".."); + type = ' '; + msg = NULL; + } + strcat(quickref, status_abbrev(ref->new_sha1)); + + print_ref_status(type, quickref, ref, ref->peer_ref, msg); + } +} + +static int print_one_push_status(struct ref *ref, const char *dest, int count) +{ + if (!count) + fprintf(stderr, "To %s\n", dest); + + switch(ref->status) { + case REF_STATUS_NONE: + print_ref_status('X', "[no match]", ref, NULL, NULL); + break; + case REF_STATUS_REJECT_NODELETE: + print_ref_status('!', "[rejected]", ref, NULL, + "remote does not support deleting refs"); + break; + case REF_STATUS_UPTODATE: + print_ref_status('=', "[up to date]", ref, + ref->peer_ref, NULL); + break; + case REF_STATUS_REJECT_NONFASTFORWARD: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "non-fast forward"); + break; + case REF_STATUS_REMOTE_REJECT: + print_ref_status('!', "[remote rejected]", ref, + ref->deletion ? NULL : ref->peer_ref, + ref->remote_status); + break; + case REF_STATUS_EXPECTING_REPORT: + print_ref_status('!', "[remote failure]", ref, + ref->deletion ? NULL : ref->peer_ref, + "remote failed to report status"); + break; + case REF_STATUS_OK: + print_ok_ref_status(ref); + break; + } + + return 1; +} + +static void print_push_status(const char *dest, struct ref *refs, int verbose) +{ + struct ref *ref; + int n = 0; + + if (verbose) { + for (ref = refs; ref; ref = ref->next) + if (ref->status == REF_STATUS_UPTODATE) + n += print_one_push_status(ref, dest, n); + } + + for (ref = refs; ref; ref = ref->next) + if (ref->status == REF_STATUS_OK) + n += print_one_push_status(ref, dest, n); + + for (ref = refs; ref; ref = ref->next) { + if (ref->status != REF_STATUS_NONE && + ref->status != REF_STATUS_UPTODATE && + ref->status != REF_STATUS_OK) + n += print_one_push_status(ref, dest, n); + } +} + +static void verify_remote_names(int nr_heads, const char **heads) +{ + int i; + + for (i = 0; i < nr_heads; i++) { + const char *local = heads[i]; + const char *remote = strrchr(heads[i], ':'); + + if (*local == '+') + local++; + + /* A matching refspec is okay. */ + if (remote == local && remote[1] == '\0') + continue; + + remote = remote ? (remote + 1) : local; + switch (check_ref_format(remote)) { + case 0: /* ok */ + case CHECK_REF_FORMAT_ONELEVEL: + /* ok but a single level -- that is fine for + * a match pattern. + */ + case CHECK_REF_FORMAT_WILDCARD: + /* ok but ends with a pattern-match character */ + continue; + } + die("remote part of refspec is not a valid name in %s", + heads[i]); + } +} + +static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags) { struct git_transport_data *data = transport->data; struct send_pack_args args; + int ret; + + if (!data->conn) { + struct ref *tmp_refs; + connect_setup(transport, 1, 0); + + get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL, + NULL); + } - args.receivepack = data->receivepack; - args.send_all = !!(flags & TRANSPORT_PUSH_ALL); args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR); args.force_update = !!(flags & TRANSPORT_PUSH_FORCE); args.use_thin_pack = data->thin; args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE); args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN); - return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec); + ret = send_pack(&args, data->fd, data->conn, remote_refs, + &data->extra_have); + + close(data->fd[1]); + close(data->fd[0]); + ret |= finish_connect(data->conn); + data->conn = NULL; + + return ret; } static int disconnect_git(struct transport *transport) @@ -753,7 +962,7 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->set_option = set_git_option; ret->get_refs_list = get_refs_via_connect; ret->fetch = fetch_refs_via_pack; - ret->push = git_transport_push; + ret->push_refs = git_transport_push; ret->disconnect = disconnect_git; data->thin = 1; @@ -780,15 +989,53 @@ int transport_set_option(struct transport *transport, int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { - if (!transport->push) - return 1; - return transport->push(transport, refspec_nr, refspec, flags); + verify_remote_names(refspec_nr, refspec); + + if (transport->push) + return transport->push(transport, refspec_nr, refspec, flags); + if (transport->push_refs) { + struct ref *remote_refs = + transport->get_refs_list(transport, 1); + struct ref **remote_tail; + struct ref *local_refs = get_local_heads(); + int match_flags = MATCH_REFS_NONE; + int verbose = flags & TRANSPORT_PUSH_VERBOSE; + int ret; + + if (flags & TRANSPORT_PUSH_ALL) + match_flags |= MATCH_REFS_ALL; + if (flags & TRANSPORT_PUSH_MIRROR) + match_flags |= MATCH_REFS_MIRROR; + + remote_tail = &remote_refs; + while (*remote_tail) + remote_tail = &((*remote_tail)->next); + if (match_refs(local_refs, remote_refs, &remote_tail, + refspec_nr, refspec, match_flags)) { + return -1; + } + + ret = transport->push_refs(transport, remote_refs, flags); + + print_push_status(transport->url, remote_refs, verbose); + + if (!(flags & TRANSPORT_PUSH_DRY_RUN)) { + struct ref *ref; + for (ref = remote_refs; ref; ref = ref->next) + update_tracking_ref(transport->remote, ref, verbose); + } + + if (!ret && !refs_pushed(remote_refs)) + fprintf(stderr, "Everything up-to-date\n"); + return ret; + } + return 1; } const struct ref *transport_get_remote_refs(struct transport *transport) { if (!transport->remote_refs) - transport->remote_refs = transport->get_refs_list(transport); + transport->remote_refs = transport->get_refs_list(transport, 0); return transport->remote_refs; } diff --git a/transport.h b/transport.h index 6bbc1a8264..b1c2252766 100644 --- a/transport.h +++ b/transport.h @@ -18,8 +18,9 @@ struct transport { int (*set_option)(struct transport *connection, const char *name, const char *value); - struct ref *(*get_refs_list)(struct transport *transport); + struct ref *(*get_refs_list)(struct transport *transport, int for_push); int (*fetch)(struct transport *transport, int refs_nr, const struct ref **refs); + 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 (*disconnect)(struct transport *connection); From 4251ccbd80eff92270503a48d35385516c3d106d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Mar 2009 18:47:29 -0700 Subject: [PATCH 04/95] http.c: style cleanups Signed-off-by: Junio C Hamano --- http.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/http.c b/http.c index 56f18f1b03..d1ead6643d 100644 --- a/http.c +++ b/http.c @@ -1,7 +1,7 @@ #include "http.h" int data_received; -int active_requests = 0; +int active_requests; #ifdef USE_CURL_MULTI static int max_requests = -1; @@ -13,22 +13,22 @@ static CURL *curl_default; char curl_errorstr[CURL_ERROR_SIZE]; static int curl_ssl_verify = -1; -static const char *ssl_cert = NULL; +static const char *ssl_cert; #if LIBCURL_VERSION_NUM >= 0x070902 -static const char *ssl_key = NULL; +static const char *ssl_key; #endif #if LIBCURL_VERSION_NUM >= 0x070908 -static const char *ssl_capath = NULL; +static const char *ssl_capath; #endif -static const char *ssl_cainfo = NULL; +static const char *ssl_cainfo; static long curl_low_speed_limit = -1; static long curl_low_speed_time = -1; -static int curl_ftp_no_epsv = 0; -static const char *curl_http_proxy = NULL; +static int curl_ftp_no_epsv; +static const char *curl_http_proxy; static struct curl_slist *pragma_header; -static struct active_request_slot *active_queue_head = NULL; +static struct active_request_slot *active_queue_head; size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_) { @@ -94,9 +94,8 @@ static void process_curl_messages(void) static int http_options(const char *var, const char *value, void *cb) { if (!strcmp("http.sslverify", var)) { - if (curl_ssl_verify == -1) { + if (curl_ssl_verify == -1) curl_ssl_verify = git_config_bool(var, value); - } return 0; } @@ -158,9 +157,9 @@ static int http_options(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static CURL* get_curl_handle(void) +static CURL *get_curl_handle(void) { - CURL* result = curl_easy_init(); + CURL *result = curl_easy_init(); if (!curl_ssl_verify) { curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0); @@ -322,15 +321,14 @@ struct active_request_slot *get_active_slot(void) /* Wait for a slot to open up if the queue is full */ while (active_requests >= max_requests) { curl_multi_perform(curlm, &num_transfers); - if (num_transfers < active_requests) { + if (num_transfers < active_requests) process_curl_messages(); - } } #endif - while (slot != NULL && slot->in_use) { + while (slot != NULL && slot->in_use) slot = slot->next; - } + if (slot == NULL) { newslot = xmalloc(sizeof(*newslot)); newslot->curl = NULL; @@ -341,9 +339,8 @@ struct active_request_slot *get_active_slot(void) if (slot == NULL) { active_queue_head = newslot; } else { - while (slot->next != NULL) { + while (slot->next != NULL) slot = slot->next; - } slot->next = newslot; } slot = newslot; @@ -404,7 +401,7 @@ struct fill_chain { struct fill_chain *next; }; -static struct fill_chain *fill_cfg = NULL; +static struct fill_chain *fill_cfg; void add_fill_function(void *data, int (*fill)(void *)) { @@ -535,9 +532,8 @@ static void finish_active_slot(struct active_request_slot *slot) } /* Run callback if appropriate */ - if (slot->callback_func != NULL) { + if (slot->callback_func != NULL) slot->callback_func(slot->callback_data); - } } void finish_all_active_slots(void) @@ -567,8 +563,10 @@ static inline int needs_quote(int ch) static inline int hex(int v) { - if (v < 10) return '0' + v; - else return 'A' + v - 10; + if (v < 10) + return '0' + v; + else + return 'A' + v - 10; } static char *quote_ref_url(const char *base, const char *ref) From 7059cd99fc671f9594b61cee7d10d69704f3ebe2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Mar 2009 19:00:30 -0700 Subject: [PATCH 05/95] http_init(): Fix config file parsing We honor the command line options, environment variables, variables in repository configuration file, variables in user's global configuration file, variables in the system configuration file, and then finally use built-in default. To implement this semantics, the code should: - start from built-in default values; - call git_config() with the configuration parser callback, which implements "later definition overrides earlier ones" logic (git_config() reads the system's, user's and then repository's configuration file in this order); - override the result from the above with environment variables if set; - override the result from the above with command line options. The initialization code http_init() for http transfer got this wrong, and implemented a "first one wins, ignoring the later ones" in http_options(), to compensate this mistake, read environment variables before calling git_config(). This is all wrong. As a second class citizen, the http codepath hasn't been audited as closely as other parts of the system, but we should try to bring sanity to it, before inviting contributors to improve on it. Signed-off-by: Junio C Hamano --- http.c | 69 +++++++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/http.c b/http.c index d1ead6643d..4c4614c92f 100644 --- a/http.c +++ b/http.c @@ -94,52 +94,33 @@ static void process_curl_messages(void) static int http_options(const char *var, const char *value, void *cb) { if (!strcmp("http.sslverify", var)) { - if (curl_ssl_verify == -1) - curl_ssl_verify = git_config_bool(var, value); - return 0; - } - - if (!strcmp("http.sslcert", var)) { - if (ssl_cert == NULL) - return git_config_string(&ssl_cert, var, value); + curl_ssl_verify = git_config_bool(var, value); return 0; } + if (!strcmp("http.sslcert", var)) + return git_config_string(&ssl_cert, var, value); #if LIBCURL_VERSION_NUM >= 0x070902 - if (!strcmp("http.sslkey", var)) { - if (ssl_key == NULL) - return git_config_string(&ssl_key, var, value); - return 0; - } + if (!strcmp("http.sslkey", var)) + return git_config_string(&ssl_key, var, value); #endif #if LIBCURL_VERSION_NUM >= 0x070908 - if (!strcmp("http.sslcapath", var)) { - if (ssl_capath == NULL) - return git_config_string(&ssl_capath, var, value); - return 0; - } + if (!strcmp("http.sslcapath", var)) + return git_config_string(&ssl_capath, var, value); #endif - if (!strcmp("http.sslcainfo", var)) { - if (ssl_cainfo == NULL) - return git_config_string(&ssl_cainfo, var, value); - return 0; - } - + if (!strcmp("http.sslcainfo", var)) + return git_config_string(&ssl_cainfo, var, value); #ifdef USE_CURL_MULTI if (!strcmp("http.maxrequests", var)) { - if (max_requests == -1) - max_requests = git_config_int(var, value); + max_requests = git_config_int(var, value); return 0; } #endif - if (!strcmp("http.lowspeedlimit", var)) { - if (curl_low_speed_limit == -1) - curl_low_speed_limit = (long)git_config_int(var, value); + curl_low_speed_limit = (long)git_config_int(var, value); return 0; } if (!strcmp("http.lowspeedtime", var)) { - if (curl_low_speed_time == -1) - curl_low_speed_time = (long)git_config_int(var, value); + curl_low_speed_time = (long)git_config_int(var, value); return 0; } @@ -147,11 +128,8 @@ static int http_options(const char *var, const char *value, void *cb) curl_ftp_no_epsv = git_config_bool(var, value); return 0; } - if (!strcmp("http.proxy", var)) { - if (curl_http_proxy == NULL) - return git_config_string(&curl_http_proxy, var, value); - return 0; - } + if (!strcmp("http.proxy", var)) + return git_config_string(&curl_http_proxy, var, value); /* Fall back on the default ones */ return git_default_config(var, value, cb); @@ -212,11 +190,20 @@ static CURL *get_curl_handle(void) return result; } +static void set_from_env(const char **var, const char *envname) +{ + const char *val = getenv(envname); + if (val) + *var = val; +} + void http_init(struct remote *remote) { char *low_speed_limit; char *low_speed_time; + git_config(http_options, NULL); + curl_global_init(CURL_GLOBAL_ALL); if (remote && remote->http_proxy) @@ -241,14 +228,14 @@ void http_init(struct remote *remote) if (getenv("GIT_SSL_NO_VERIFY")) curl_ssl_verify = 0; - ssl_cert = getenv("GIT_SSL_CERT"); + set_from_env(&ssl_cert, "GIT_SSL_CERT"); #if LIBCURL_VERSION_NUM >= 0x070902 - ssl_key = getenv("GIT_SSL_KEY"); + set_from_env(&ssl_key, "GIT_SSL_KEY"); #endif #if LIBCURL_VERSION_NUM >= 0x070908 - ssl_capath = getenv("GIT_SSL_CAPATH"); + set_from_env(&ssl_capath, "GIT_SSL_CAPATH"); #endif - ssl_cainfo = getenv("GIT_SSL_CAINFO"); + set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO"); low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT"); if (low_speed_limit != NULL) @@ -257,8 +244,6 @@ void http_init(struct remote *remote) if (low_speed_time != NULL) curl_low_speed_time = strtol(low_speed_time, NULL, 10); - git_config(http_options, NULL); - if (curl_ssl_verify == -1) curl_ssl_verify = 1; From c33976cbc6d1895fca5c1683fba678e786ee3e58 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Mar 2009 23:34:25 -0700 Subject: [PATCH 06/95] http authentication via prompts Curl is designed not to ask for password when only username is given in the URL, but has a way for application to feed a (username, password) pair to it. With this patch, you do not have to keep your password in plaintext in your $HOME/.netrc file when talking with a password protected URL with http://@/path/to/repository.git/ syntax. The code handles only the http-walker side, not the push side. At least, not yet. But interested parties can add support for it. Signed-off-by: Junio C Hamano --- http.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/http.c b/http.c index 4c4614c92f..b8f947e405 100644 --- a/http.c +++ b/http.c @@ -25,6 +25,7 @@ static long curl_low_speed_limit = -1; static long curl_low_speed_time = -1; static int curl_ftp_no_epsv; static const char *curl_http_proxy; +static char *user_name, *user_pass; static struct curl_slist *pragma_header; @@ -135,6 +136,20 @@ static int http_options(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } +static void init_curl_http_auth(CURL *result) +{ + if (!user_name) + curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); + else { + struct strbuf up = STRBUF_INIT; + if (!user_pass) + user_pass = xstrdup(getpass("Password: ")); + strbuf_addf(&up, "%s:%s", user_name, user_pass); + curl_easy_setopt(result, CURLOPT_USERPWD, + strbuf_detach(&up, NULL)); + } +} + static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); @@ -153,6 +168,8 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); #endif + init_curl_http_auth(result); + if (ssl_cert != NULL) curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert); #if LIBCURL_VERSION_NUM >= 0x070902 @@ -190,6 +207,46 @@ static CURL *get_curl_handle(void) return result; } +static void http_auth_init(const char *url) +{ + char *at, *colon, *cp, *slash; + int len; + + cp = strstr(url, "://"); + if (!cp) + return; + + /* + * Ok, the URL looks like "proto://something". Which one? + * "proto://:@/...", + * "proto://@/...", or just + * "proto:///..."? + */ + cp += 3; + at = strchr(cp, '@'); + colon = strchr(cp, ':'); + slash = strchrnul(cp, '/'); + if (!at || slash <= at) + return; /* No credentials */ + if (!colon || at <= colon) { + /* Only username */ + len = at - cp; + user_name = xmalloc(len + 1); + memcpy(user_name, cp, len); + user_name[len] = '\0'; + user_pass = NULL; + } else { + len = colon - cp; + user_name = xmalloc(len + 1); + memcpy(user_name, cp, len); + user_name[len] = '\0'; + len = at - (colon + 1); + user_pass = xmalloc(len + 1); + memcpy(user_pass, colon + 1, len); + user_pass[len] = '\0'; + } +} + static void set_from_env(const char **var, const char *envname) { const char *val = getenv(envname); @@ -255,6 +312,9 @@ void http_init(struct remote *remote) if (getenv("GIT_CURL_FTP_NO_EPSV")) curl_ftp_no_epsv = 1; + if (remote && remote->url && remote->url[0]) + http_auth_init(remote->url[0]); + #ifndef NO_CURL_EASY_DUPHANDLE curl_default = get_curl_handle(); #endif From 750d9305009a0f3fd14c0b5c5e62ae1eb2b18fda Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 12 Mar 2009 22:34:43 -0700 Subject: [PATCH 07/95] http.c: CURLOPT_NETRC_OPTIONAL is not available in ancient versions of cURL Besides, we have already called easy_setopt with the option before coming to this function if it was available, so there is no need to repeat it here. Signed-off-by: Junio C Hamano --- http.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/http.c b/http.c index b8f947e405..2fc55d671e 100644 --- a/http.c +++ b/http.c @@ -138,9 +138,7 @@ static int http_options(const char *var, const char *value, void *cb) static void init_curl_http_auth(CURL *result) { - if (!user_name) - curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); - else { + if (user_name) { struct strbuf up = STRBUF_INIT; if (!user_pass) user_pass = xstrdup(getpass("Password: ")); From 06f33c1735bf76e02f3e2601cde5161e969872a7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 13 Mar 2009 21:24:08 -0700 Subject: [PATCH 08/95] Read attributes from the index that is being checked out Traditionally we used .gitattributes file from the work tree if exists, and otherwise read from the index as a fallback. When switching to a branch that has an updated .gitattributes file, and entries in it give different attributes to other paths being checked out, we should instead read from the .gitattributes in the index. This breaks a use case of fixing incorrect entries in the .gitattributes in the work tree (without adding it to the index) and checking other paths out, though. $ edit .gitattributes ;# mark foo.dat as binary $ rm foo.dat $ git checkout foo.dat Signed-off-by: Junio C Hamano --- attr.c | 73 +++++++++++++++++++++++++++++++++++++------------- attr.h | 6 +++++ unpack-trees.c | 3 +++ 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/attr.c b/attr.c index 17f6a4dca5..43259e5b01 100644 --- a/attr.c +++ b/attr.c @@ -1,3 +1,4 @@ +#define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "attr.h" @@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list) return res; } +static enum git_attr_direction direction; +static struct index_state *use_index; + static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) { FILE *fp = fopen(path, "r"); @@ -340,9 +344,10 @@ static void *read_index_data(const char *path) unsigned long sz; enum object_type type; void *data; + struct index_state *istate = use_index ? use_index : &the_index; len = strlen(path); - pos = cache_name_pos(path, len); + pos = index_name_pos(istate, path, len); if (pos < 0) { /* * We might be in the middle of a merge, in which @@ -350,15 +355,15 @@ static void *read_index_data(const char *path) */ int i; for (i = -pos - 1; - (pos < 0 && i < active_nr && - !strcmp(active_cache[i]->name, path)); + (pos < 0 && i < istate->cache_nr && + !strcmp(istate->cache[i]->name, path)); i++) - if (ce_stage(active_cache[i]) == 2) + if (ce_stage(istate->cache[i]) == 2) pos = i; } if (pos < 0) return NULL; - data = read_sha1_file(active_cache[pos]->sha1, &type, &sz); + data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz); if (!data || type != OBJ_BLOB) { free(data); return NULL; @@ -366,27 +371,17 @@ static void *read_index_data(const char *path) return data; } -static struct attr_stack *read_attr(const char *path, int macro_ok) +static struct attr_stack *read_attr_from_index(const char *path, int macro_ok) { struct attr_stack *res; char *buf, *sp; int lineno = 0; - res = read_attr_from_file(path, macro_ok); - if (res) - return res; - - res = xcalloc(1, sizeof(*res)); - - /* - * There is no checked out .gitattributes file there, but - * we might have it in the index. We allow operation in a - * sparsely checked out work tree, so read from it. - */ buf = read_index_data(path); if (!buf) - return res; + return NULL; + res = xcalloc(1, sizeof(*res)); for (sp = buf; *sp; ) { char *ep; int more; @@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok) return res; } +static struct attr_stack *read_attr(const char *path, int macro_ok) +{ + struct attr_stack *res; + + if (direction == GIT_ATTR_CHECKOUT) { + res = read_attr_from_index(path, macro_ok); + if (!res) + res = read_attr_from_file(path, macro_ok); + } + else { + res = read_attr_from_file(path, macro_ok); + if (!res) + /* + * There is no checked out .gitattributes file there, but + * we might have it in the index. We allow operation in a + * sparsely checked out work tree, so read from it. + */ + res = read_attr_from_index(path, macro_ok); + } + if (!res) + res = xcalloc(1, sizeof(*res)); + return res; +} + #if DEBUG_ATTR static void debug_info(const char *what, struct attr_stack *elem) { @@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr #define debug_set(a,b,c,d) do { ; } while (0) #endif +static void drop_attr_stack(void) +{ + while (attr_stack) { + struct attr_stack *elem = attr_stack; + attr_stack = elem->prev; + free_attr_elem(elem); + } +} + static void bootstrap_attr_stack(void) { if (!attr_stack) { @@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) return 0; } + +void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate) +{ + enum git_attr_direction old = direction; + direction = new; + if (new != old) + drop_attr_stack(); + use_index = istate; +} diff --git a/attr.h b/attr.h index f1c2038b09..3a2f4ec1a0 100644 --- a/attr.h +++ b/attr.h @@ -31,4 +31,10 @@ struct git_attr_check { int git_checkattr(const char *path, int, struct git_attr_check *); +enum git_attr_direction { + GIT_ATTR_CHECKIN, + GIT_ATTR_CHECKOUT +}; +void git_attr_set_direction(enum git_attr_direction, struct index_state *); + #endif /* ATTR_H */ diff --git a/unpack-trees.c b/unpack-trees.c index e547282ed5..661218c5ae 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -7,6 +7,7 @@ #include "unpack-trees.h" #include "progress.h" #include "refs.h" +#include "attr.h" /* * Error messages expected by scripts out of plumbing commands such as @@ -105,6 +106,7 @@ static int check_updates(struct unpack_trees_options *o) cnt = 0; } + git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result); for (i = 0; i < index->cache_nr; i++) { struct cache_entry *ce = index->cache[i]; @@ -130,6 +132,7 @@ static int check_updates(struct unpack_trees_options *o) } } stop_progress(&progress); + git_attr_set_direction(GIT_ATTR_CHECKIN, NULL); return errs != 0; } From 521537476fe99b97bfcdf1b8f0c579061af5fd3e Mon Sep 17 00:00:00 2001 From: Finn Arne Gangstad Date: Mon, 16 Mar 2009 16:42:51 +0100 Subject: [PATCH 09/95] New config push.default to decide default behavior for push When "git push" is not told what refspecs to push, it pushes all matching branches to the current remote. For some workflows this default is not useful, and surprises new users. Some have even found that this default behaviour is too easy to trigger by accident with unwanted consequences. Introduce a new configuration variable "push.default" that decides what action git push should take if no refspecs are given or implied by the command line arguments or the current remote configuration. Possible values are: 'nothing' : Push nothing; 'matching' : Current default behaviour, push all branches that already exist in the current remote; 'tracking' : Push the current branch to whatever it is tracking; 'current' : Push the current branch to a branch of the same name, i.e. HEAD. Signed-off-by: Finn Arne Gangstad Signed-off-by: Junio C Hamano --- Documentation/config.txt | 18 ++++++++++++++ builtin-push.c | 53 ++++++++++++++++++++++++++++++++++++---- cache.h | 9 +++++++ config.c | 28 +++++++++++++++++++++ environment.c | 1 + 5 files changed, 104 insertions(+), 5 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index f5152c5038..7b2b3f44aa 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1160,6 +1160,24 @@ pull.octopus:: pull.twohead:: The default merge strategy to use when pulling a single branch. +push.default:: + Defines the action git push should take if no refspec is given + on the command line, no refspec is configured in the remote, and + no refspec is implied by any of the options given on the command + line. ++ +The term `current remote` means the remote configured for the current +branch, or `origin` if no remote is configured. `origin` is also used +if you are not on any branch. Possible values are: ++ +* `nothing` do not push anything. +* `matching` push all matching branches to the current remote. + All branches having the same name in both ends are considered to be + matching. This is the current default value. +* `tracking` push the current branch to the branch it is tracking. +* `current` push the current branch to a branch of the same name on the + current remote. + receive.fsckObjects:: If it is set to true, git-receive-pack will check all received objects. It will abort in the case of a malformed object or a diff --git a/builtin-push.c b/builtin-push.c index 122fdcfbdc..45fe843b20 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -48,6 +48,48 @@ static void set_refspecs(const char **refs, int nr) } } +static void setup_push_tracking(void) +{ + struct strbuf refspec = STRBUF_INIT; + struct branch *branch = branch_get(NULL); + if (!branch) + die("You are not currently on a branch."); + if (!branch->merge_nr) + die("The current branch %s is not tracking anything.", + branch->name); + if (branch->merge_nr != 1) + die("The current branch %s is tracking multiple branches, " + "refusing to push.", branch->name); + strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); + add_refspec(refspec.buf); +} + +static void setup_default_push_refspecs(void) +{ + git_config(git_default_config, NULL); + switch (push_default) { + case PUSH_DEFAULT_UNSPECIFIED: + /* fallthrough */ + + case PUSH_DEFAULT_MATCHING: + add_refspec(":"); + break; + + case PUSH_DEFAULT_TRACKING: + setup_push_tracking(); + break; + + case PUSH_DEFAULT_CURRENT: + add_refspec("HEAD"); + break; + + case PUSH_DEFAULT_NOTHING: + die("You didn't specify any refspecs to push, and " + "push.default is \"nothing\"."); + break; + } +} + static int do_push(const char *repo, int flags) { int i, errs; @@ -76,11 +118,12 @@ static int do_push(const char *repo, int flags) return error("--all and --mirror are incompatible"); } - if (!refspec - && !(flags & TRANSPORT_PUSH_ALL) - && remote->push_refspec_nr) { - refspec = remote->push_refspec; - refspec_nr = remote->push_refspec_nr; + if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) { + if (remote->push_refspec_nr) { + refspec = remote->push_refspec; + refspec_nr = remote->push_refspec_nr; + } else if (!(flags & TRANSPORT_PUSH_MIRROR)) + setup_default_push_refspecs(); } errs = 0; for (i = 0; i < remote->url_nr; i++) { diff --git a/cache.h b/cache.h index 189151de25..df4f117ac6 100644 --- a/cache.h +++ b/cache.h @@ -541,8 +541,17 @@ enum rebase_setup_type { AUTOREBASE_ALWAYS, }; +enum push_default_type { + PUSH_DEFAULT_UNSPECIFIED = -1, + PUSH_DEFAULT_NOTHING = 0, + PUSH_DEFAULT_MATCHING, + PUSH_DEFAULT_TRACKING, + PUSH_DEFAULT_CURRENT, +}; + extern enum branch_track git_branch_track; extern enum rebase_setup_type autorebase; +extern enum push_default_type push_default; #define GIT_REPO_VERSION 0 extern int repository_format_version; diff --git a/config.c b/config.c index 0c8c76f13b..30443e3279 100644 --- a/config.c +++ b/config.c @@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value) return 0; } +static int git_default_push_config(const char *var, const char *value) +{ + if (!strcmp(var, "push.default")) { + if (!value) + return config_error_nonbool(var); + else if (!strcmp(value, "nothing")) + push_default = PUSH_DEFAULT_NOTHING; + else if (!strcmp(value, "matching")) + push_default = PUSH_DEFAULT_MATCHING; + else if (!strcmp(value, "tracking")) + push_default = PUSH_DEFAULT_TRACKING; + else if (!strcmp(value, "current")) + push_default = PUSH_DEFAULT_CURRENT; + else { + error("Malformed value for %s: %s", var, value); + return error("Must be one of nothing, matching, " + "tracking or current."); + } + return 0; + } + + /* Add other config variables here and to Documentation/config.txt. */ + return 0; +} + static int git_default_mailmap_config(const char *var, const char *value) { if (!strcmp(var, "mailmap.file")) @@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy) if (!prefixcmp(var, "branch.")) return git_default_branch_config(var, value); + if (!prefixcmp(var, "push.")) + return git_default_push_config(var, value); + if (!prefixcmp(var, "mailmap.")) return git_default_mailmap_config(var, value); diff --git a/environment.c b/environment.c index e278bce0ea..4696885b22 100644 --- a/environment.c +++ b/environment.c @@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN; unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; enum branch_track git_branch_track = BRANCH_TRACK_REMOTE; enum rebase_setup_type autorebase = AUTOREBASE_NEVER; +enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; /* Parallel index stat data preload? */ int core_preload_index = 0; From 665d3e8f057b90d7b43d70db75b9ac5506bd204d Mon Sep 17 00:00:00 2001 From: Finn Arne Gangstad Date: Mon, 16 Mar 2009 16:42:52 +0100 Subject: [PATCH 10/95] Display warning for default git push with no push.default config If a git push without any refspecs is attempted, display a warning. The current default behavior is to push all matching refspecs, which may come as a surprise to new users, so the warning shows how push.default can be configured and what the possible values are. Traditionalists who wish to keep the current behaviour are also told how to configure this once and never see the warning again. Signed-off-by: Finn Arne Gangstad Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.3.txt | 7 +++++++ builtin-push.c | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Documentation/RelNotes-1.6.3.txt b/Documentation/RelNotes-1.6.3.txt index ee1fddb76a..7c02b2a305 100644 --- a/Documentation/RelNotes-1.6.3.txt +++ b/Documentation/RelNotes-1.6.3.txt @@ -22,6 +22,13 @@ branch pointed at by its HEAD, gets a large warning. You can choose what should happen upon such a push by setting the configuration variable receive.denyDeleteCurrent in the receiving repository. +In a future release, the default of "git push" without further +arguments might be changed. Currently, it will push all matching +refspecs to the current remote. A configuration variable push.default +has been introduced to select the default behaviour. To ease the +transition, a big warning is issued if this is not configured and a +git push without arguments is attempted. + Updates since v1.6.2 -------------------- diff --git a/builtin-push.c b/builtin-push.c index 45fe843b20..8f4fa5b09e 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -64,11 +64,34 @@ static void setup_push_tracking(void) add_refspec(refspec.buf); } +static const char *warn_unconfigured_push_msg[] = { + "You did not specify any refspecs to push, and the current remote", + "has not configured any push refspecs. The default action in this", + "case is to push all matching refspecs, that is, all branches", + "that exist both locally and remotely will be updated. This may", + "not necessarily be what you want to happen.", + "", + "You can specify what action you want to take in this case, and", + "avoid seeing this message again, by configuring 'push.default' to:", + " 'nothing' : Do not push anythig", + " 'matching' : Push all matching branches (default)", + " 'tracking' : Push the current branch to whatever it is tracking", + " 'current' : Push the current branch" +}; + +static void warn_unconfigured_push(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++) + warning("%s", warn_unconfigured_push_msg[i]); +} + static void setup_default_push_refspecs(void) { git_config(git_default_config, NULL); switch (push_default) { case PUSH_DEFAULT_UNSPECIFIED: + warn_unconfigured_push(); /* fallthrough */ case PUSH_DEFAULT_MATCHING: From aa9ea77de4fffd133b3da1d36a19fd0bd11ad368 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 18 Mar 2009 00:13:03 -0700 Subject: [PATCH 11/95] blame: read custom grafts given by -S before calling setup_revisions() setup_revisions() while getting the command line arguments parses the given commits from the command line, which means their direct parents will not be rewritten by the custom graft file. Call read_ancestry() early to work around this issue. Signed-off-by: Junio C Hamano --- builtin-blame.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index 4ea343189f..0c241a9ec8 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2346,6 +2346,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix) parse_done: argc = parse_options_end(&ctx); + if (revs_file && read_ancestry(revs_file)) + die("reading graft file %s failed: %s", + revs_file, strerror(errno)); + if (DIFF_OPT_TST(&revs.diffopt, FIND_COPIES_HARDER)) opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE | PICKAXE_BLAME_COPY_HARDER); @@ -2484,10 +2488,6 @@ parse_done: sb.ent = ent; sb.path = path; - if (revs_file && read_ancestry(revs_file)) - die("reading graft file %s failed: %s", - revs_file, strerror(errno)); - read_mailmap(&mailmap, ".mailmap", NULL); if (!incremental) From 7b5201a60d8f00e7026a3fc4cfdd7852caa9882f Mon Sep 17 00:00:00 2001 From: Amos King Date: Wed, 18 Mar 2009 18:43:53 -0500 Subject: [PATCH 12/95] Do not name "repo" struct "remote" in push_http.c This patch is a first step in getting http-push to use http authentication via prompts. The patch renames remote to repo so that it doesn't get confusing with the same remote that is passed around when using http. Signed-off-by: Amos King Signed-off-by: Junio C Hamano --- http-push.c | 152 ++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/http-push.c b/http-push.c index 30d2d34041..dfbb247cfc 100644 --- a/http-push.c +++ b/http-push.c @@ -97,7 +97,7 @@ struct repo struct remote_lock *locks; }; -static struct repo *remote; +static struct repo *repo; enum transfer_state { NEED_FETCH, @@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request) git_SHA1_Init(&request->c); - url = get_remote_object_url(remote->url, hex, 0); + url = get_remote_object_url(repo->url, hex, 0); request->url = xstrdup(url); /* If a previous temp file is present, process what was already @@ -389,7 +389,7 @@ static void start_fetch_loose(struct transfer_request *request) request->state = RUN_FETCH_LOOSE; if (!start_active_slot(slot)) { fprintf(stderr, "Unable to start GET request\n"); - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; release_request(request); } } @@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request) char *hex = sha1_to_hex(request->obj->sha1); struct active_request_slot *slot; - request->url = get_remote_object_url(remote->url, hex, 1); + request->url = get_remote_object_url(repo->url, hex, 1); slot = get_active_slot(); slot->callback_func = process_response; @@ -434,10 +434,10 @@ static void start_fetch_packed(struct transfer_request *request) struct transfer_request *check_request = request_queue_head; struct active_request_slot *slot; - target = find_sha1_pack(request->obj->sha1, remote->packs); + target = find_sha1_pack(request->obj->sha1, repo->packs); if (!target) { fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1)); - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; release_request(request); return; } @@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request) snprintf(request->tmpfile, sizeof(request->tmpfile), "%s.temp", filename); - url = xmalloc(strlen(remote->url) + 64); + url = xmalloc(strlen(repo->url) + 64); sprintf(url, "%sobjects/pack/pack-%s.pack", - remote->url, sha1_to_hex(target->sha1)); + repo->url, sha1_to_hex(target->sha1)); /* Make sure there isn't another open request for this pack */ while (check_request) { @@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request) if (!packfile) { fprintf(stderr, "Unable to open local file %s for pack", request->tmpfile); - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; free(url); return; } @@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request) request->state = RUN_FETCH_PACKED; if (!start_active_slot(slot)) { fprintf(stderr, "Unable to start GET request\n"); - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; release_request(request); } } @@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request) request->buffer.buf.len = stream.total_out; strbuf_addstr(&buf, "Destination: "); - append_remote_object_url(&buf, remote->url, hex, 0); + append_remote_object_url(&buf, repo->url, hex, 0); request->dest = strbuf_detach(&buf, NULL); - append_remote_object_url(&buf, remote->url, hex, 0); + append_remote_object_url(&buf, repo->url, hex, 0); strbuf_add(&buf, request->lock->tmpfile_suffix, 41); request->url = strbuf_detach(&buf, NULL); @@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock) static void check_locks(void) { - struct remote_lock *lock = remote->locks; + struct remote_lock *lock = repo->locks; time_t current_time = time(NULL); int time_remaining; @@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request) if (request->curl_result != CURLE_OK) { fprintf(stderr, "Unable to get pack file %s\n%s", request->url, curl_errorstr); - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; } else { off_t pack_size = ftell(request->local_stream); @@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request) request->filename)) { target = (struct packed_git *)request->userData; target->pack_size = pack_size; - lst = &remote->packs; + lst = &repo->packs; while (*lst != target) lst = &((*lst)->next); *lst = (*lst)->next; @@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request) if (!verify_pack(target)) install_packed_git(target); else - remote->can_update_info_refs = 0; + repo->can_update_info_refs = 0; } } release_request(request); @@ -889,7 +889,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) get_remote_object_list(obj->sha1[0]); if (obj->flags & (REMOTE | PUSHING)) return 0; - target = find_sha1_pack(obj->sha1, remote->packs); + target = find_sha1_pack(obj->sha1, repo->packs); if (target) { obj->flags |= REMOTE; return 0; @@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1) struct slot_results results; /* Don't use the index if the pack isn't there */ - url = xmalloc(strlen(remote->url) + 64); - sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex); + url = xmalloc(strlen(repo->url) + 64); + sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex); slot = get_active_slot(); slot->results = &results; curl_easy_setopt(slot->curl, CURLOPT_URL, url); @@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1) if (push_verbosely) fprintf(stderr, "Getting index for pack %s\n", hex); - sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex); + sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex); filename = sha1_pack_index_name(sha1); snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); @@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1) return -1; new_pack = parse_pack_index(sha1); - new_pack->next = remote->packs; - remote->packs = new_pack; + new_pack->next = repo->packs; + repo->packs = new_pack; return 0; } @@ -1037,8 +1037,8 @@ static int fetch_indices(void) if (push_verbosely) fprintf(stderr, "Getting pack list\n"); - url = xmalloc(strlen(remote->url) + 20); - sprintf(url, "%sobjects/info/packs", remote->url); + url = xmalloc(strlen(repo->url) + 20); + sprintf(url, "%sobjects/info/packs", repo->url); slot = get_active_slot(); slot->results = &results; @@ -1223,11 +1223,11 @@ static struct remote_lock *lock_remote(const char *path, long timeout) struct curl_slist *dav_headers = NULL; struct xml_ctx ctx; - url = xmalloc(strlen(remote->url) + strlen(path) + 1); - sprintf(url, "%s%s", remote->url, path); + url = xmalloc(strlen(repo->url) + strlen(path) + 1); + sprintf(url, "%s%s", repo->url, path); /* Make sure leading directories exist for the remote ref */ - ep = strchr(url + strlen(remote->url) + 1, '/'); + ep = strchr(url + strlen(repo->url) + 1, '/'); while (ep) { char saved_character = ep[1]; ep[1] = '\0'; @@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout) } else { lock->url = url; lock->start_time = time(NULL); - lock->next = remote->locks; - remote->locks = lock; + lock->next = repo->locks; + repo->locks = lock; } return lock; @@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock) { struct active_request_slot *slot; struct slot_results results; - struct remote_lock *prev = remote->locks; + struct remote_lock *prev = repo->locks; struct curl_slist *dav_headers; int rc = 0; @@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock) curl_slist_free_all(dav_headers); - if (remote->locks == lock) { - remote->locks = lock->next; + if (repo->locks == lock) { + repo->locks = lock->next; } else { while (prev && prev->next != lock) prev = prev->next; @@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock) static void remove_locks(void) { - struct remote_lock *lock = remote->locks; + struct remote_lock *lock = repo->locks; fprintf(stderr, "Removing remote locks...\n"); while (lock) { @@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed) } } if (path) { - path += remote->path_len; + path += repo->path_len; ls->dentry_name = xstrdup(path); } } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) { @@ -1480,7 +1480,7 @@ static void remote_ls(const char *path, int flags, void (*userFunc)(struct remote_ls_ctx *ls), void *userData) { - char *url = xmalloc(strlen(remote->url) + strlen(path) + 1); + char *url = xmalloc(strlen(repo->url) + strlen(path) + 1); struct active_request_slot *slot; struct slot_results results; struct strbuf in_buffer = STRBUF_INIT; @@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags, ls.userData = userData; ls.userFunc = userFunc; - sprintf(url, "%s%s", remote->url, path); + sprintf(url, "%s%s", repo->url, path); strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST); @@ -1574,7 +1574,7 @@ static int locking_available(void) struct xml_ctx ctx; int lock_flags = 0; - strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url); + strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url); dav_headers = curl_slist_append(dav_headers, "Depth: 0"); dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); @@ -1586,7 +1586,7 @@ static int locking_available(void) curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer); curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); - curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url); + curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url); curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1); curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); @@ -1617,15 +1617,15 @@ static int locking_available(void) XML_ParserFree(parser); if (!lock_flags) error("Error: no DAV locking support on %s", - remote->url); + repo->url); } else { error("Cannot access URL %s, return code %d", - remote->url, results.curl_result); + repo->url, results.curl_result); lock_flags = 0; } } else { - error("Unable to start PROPFIND request on %s", remote->url); + error("Unable to start PROPFIND request on %s", repo->url); } strbuf_release(&out_buffer.buf); @@ -1814,10 +1814,10 @@ static void one_remote_ref(char *refname) ref = alloc_ref(refname); - if (http_fetch_ref(remote->url, ref) != 0) { + if (http_fetch_ref(repo->url, ref) != 0) { fprintf(stderr, "Unable to fetch ref %s from %s\n", - refname, remote->url); + refname, repo->url); free(ref); return; } @@ -1826,7 +1826,7 @@ static void one_remote_ref(char *refname) * Fetch a copy of the object if it doesn't exist locally - it * may be required for updating server info later. */ - if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) { + if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) { obj = lookup_unknown_object(ref->old_sha1); if (obj) { fprintf(stderr, " fetch %s for %s\n", @@ -1921,10 +1921,10 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls) ref = alloc_ref(ls->dentry_name); - if (http_fetch_ref(remote->url, ref) != 0) { + if (http_fetch_ref(repo->url, ref) != 0) { fprintf(stderr, "Unable to fetch ref %s from %s\n", - ls->dentry_name, remote->url); + ls->dentry_name, repo->url); aborted = 1; free(ref); return; @@ -1999,12 +1999,12 @@ static void update_remote_info_refs(struct remote_lock *lock) static int remote_exists(const char *path) { - char *url = xmalloc(strlen(remote->url) + strlen(path) + 1); + char *url = xmalloc(strlen(repo->url) + strlen(path) + 1); struct active_request_slot *slot; struct slot_results results; int ret = -1; - sprintf(url, "%s%s", remote->url, path); + sprintf(url, "%s%s", repo->url, path); slot = get_active_slot(); slot->results = &results; @@ -2034,8 +2034,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) struct active_request_slot *slot; struct slot_results results; - url = xmalloc(strlen(remote->url) + strlen(path) + 1); - sprintf(url, "%s%s", remote->url, path); + url = xmalloc(strlen(repo->url) + strlen(path) + 1); + sprintf(url, "%s%s", repo->url, path); slot = get_active_slot(); slot->results = &results; @@ -2150,7 +2150,7 @@ static int delete_remote_branch(char *pattern, int force) "of your current HEAD.\n" "If you are sure you want to delete it," " run:\n\t'git http-push -D %s %s'", - remote_ref->name, remote->url, pattern); + remote_ref->name, repo->url, pattern); } } @@ -2158,8 +2158,8 @@ static int delete_remote_branch(char *pattern, int force) fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name); if (dry_run) return 0; - url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1); - sprintf(url, "%s%s", remote->url, remote_ref->name); + url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1); + sprintf(url, "%s%s", repo->url, remote_ref->name); slot = get_active_slot(); slot->results = &results; curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); @@ -2202,7 +2202,7 @@ int main(int argc, char **argv) setup_git_directory(); - remote = xcalloc(sizeof(*remote), 1); + repo = xcalloc(sizeof(*repo), 1); argv++; for (i = 1; i < argc; i++, argv++) { @@ -2235,14 +2235,14 @@ int main(int argc, char **argv) continue; } } - if (!remote->url) { + if (!repo->url) { char *path = strstr(arg, "//"); - remote->url = arg; - remote->path_len = strlen(arg); + repo->url = arg; + repo->path_len = strlen(arg); if (path) { - remote->path = strchr(path+2, '/'); - if (remote->path) - remote->path_len = strlen(remote->path); + repo->path = strchr(path+2, '/'); + if (repo->path) + repo->path_len = strlen(repo->path); } continue; } @@ -2255,7 +2255,7 @@ int main(int argc, char **argv) die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI"); #endif - if (!remote->url) + if (!repo->url) usage(http_push_usage); if (delete_branch && nr_refspec != 1) @@ -2267,13 +2267,13 @@ int main(int argc, char **argv) no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); - if (remote->url && remote->url[strlen(remote->url)-1] != '/') { - rewritten_url = xmalloc(strlen(remote->url)+2); - strcpy(rewritten_url, remote->url); + if (repo->url && repo->url[strlen(repo->url)-1] != '/') { + rewritten_url = xmalloc(strlen(repo->url)+2); + strcpy(rewritten_url, repo->url); strcat(rewritten_url, "/"); - remote->path = rewritten_url + (remote->path - remote->url); - remote->path_len++; - remote->url = rewritten_url; + repo->path = rewritten_url + (repo->path - repo->url); + repo->path_len++; + repo->url = rewritten_url; } /* Verify DAV compliance/lock support */ @@ -2285,20 +2285,20 @@ int main(int argc, char **argv) sigchain_push_common(remove_locks_on_signal); /* Check whether the remote has server info files */ - remote->can_update_info_refs = 0; - remote->has_info_refs = remote_exists("info/refs"); - remote->has_info_packs = remote_exists("objects/info/packs"); - if (remote->has_info_refs) { + repo->can_update_info_refs = 0; + repo->has_info_refs = remote_exists("info/refs"); + repo->has_info_packs = remote_exists("objects/info/packs"); + if (repo->has_info_refs) { info_ref_lock = lock_remote("info/refs", LOCK_TIME); if (info_ref_lock) - remote->can_update_info_refs = 1; + repo->can_update_info_refs = 1; else { fprintf(stderr, "Error: cannot lock existing info/refs\n"); rc = 1; goto cleanup; } } - if (remote->has_info_packs) + if (repo->has_info_packs) fetch_indices(); /* Get a list of all local and remote heads to validate refspecs */ @@ -2456,8 +2456,8 @@ int main(int argc, char **argv) } /* Update remote server info if appropriate */ - if (remote->has_info_refs && new_refs) { - if (info_ref_lock && remote->can_update_info_refs) { + if (repo->has_info_refs && new_refs) { + if (info_ref_lock && repo->can_update_info_refs) { fprintf(stderr, "Updating remote server info\n"); if (!dry_run) update_remote_info_refs(info_ref_lock); @@ -2470,7 +2470,7 @@ int main(int argc, char **argv) free(rewritten_url); if (info_ref_lock) unlock_remote(info_ref_lock); - free(remote); + free(repo); curl_slist_free_all(no_pragma_header); From 44d808c238f0817fc3ae7caea8f3b625b6180e37 Mon Sep 17 00:00:00 2001 From: Amos King Date: Wed, 18 Mar 2009 18:46:41 -0500 Subject: [PATCH 13/95] http-push.c: use a faux remote to pass to http_init This patch allows http_push to use http authentication via prompts. You may notice that there is a remote struct that only contains the url from the repo struct. This struct is a temporary fix for a larger issue, but gets http authentication via prompts out the door, and keeps users from having to store passwords in plain text files. Signed-off-by: Amos King Signed-off-by: Junio C Hamano --- http-push.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/http-push.c b/http-push.c index dfbb247cfc..962934858e 100644 --- a/http-push.c +++ b/http-push.c @@ -2196,6 +2196,7 @@ int main(int argc, char **argv) int i; int new_refs; struct ref *ref; + struct remote *remote; char *rewritten_url = NULL; git_extract_argv0_path(argv[0]); @@ -2263,7 +2264,14 @@ int main(int argc, char **argv) memset(remote_dir_exists, -1, 256); - http_init(NULL); + /* + * Create a minimum remote by hand to give to http_init(), + * primarily to allow it to look at the URL. + */ + remote = xcalloc(sizeof(*remote), 1); + ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc); + remote->url[remote->url_nr++] = repo->url; + http_init(remote); no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); From cd4371208a0e9f882f6fd4b4dd28d6911848ec79 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 20 Mar 2009 02:00:43 -0400 Subject: [PATCH 14/95] make oneline reflog dates more consistent with multiline format The multiline reflog format (e.g., as shown by "git log -g") will show HEAD@{} rather than HEAD@{} in two situations: 1. If the user gave branch@{} syntax to specify the reflog 2. If the user gave a --date= specifier It uses the "normal" date format in case 1, and the user-specified format in case 2. The oneline reflog format (e.g., "git reflog show" or "git log -g --oneline") will show the date in the same two circumstances. However, it _always_ shows the date as a relative date, and it always ignores the timezone. In case 2, it seems ridiculous to trigger the date but use a format totally different from what the user requested. For case 1, it is arguable that the user might want to see the relative date by default; however, the multiline version shows the normal format. This patch does three things: - refactors the "relative_date" parameter to show_reflog_message to be an actual date_mode enum, since this is how it is used (it is passed to show_date) - uses the passed date_mode parameter in the oneline format (making it consistent with the multiline format) - does not ignore the timezone parameter in oneline mode Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- reflog-walk.c | 12 ++++---- reflog-walk.h | 5 +++- t/t1411-reflog-show.sh | 67 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100755 t/t1411-reflog-show.sh diff --git a/reflog-walk.c b/reflog-walk.c index f751fdc8d8..fd065f4e1a 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -242,7 +242,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) } void show_reflog_message(struct reflog_walk_info* info, int oneline, - int relative_date) + enum date_mode dmode) { if (info && info->last_commit_reflog) { struct commit_reflog *commit_reflog = info->last_commit_reflog; @@ -251,8 +251,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline, info = &commit_reflog->reflogs->items[commit_reflog->recno+1]; if (oneline) { printf("%s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || relative_date) - printf("%s", show_date(info->timestamp, 0, 1)); + if (commit_reflog->flag || dmode) + printf("%s", show_date(info->timestamp, + info->tz, + dmode)); else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); @@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline, } else { printf("Reflog: %s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || relative_date) + if (commit_reflog->flag || dmode) printf("%s", show_date(info->timestamp, info->tz, - relative_date)); + dmode)); else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); diff --git a/reflog-walk.h b/reflog-walk.h index 7ca1438f4d..74c90964bd 100644 --- a/reflog-walk.h +++ b/reflog-walk.h @@ -1,11 +1,14 @@ #ifndef REFLOG_WALK_H #define REFLOG_WALK_H +#include "cache.h" + extern void init_reflog_walk(struct reflog_walk_info** info); extern int add_reflog_for_walk(struct reflog_walk_info *info, struct commit *commit, const char *name); extern void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit); -extern void show_reflog_message(struct reflog_walk_info *info, int, int); +extern void show_reflog_message(struct reflog_walk_info *info, int, + enum date_mode); #endif diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh new file mode 100755 index 0000000000..c18ed8edf9 --- /dev/null +++ b/t/t1411-reflog-show.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='Test reflog display routines' +. ./test-lib.sh + +test_expect_success 'setup' ' + echo content >file && + git add file && + test_tick && + git commit -m one +' + +cat >expect <<'EOF' +Reflog: HEAD@{0} (C O Mitter ) +Reflog message: commit (initial): one +EOF +test_expect_success 'log -g shows reflog headers' ' + git log -g -1 >tmp && + grep ^Reflog actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{0}: commit (initial): one +EOF +test_expect_success 'oneline reflog format' ' + git log -g -1 --oneline >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter ) +Reflog message: commit (initial): one +EOF +test_expect_success 'using @{now} syntax shows reflog date (multiline)' ' + git log -g -1 HEAD@{now} >tmp && + grep ^Reflog actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one +EOF +test_expect_success 'using @{now} syntax shows reflog date (oneline)' ' + git log -g -1 --oneline HEAD@{now} >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Reflog: HEAD@{1112911993 -0700} (C O Mitter ) +Reflog message: commit (initial): one +EOF +test_expect_success 'using --date= shows reflog date (multiline)' ' + git log -g -1 --date=raw >tmp && + grep ^Reflog actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{1112911993 -0700}: commit (initial): one +EOF +test_expect_success 'using --date= shows reflog date (oneline)' ' + git log -g -1 --oneline --date=raw >actual && + test_cmp expect actual +' + +test_done From b997045e01c2f12ac7dc44c487915f8e50da4d4d Mon Sep 17 00:00:00 2001 From: Kristian Amlie Date: Fri, 20 Mar 2009 10:32:09 +0100 Subject: [PATCH 15/95] Add a test for checking whether gitattributes is honored by checkout. The original bug will not honor new entries in gitattributes if they are changed in the same checkout as the files they affect. It will also keep using .gitattributes, even if it is deleted in the same commit as the files it affects. Signed-off-by: Junio C Hamano --- t/t0020-crlf.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 1be7446d8d..4e72b53140 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' ' } ' +test_expect_success 'checkout with existing .gitattributes' ' + + git config core.autocrlf true && + git config --unset core.safecrlf && + echo ".file2 -crlfQ" | q_to_cr >> .gitattributes && + git add .gitattributes && + git commit -m initial && + echo ".file -crlfQ" | q_to_cr >> .gitattributes && + echo "contents" > .file && + git add .gitattributes .file && + git commit -m second && + + git checkout master~1 && + git checkout master && + test "$(git diff-files --raw)" = "" + +' + +test_expect_success 'checkout when deleting .gitattributes' ' + + git rm .gitattributes && + echo "contentsQ" | q_to_cr > .file2 && + git add .file2 && + git commit -m third + + git checkout master~1 && + git checkout master && + remove_cr .file2 >/dev/null + +' + test_expect_success 'invalid .gitattributes (must not crash)' ' echo "three +crlf" >>.gitattributes && From 92cd872202241a0b80e88dadac5a4db071c8d1fa Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 19 Mar 2009 22:47:50 -0500 Subject: [PATCH 16/95] t7700-repack: add two new tests demonstrating repacking flaws 1) The new --kept-pack-only mechansim of rev-list/pack-objects has replaced --unpacked=. This new mechansim does not operate solely on "local" packs now. The result is that objects residing in an alternate pack which has a .keep file will not be repacked with repack -a. This flaw is only apparent when a commit object is the one residing in an alternate kept pack. 2) The 'repack unpacked objects' and 'loosen unpacked objects' mechanisms of pack-objects, i.e. --keep-unreachable and --unpack-unreachable, now do not operate solely on local packs. The --keep-unreachable option no longer has any callers, but --unpack-unreachable is used when repack is called with '-A -d' and the local repo has existing packs. In this case, objects residing in alternate, not-kept packs will be loosened, and then immediately deleted by repack's call to prune-packed. The test must manually call pack-objects to avoid the call to prune-packed that is made by repack when -d is used. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- t/t7700-repack.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 3f602ea7de..fa4772101f 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -69,5 +69,49 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is done ' +test_expect_failure 'packed obs in alternate ODB kept pack are repacked' ' + # swap the .keep so the commit object is in the pack with .keep + for p in alt_objects/pack/*.pack + do + base_name=$(basename $p .pack) + if test -f alt_objects/pack/$base_name.keep + then + rm alt_objects/pack/$base_name.keep + else + touch alt_objects/pack/$base_name.keep + fi + done + git repack -a -d && + myidx=$(ls -1 .git/objects/pack/*.idx) && + test -f "$myidx" && + for p in alt_objects/pack/*.idx; do + git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p" + done | while read sha1 rest; do + if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then + echo "Missing object in local pack: $sha1" + return 1 + fi + done +' + +test_expect_failure 'packed unreachable obs in alternate ODB are not loosened' ' + rm -f alt_objects/pack/*.keep && + mv .git/objects/pack/* alt_objects/pack/ && + csha1=$(git rev-parse HEAD^{commit}) && + git reset --hard HEAD^ && + sleep 1 && + git reflog expire --expire=now --expire-unreachable=now --all && + # The pack-objects call on the next line is equivalent to + # git repack -A -d without the call to prune-packed + git pack-objects --honor-pack-keep --non-empty --all --reflog \ + --unpack-unreachable .git/objects/info/alternates && + test_must_fail git show $csha1 +' + test_done From 171110a4a67f04c28d2ac89385ab88ba051fc780 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 19 Mar 2009 22:47:51 -0500 Subject: [PATCH 17/95] git-repack.sh: don't use --kept-pack-only option to pack-objects The --kept-pack-only option to pack-objects treats all kept packs as equal. This results in objects that reside in an alternate pack that has a .keep file, not being packed into a newly created pack when the user specifies the -a option to repack. Since the user may not have any control over the alternate database, git should not refrain from repacking those objects even though they are in a pack with a .keep file. This fixes the 'packed obs in alternate ODB kept pack are repacked' test in t7700. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- git-repack.sh | 6 +----- t/t7700-repack.sh | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/git-repack.sh b/git-repack.sh index a736009c67..e02bf27aa6 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -71,11 +71,7 @@ case ",$all_into_one," in existing="$existing $e" fi done - if test -n "$existing" - then - args="--kept-pack-only" - fi - if test -n "$args" -a -n "$unpack_unreachable" -a \ + if test -n "$existing" -a -n "$unpack_unreachable" -a \ -n "$remove_redundant" then args="$args $unpack_unreachable" diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index fa4772101f..adba8a1c65 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -69,7 +69,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is done ' -test_expect_failure 'packed obs in alternate ODB kept pack are repacked' ' +test_expect_success 'packed obs in alternate ODB kept pack are repacked' ' # swap the .keep so the commit object is in the pack with .keep for p in alt_objects/pack/*.pack do From 79bc4c715516fdb393d107359327c1e7fbb8bf04 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 19 Mar 2009 22:47:52 -0500 Subject: [PATCH 18/95] pack-objects: only repack or loosen objects residing in "local" packs These two features were invented for use by repack when repack will delete the local packs that have been made redundant. The packs accessible through alternates are not deleted by repack, so the objects contained in them are still accessible after the local packs are deleted. They do not need to be repacked into the new pack or loosened. For the case of loosening they would immediately be deleted by the subsequent prune-packed that is called by repack anyway. This fixes the test 'packed unreachable obs in alternate ODB are not loosened' in t7700. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 4 ++-- t/t7700-repack.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index b2e46264ee..aae4d243b3 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1915,7 +1915,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs) const unsigned char *sha1; struct object *o; - if (p->pack_keep) + if (!p->pack_local || p->pack_keep) continue; if (open_pack_index(p)) die("cannot open pack index"); @@ -1951,7 +1951,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs) const unsigned char *sha1; for (p = packed_git; p; p = p->next) { - if (p->pack_keep) + if (!p->pack_local || p->pack_keep) continue; if (open_pack_index(p)) diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index adba8a1c65..1ef3892f92 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -94,7 +94,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' ' done ' -test_expect_failure 'packed unreachable obs in alternate ODB are not loosened' ' +test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' rm -f alt_objects/pack/*.keep && mv .git/objects/pack/* alt_objects/pack/ && csha1=$(git rev-parse HEAD^{commit}) && From 4d6acb70411cd4fe69610cf1b22f186fa01614f7 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 19 Mar 2009 22:47:54 -0500 Subject: [PATCH 19/95] Remove --kept-pack-only option and associated infrastructure This option to pack-objects/rev-list was created to improve the -A and -a options of repack. It was found to be lacking in that it did not provide the ability to differentiate between local and non-local kept packs, and found to be unnecessary since objects residing in local kept packs can be filtered out by the --honor-pack-keep option. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 1 - cache.h | 1 - revision.c | 9 +-------- revision.h | 1 - sha1_file.c | 21 +-------------------- 5 files changed, 2 insertions(+), 31 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index aae4d243b3..6222f19c78 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -2149,7 +2149,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) continue; } if (!strcmp("--unpacked", arg) || - !strcmp("--kept-pack-only", arg) || !strcmp("--reflog", arg) || !strcmp("--all", arg)) { use_internal_rev_list = 1; diff --git a/cache.h b/cache.h index 0a3d523d26..23c16d0d99 100644 --- a/cache.h +++ b/cache.h @@ -566,7 +566,6 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l extern int move_temp_to_file(const char *tmpfile, const char *filename); extern int has_sha1_pack(const unsigned char *sha1); -extern int has_sha1_kept_pack(const unsigned char *sha1); extern int has_sha1_file(const unsigned char *sha1); extern int has_loose_object_nonlocal(const unsigned char *sha1); diff --git a/revision.c b/revision.c index 6d8ac46081..50a5b5f394 100644 --- a/revision.c +++ b/revision.c @@ -1062,10 +1062,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->edge_hint = 1; } else if (!strcmp(arg, "--unpacked")) { revs->unpacked = 1; - revs->kept_pack_only = 0; - } else if (!strcmp(arg, "--kept-pack-only")) { - revs->unpacked = 1; - revs->kept_pack_only = 1; } else if (!prefixcmp(arg, "--unpacked=")) { die("--unpacked= no longer supported."); } else if (!strcmp(arg, "-r")) { @@ -1475,10 +1471,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) { if (commit->object.flags & SHOWN) return commit_ignore; - if (revs->unpacked && - (revs->kept_pack_only - ? has_sha1_kept_pack(commit->object.sha1) - : has_sha1_pack(commit->object.sha1))) + if (revs->unpacked && has_sha1_pack(commit->object.sha1)) return commit_ignore; if (revs->show_all) return commit_show; diff --git a/revision.h b/revision.h index b9fa9c2a67..1d322759aa 100644 --- a/revision.h +++ b/revision.h @@ -48,7 +48,6 @@ struct rev_info { edge_hint:1, limited:1, unpacked:1, - kept_pack_only:1, boundary:2, left_right:1, rewrite_parents:1, diff --git a/sha1_file.c b/sha1_file.c index 7ead56cc3e..500fd93127 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1856,8 +1856,7 @@ off_t find_pack_entry_one(const unsigned char *sha1, return 0; } -static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e, - int kept_pack_only) +static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) { static struct packed_git *last_found = (void *)1; struct packed_git *p; @@ -1869,8 +1868,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e, p = (last_found == (void *)1) ? packed_git : last_found; do { - if (kept_pack_only && !p->pack_keep) - goto next; if (p->num_bad_objects) { unsigned i; for (i = 0; i < p->num_bad_objects; i++) @@ -1910,16 +1907,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e, return 0; } -static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) -{ - return find_pack_ent(sha1, e, 0); -} - -static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e) -{ - return find_pack_ent(sha1, e, 1); -} - struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs) { @@ -2387,12 +2374,6 @@ int has_sha1_pack(const unsigned char *sha1) return find_pack_entry(sha1, &e); } -int has_sha1_kept_pack(const unsigned char *sha1) -{ - struct pack_entry e; - return find_kept_pack_entry(sha1, &e); -} - int has_sha1_file(const unsigned char *sha1) { struct pack_entry e; From 76aac715465b7678ca5b834ccbdcb88a3ab8a9f4 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Sat, 21 Mar 2009 19:09:17 -0500 Subject: [PATCH 20/95] git-branch: display "was sha1" on branch deletion rather than just "sha1" Make it more pleasant to read about a branch deletion by adding "was". Jeff King suggested this, and I ignored it. He was right. Update t3200 test again to match the change in output. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-branch.c | 2 +- t/t3200-branch.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index 02fa38fd3b..23b6949fec 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -165,7 +165,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) ret = 1; } else { struct strbuf buf = STRBUF_INIT; - printf("Deleted %sbranch %s (%s).\n", remote, argv[i], + printf("Deleted %sbranch %s (was %s).\n", remote, argv[i], find_unique_abbrev(sha1, DEFAULT_ABBREV)); strbuf_addf(&buf, "branch.%s", argv[i]); if (git_config_rename_section(buf.buf, NULL) < 0) diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 61a2010f5b..1b1e9ece57 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -195,7 +195,7 @@ test_expect_success 'test deleting branch deletes branch config' \ test_expect_success 'test deleting branch without config' \ 'git branch my7 s && sha1=$(git rev-parse my7 | cut -c 1-7) && - test "$(git branch -d my7 2>&1)" = "Deleted branch my7 ($sha1)."' + test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."' test_expect_success 'test --track without .fetch entries' \ 'git branch --track my8 && From 869a3d34c1aea92a10bc8eaa994bd55f4b0b04f2 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Sat, 21 Mar 2009 17:25:30 -0500 Subject: [PATCH 21/95] t7700: demonstrate repack flaw which may loosen objects unnecessarily If an unreferenced object exists in both a local pack and in either a pack residing in an alternate object database or a local kept pack, then the pack-objects call made by repack will loosen that object only to have it immediately pruned by repack's call to prune-packed. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- t/t7700-repack.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 1ef3892f92..013e488bdd 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -113,5 +113,22 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' test_must_fail git show $csha1 ' +test_expect_failure 'local packed unreachable obs that exist in alternate ODB are not loosened' ' + echo `pwd`/alt_objects > .git/objects/info/alternates && + echo "$csha1" | git pack-objects --non-empty --all --reflog pack && + rm -f .git/objects/pack/* && + mv pack-* .git/objects/pack/ && + # The pack-objects call on the next line is equivalent to + # git repack -A -d without the call to prune-packed + git pack-objects --honor-pack-keep --non-empty --all --reflog \ + --unpack-unreachable .git/objects/info/alternates && + test_must_fail git show $csha1 +' + test_done From c90d565a46a664663467557d381417a3153fe26e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sat, 21 Mar 2009 23:21:18 +0100 Subject: [PATCH 22/95] Propagate --exec-path setting to external commands via GIT_EXEC_PATH Let PATH0=$PATH that was set before the invocation. Let /foo be a build directory. Let /pfx be the installation prefix. Let pfxexecpath=/pfx/libexec/git-core. The following is going on when 'git --exec-path=/foo gc' is invoked: 1. git sets PATH=/foo:$PATH0 using the path from --exec-path 2. gc execs 'git repack' (note: no dash). 3. Since there is a git in /foo (it's a build directory), /foo/git is taken. 4. No explicit exec-path is set this time, hence, this secondary git sets PATH=$pfxexecpath:/foo:$PATH 5. Since 'repack' is not a built-in, execv_dashed_external execs 'git-repack' (note: dash). 6. There is a $pfxexecpath/git-repack, and it is taken. 7. This git-repack runs 'git pack-objects' (note: no dash). 8. There is no git in $pfxexecpath, but there is one in /foo. Hence, /foo/git is run. 9. pack-objects is a builtin, hence, in effect /foo/git-pack-objects is run. As you can see, the way in which we previously set the PATH allowed to mix gits of different vintage. By setting GIT_EXEC_PATH when --exec-path was given on the command line, we reduce the confusion. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- exec_cmd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exec_cmd.c b/exec_cmd.c index ce6741eb68..589059f026 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -25,6 +25,10 @@ void git_set_argv0_path(const char *path) void git_set_argv_exec_path(const char *exec_path) { argv_exec_path = exec_path; + /* + * Propagate this setting to external programs. + */ + setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1); } From 094085e3362c592c932b41525ed37152ec171192 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Sat, 21 Mar 2009 17:26:11 -0500 Subject: [PATCH 23/95] pack-objects: don't loosen objects available in alternate or kept packs If pack-objects is called with the --unpack-unreachable option then it will unpack (i.e. loosen) all unreferenced objects from local not-kept packs, including those that also exist in packs residing in an alternate object database or a locally kept pack. The only user of this option is git-repack. In this case, repack will follow the call to pack-objects with a call to prune-packed, which will delete these newly loosened objects, making the act of loosening a waste of time. The unnecessary loosening can be avoided by checking whether an object exists in a non-local pack or a locally kept pack before loosening it. This fixes the 'local packed unreachable obs that exist in alternate ODB are not loosened' test in t7700. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 26 +++++++++++++++++++++++++- t/t7700-repack.sh | 2 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 6222f19c78..ad3f8e7751 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1944,6 +1944,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs) free(in_pack.array); } +static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1) +{ + static struct packed_git *last_found = (void *)1; + struct packed_git *p; + + p = (last_found != (void *)1) ? last_found : packed_git; + + while (p) { + if ((!p->pack_local || p->pack_keep) && + find_pack_entry_one(sha1, p)) { + last_found = p; + return 1; + } + if (p == last_found) + p = packed_git; + else + p = p->next; + if (p == last_found) + p = p->next; + } + return 0; +} + static void loosen_unused_packed_objects(struct rev_info *revs) { struct packed_git *p; @@ -1959,7 +1982,8 @@ static void loosen_unused_packed_objects(struct rev_info *revs) for (i = 0; i < p->num_objects; i++) { sha1 = nth_packed_object_sha1(p, i); - if (!locate_object_entry(sha1)) + if (!locate_object_entry(sha1) && + !has_sha1_pack_kept_or_nonlocal(sha1)) if (force_object_loose(sha1, p->mtime)) die("unable to force loose object"); } diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 013e488bdd..9ce546e3b2 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -113,7 +113,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' test_must_fail git show $csha1 ' -test_expect_failure 'local packed unreachable obs that exist in alternate ODB are not loosened' ' +test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' ' echo `pwd`/alt_objects > .git/objects/info/alternates && echo "$csha1" | git pack-objects --non-empty --all --reflog pack && rm -f .git/objects/pack/* && From 48ef563641d1904f8da2c6fffe700fe6276af8dd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 22 Mar 2009 04:59:20 -0400 Subject: [PATCH 24/95] remote: improve sorting of "configure for git push" list The data structure used to store this list is a string_list of sources with the destination in the util member. The current code just sorts on the source; if a single source is pushed to two different destination refs at a remote, then the order in which they are printed is non-deterministic. This patch implements a comparison using both fields. Besides being a little nicer on the eyes, giving a stable sort prevents false negatives in the test suite when comparing output. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-remote.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/builtin-remote.c b/builtin-remote.c index 7b31e554e9..9fdbb6c103 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -931,6 +931,20 @@ int add_push_to_show_info(struct string_list_item *push_item, void *cb_data) return 0; } +/* + * Sorting comparison for a string list that has push_info + * structs in its util field + */ +static int cmp_string_with_push(const void *va, const void *vb) +{ + const struct string_list_item *a = va; + const struct string_list_item *b = vb; + const struct push_info *a_push = a->util; + const struct push_info *b_push = b->util; + int cmp = strcmp(a->string, b->string); + return cmp ? cmp : strcmp(a_push->dest, b_push->dest); +} + int show_push_info_item(struct string_list_item *item, void *cb_data) { struct show_info *show_info = cb_data; @@ -1041,7 +1055,8 @@ static int show(int argc, const char **argv) info.width = info.width2 = 0; for_each_string_list(add_push_to_show_info, &states.push, &info); - sort_string_list(info.list); + qsort(info.list->items, info.list->nr, + sizeof(*info.list->items), cmp_string_with_push); if (info.list->nr) printf(" Local ref%s configured for 'git push'%s:\n", info.list->nr > 1 ? "s" : "", From 24c11552cb3bd7ec343c8061c87b07aa7abbad00 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sun, 22 Mar 2009 19:46:38 +0100 Subject: [PATCH 25/95] githooks documentation: post-checkout hook is also called after clone The documentation of the post-checkout hook just talks about git-checkout. But recently git-clone was changed to call it too, unless the -no-checkout (-n) option is used. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- Documentation/githooks.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 1fd512bca2..1c736738cc 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -151,6 +151,10 @@ indicating whether the checkout was a branch checkout (changing branches, flag=1) or a file checkout (retrieving a file from the index, flag=0). This hook cannot affect the outcome of 'git-checkout'. +It is also run after 'git-clone', unless the --no-checkout (-n) option is +used. The first parameter given to the hook is the null-ref, the second the +ref of the new HEAD and the flag is always 1. + This hook can be used to perform repository validity checks, auto-display differences from the previous HEAD if different, or set working dir metadata properties. From 4e218f54b3de6aa8ef7d15020c4507031a519f7d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 21 Mar 2009 12:42:52 +0100 Subject: [PATCH 26/95] Smudge the files fed to external diff and textconv When preparing temporary files for an external diff or textconv, it is easier on the external tools, especially when they are implemented using platform tools, if they are fed the input after convert_to_working_tree(). This fixes msysGit issue 177. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 13 ++++++++++--- t/t4020-diff-external.sh | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/diff.c b/diff.c index 006aa017e2..11798af0c1 100644 --- a/diff.c +++ b/diff.c @@ -1948,17 +1948,23 @@ void diff_free_filespec_data(struct diff_filespec *s) s->cnt_data = NULL; } -static void prep_temp_blob(struct diff_tempfile *temp, +static void prep_temp_blob(const char *path, struct diff_tempfile *temp, void *blob, unsigned long size, const unsigned char *sha1, int mode) { int fd; + struct strbuf buf = STRBUF_INIT; fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX"); if (fd < 0) die("unable to create temp-file: %s", strerror(errno)); + if (convert_to_working_tree(path, + (const char *)blob, (size_t)size, &buf)) { + blob = buf.buf; + size = buf.len; + } if (write_in_full(fd, blob, size) != size) die("unable to write temp-file"); close(fd); @@ -1966,6 +1972,7 @@ static void prep_temp_blob(struct diff_tempfile *temp, strcpy(temp->hex, sha1_to_hex(sha1)); temp->hex[40] = 0; sprintf(temp->mode, "%06o", mode); + strbuf_release(&buf); } static struct diff_tempfile *prepare_temp_file(const char *name, @@ -2006,7 +2013,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, die("readlink(%s)", name); if (ret == sizeof(buf)) die("symlink too long: %s", name); - prep_temp_blob(temp, buf, ret, + prep_temp_blob(name, temp, buf, ret, (one->sha1_valid ? one->sha1 : null_sha1), (one->sha1_valid ? @@ -2032,7 +2039,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, else { if (diff_populate_filespec(one, 0)) die("cannot read data blob for %s", one->path); - prep_temp_blob(temp, one->data, one->size, + prep_temp_blob(name, temp, one->data, one->size, one->sha1, one->mode); } return temp; diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 281680d95a..f8c99f1a98 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -136,4 +136,20 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' ' GIT_EXTERNAL_DIFF=echo git diff ' +echo "#!$SHELL_PATH" >fake-diff.sh +cat >> fake-diff.sh <<\EOF +cat $2 >> crlfed.txt +EOF +chmod a+x fake-diff.sh + +keep_only_cr () { + tr -dc '\015' +} + +test_expect_success 'external diff with autocrlf = true' ' + git config core.autocrlf true && + GIT_EXTERNAL_DIFF=./fake-diff.sh git diff && + test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c) +' + test_done From 150115aded2e1e0a83db7366f59e4b5bf1aa8135 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 22 Mar 2009 15:26:07 -0700 Subject: [PATCH 27/95] diff --cached: do not borrow from a work tree when a path is marked as assume-unchanged When the index says that the file in the work tree that corresponds to the blob object that is used for comparison is known to be unchanged, "diff" reads from the file and applies convert_to_git(), instead of inflating the object, to feed the internal diff engine with, because an earlier benchnark found that it tends to be faster to use this optimization. However, the index can lie when the path is marked as assume-unchanged. Disable the optimization for such paths. Signed-off-by: Junio C Hamano --- diff.c | 10 +++++++++- t/t4020-diff-external.sh | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/diff.c b/diff.c index bf5d5f15a3..c2d277a52d 100644 --- a/diff.c +++ b/diff.c @@ -1687,7 +1687,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int struct stat st; int pos, len; - /* We do not read the cache ourselves here, because the + /* + * We do not read the cache ourselves here, because the * benchmark with my previous version that always reads cache * shows that it makes things worse for diff-tree comparing * two linux-2.6 kernel trees in an already checked out work @@ -1727,6 +1728,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode)) return 0; + /* + * If ce is marked as "assume unchanged", there is no + * guarantee that work tree matches what we are looking for. + */ + if (ce->ce_flags & CE_VALID) + return 0; + /* * If ce matches the file in the work tree, we can reuse it. */ diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 637b4e19d5..f853b8a894 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -107,4 +107,12 @@ test_expect_success 'force diff with "diff"' ' test_cmp ../t4020/diff.NUL actual ' +test_expect_success 'diff --cached' ' + git add file && + git update-index --assume-unchanged file && + echo second >file && + git diff --cached >actual && + test_cmp ../t4020/diff.NUL actual +' + test_done From a42dea3281898b06be687f6763e1a52b898ac2d8 Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Sun, 22 Mar 2009 20:11:10 -0700 Subject: [PATCH 28/95] Documentation: remove some uses of the passive voice in git-bisect.txt Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index ec9594eda3..f74354f0fe 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -81,7 +81,7 @@ will have been left with the first bad kernel revision in "refs/bisect/bad". Bisect reset ~~~~~~~~~~~~ -To return to the original head after a bisect session, you issue the +To return to the original head after a bisect session, issue the following command: ------------------------------------------------ @@ -95,8 +95,8 @@ the bisection state). Bisect visualize ~~~~~~~~~~~~~~~~ -To see the currently remaining suspects in 'gitk', the following command -is issued during the bisection process: +To see the currently remaining suspects in 'gitk', issue the following +command during the bisection process: ------------ $ git bisect visualize @@ -115,7 +115,7 @@ $ git bisect view --stat Bisect log and bisect replay ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -After having marked revisions as good or bad, you issue the following +After having marked revisions as good or bad, issue the following command to show what has been done so far: ------------ @@ -135,7 +135,7 @@ $ git bisect replay that-file Avoiding testing a commit ~~~~~~~~~~~~~~~~~~~~~~~~~ -If in the middle of a bisect session, you know that the next suggested +If, in the middle of a bisect session, you know that the next suggested revision is not a good one to test (e.g. the change the commit introduces is known not to work in your environment and you know it does not have anything to do with the bug you are chasing), you may @@ -151,8 +151,8 @@ $ git reset --hard HEAD~3 # try 3 revisions before what # was suggested ------------ -Then compile and test the chosen revision. Afterwards the revision -is marked as good or bad in the usual manner. +Then you compile and test the chosen revision. Afterwards you mark +the revision as good or bad in the usual manner. Bisect skip ~~~~~~~~~~~~ @@ -175,8 +175,8 @@ using the "''..''" notation. For example: $ git bisect skip v2.5..v2.6 ------------ -The effect of this would be that no commit between `v2.5` excluded and -`v2.6` included could be tested. +This tells the bisect process that no commit between `v2.5` excluded and +`v2.6` included should be tested. Note that if you also want to skip the first commit of the range you would issue the command: @@ -185,8 +185,8 @@ would issue the command: $ git bisect skip v2.5 v2.5..v2.6 ------------ -This would cause the commits between `v2.5` included and `v2.6` included -to be skipped. +This tells the bisect process that the commits between `v2.5` included +and `v2.6` included should be skipped. Cutting down bisection by giving more parameters to bisect start From 1d52b02696d01f7222419f3379565ba05faf1143 Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Sun, 22 Mar 2009 18:00:14 -0700 Subject: [PATCH 29/95] Documentation: minor grammatical fixes and rewording in git-bundle.txt This commit also converts all reference specifications to a monospaced font, as the embedded ~ character used in some of the references sometimes causes the text up to the next ~ to be displayed incorrectly as a subscript when the HTML pages are generated. This was tested with asciidoc 8.2.5. Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-bundle.txt | 86 ++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt index 57590b1480..aee7e4a8c9 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.txt @@ -19,13 +19,13 @@ DESCRIPTION Some workflows require that one or more branches of development on one machine be replicated on another machine, but the two machines cannot -be directly connected so the interactive git protocols (git, ssh, -rsync, http) cannot be used. This command provides support for +be directly connected, and therefore the interactive git protocols (git, +ssh, rsync, http) cannot be used. This command provides support for 'git-fetch' and 'git-pull' to operate by packaging objects and references in an archive at the originating machine, then importing those into another repository using 'git-fetch' and 'git-pull' after moving the archive by some means (i.e., by sneakernet). As no -direct connection between repositories exists, the user must specify a +direct connection between the repositories exists, the user must specify a basis for the bundle that is held by the destination repository: the bundle assumes that all objects in the basis are already in the destination repository. @@ -43,7 +43,7 @@ verify :: bundle format itself as well as checking that the prerequisite commits exist and are fully linked in the current repository. 'git-bundle' prints a list of missing commits, if any, and exits - with non-zero status. + with a non-zero status. list-heads :: Lists the references defined in the bundle. If followed by a @@ -53,14 +53,14 @@ list-heads :: unbundle :: Passes the objects in the bundle to 'git-index-pack' for storage in the repository, then prints the names of all - defined references. If a reflist is given, only references - matching those in the given list are printed. This command is + defined references. If a list of references is given, only + references matching those in the list are printed. This command is really plumbing, intended to be called only by 'git-fetch'. [git-rev-list-args...]:: A list of arguments, acceptable to 'git-rev-parse' and - 'git-rev-list', that specify the specific objects and references - to transport. For example, "master~10..master" causes the + 'git-rev-list', that specifies the specific objects and references + to transport. For example, `master\~10..master` causes the current master reference to be packaged along with all objects added since its 10th ancestor commit. There is no explicit limit to the number of references and objects that may be @@ -71,24 +71,24 @@ unbundle :: A list of references used to limit the references reported as available. This is principally of use to 'git-fetch', which expects to receive only those references asked for and not - necessarily everything in the pack (in this case, 'git-bundle' is - acting like 'git-fetch-pack'). + necessarily everything in the pack (in this case, 'git-bundle' acts + like 'git-fetch-pack'). SPECIFYING REFERENCES --------------------- 'git-bundle' will only package references that are shown by 'git-show-ref': this includes heads, tags, and remote heads. References -such as master~1 cannot be packaged, but are perfectly suitable for +such as `master\~1` cannot be packaged, but are perfectly suitable for defining the basis. More than one reference may be packaged, and more than one basis can be specified. The objects packaged are those not contained in the union of the given bases. Each basis can be -specified explicitly (e.g., ^master~10), or implicitly (e.g., -master~10..master, --since=10.days.ago master). +specified explicitly (e.g. `^master\~10`), or implicitly (e.g. +`master\~10..master`, `--since=10.days.ago master`). It is very important that the basis used be held by the destination. -It is okay to err on the side of conservatism, causing the bundle file -to contain objects already in the destination as these are ignored +It is okay to err on the side of caution, causing the bundle file +to contain objects already in the destination, as these are ignored when unpacking at the destination. EXAMPLE @@ -97,13 +97,13 @@ EXAMPLE Assume you want to transfer the history from a repository R1 on machine A to another repository R2 on machine B. For whatever reason, direct connection between A and B is not allowed, -but we can move data from A to B via some mechanism (CD, email, etc). -We want to update R2 with developments made on branch master in R1. +but we can move data from A to B via some mechanism (CD, email, etc.). +We want to update R2 with development made on the branch master in R1. -To bootstrap the process, you can first create a bundle that doesn't have -any basis. You can use a tag to remember up to what commit you sent out -in order to make it easy to later update the other repository with -incremental bundle, +To bootstrap the process, you can first create a bundle that does not have +any basis. You can use a tag to remember up to what commit you last +processed, in order to make it easy to later update the other repository +with an incremental bundle: ---------------- machineA$ cd R1 @@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master machineA$ git tag -f lastR2bundle master ---------------- -Then you sneakernet file.bundle to the target machine B. Because you don't -have to have any object to extract objects from such a bundle, not only -you can fetch/pull from a bundle, you can clone from it as if it was a -remote repository. +Then you transfer file.bundle to the target machine B. If you are creating +the repository on machine B, then you can clone from the bundle as if it +were a remote repository instead of creating an empty repository and then +pulling or fetching objects from the bundle: ---------------- machineB$ git clone /home/me/tmp/file.bundle R2 ---------------- This will define a remote called "origin" in the resulting repository that -lets you fetch and pull from the bundle. $GIT_DIR/config file in R2 may +lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will have an entry like this: ------------------------ @@ -130,12 +130,12 @@ have an entry like this: fetch = refs/heads/*:refs/remotes/origin/* ------------------------ -You can fetch/pull to update the resulting mine.git repository after -replacing the bundle you store at /home/me/tmp/file.bundle with incremental -updates from here on. +To update the resulting mine.git repository, you can fetch or pull after +replacing the bundle stored at /home/me/tmp/file.bundle with incremental +updates. -After working more in the original repository, you can create an -incremental bundle to update the other: +After working some more in the original repository, you can create an +incremental bundle to update the other repository: ---------------- machineA$ cd R1 @@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master machineA$ git tag -f lastR2bundle master ---------------- -and sneakernet it to the other machine to replace /home/me/tmp/file.bundle, -and pull from it. +You then transfer the bundle to the other machine to replace +/home/me/tmp/file.bundle, and pull from it. ---------------- machineB$ cd R2 @@ -152,49 +152,49 @@ machineB$ git pull ---------------- If you know up to what commit the intended recipient repository should -have the necessary objects for, you can use that knowledge to specify the +have the necessary objects, you can use that knowledge to specify the basis, giving a cut-off point to limit the revisions and objects that go in the resulting bundle. The previous example used lastR2bundle tag -for this purpose, but you can use other options you would give to +for this purpose, but you can use any other options that you would give to the linkgit:git-log[1] command. Here are more examples: -You can use a tag that is present in both. +You can use a tag that is present in both: ---------------- $ git bundle create mybundle v1.0.0..master ---------------- -You can use a basis based on time. +You can use a basis based on time: ---------------- $ git bundle create mybundle --since=10.days master ---------------- -Or you can use the number of commits. +You can use the number of commits: ---------------- $ git bundle create mybundle -10 master ---------------- You can run `git-bundle verify` to see if you can extract from a bundle -that was created with a basis. +that was created with a basis: ---------------- $ git bundle verify mybundle ---------------- This will list what commits you must have in order to extract from the -bundle and will error out if you don't have them. +bundle and will error out if you do not have them. A bundle from a recipient repository's point of view is just like a -regular repository it fetches/pulls from. You can for example map -refs, like this example, when fetching: +regular repository which it fetches or pulls from. You can, for example, map +references when fetching: ---------------- $ git fetch mybundle master:localRef ---------------- -Or see what refs it offers. +You can also see what references it offers. ---------------- $ git ls-remote mybundle From d83a42f34a6c12e4c1a3a18bf6f9036cc4933691 Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Sun, 22 Mar 2009 18:00:15 -0700 Subject: [PATCH 30/95] Documentation: minor grammatical fixes in git-cat-file.txt Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-cat-file.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 668f697c2a..b191276d7a 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -3,7 +3,7 @@ git-cat-file(1) NAME ---- -git-cat-file - Provide content or type/size information for repository objects +git-cat-file - Provide content or type and size information for repository objects SYNOPSIS @@ -14,19 +14,19 @@ SYNOPSIS DESCRIPTION ----------- -In the first form, provides content or type of objects in the repository. The -type is required unless '-t' or '-p' is used to find the object type, or '-s' -is used to find the object size. +In its first form, the command provides the content or the type of an object in +the repository. The type is required unless '-t' or '-p' is used to find the +object type, or '-s' is used to find the object size. -In the second form, a list of object (separated by LFs) is provided on stdin, -and the SHA1, type, and size of each object is printed on stdout. +In the second form, a list of objects (separated by linefeeds) is provided on +stdin, and the SHA1, type, and size of each object is printed on stdout. OPTIONS ------- :: The name of the object to show. For a more complete list of ways to spell object names, see - "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1]. + the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1]. -t:: Instead of the content, show the object type identified by @@ -56,8 +56,8 @@ OPTIONS stdin. May not be combined with any other options or arguments. --batch-check:: - Print the SHA1, type, and size of each object provided on stdin. May not be - combined with any other options or arguments. + Print the SHA1, type, and size of each object provided on stdin. May not + be combined with any other options or arguments. OUTPUT ------ From 3460a60064652dd79c1017c6701228d3c53ab3a4 Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Sun, 22 Mar 2009 18:00:16 -0700 Subject: [PATCH 31/95] Documentation: minor grammatical fixes in git-check-attr.txt Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-check-attr.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt index 8c2ac12f5d..50824e3a2d 100644 --- a/Documentation/git-check-attr.txt +++ b/Documentation/git-check-attr.txt @@ -14,7 +14,7 @@ SYNOPSIS DESCRIPTION ----------- -For every pathname, this command will list if each attr is 'unspecified', +For every pathname, this command will list if each attribute is 'unspecified', 'set', or 'unset' as a gitattribute on that pathname. OPTIONS @@ -23,11 +23,11 @@ OPTIONS Read file names from stdin instead of from the command-line. -z:: - Only meaningful with `--stdin`; paths are separated with - NUL character instead of LF. + Only meaningful with `--stdin`; paths are separated with a + NUL character instead of a linefeed character. \--:: - Interpret all preceding arguments as attributes, and all following + Interpret all preceding arguments as attributes and all following arguments as path names. If not supplied, only the first argument will be treated as an attribute. @@ -37,12 +37,12 @@ OUTPUT The output is of the form: COLON SP COLON SP LF -Where is the path of a file being queried, is an attribute + is the path of a file being queried, is an attribute being queried and can be either: 'unspecified';; when the attribute is not defined for the path. -'unset';; when the attribute is defined to false. -'set';; when the attribute is defined to true. +'unset';; when the attribute is defined as false. +'set';; when the attribute is defined as true. ;; when a value has been assigned to the attribute. EXAMPLES @@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java org/example/MyClass.java: myAttr: set --------------- -* Listing attribute for multiple files: +* Listing an attribute for multiple files: --------------- $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java org/example/MyClass.java: myAttr: set From cd747dc6dcb18f10b90fd8a1f8831b1da3551354 Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Sun, 22 Mar 2009 18:00:17 -0700 Subject: [PATCH 32/95] Documentation: minor grammatical fix in git-check-ref-format.txt Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-check-ref-format.txt | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index 034223cc5a..171b68377d 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -3,7 +3,7 @@ git-check-ref-format(1) NAME ---- -git-check-ref-format - Make sure ref name is well formed +git-check-ref-format - Ensures that a reference name is well formed SYNOPSIS -------- @@ -11,40 +11,40 @@ SYNOPSIS DESCRIPTION ----------- -Checks if a given 'refname' is acceptable, and exits non-zero if -it is not. +Checks if a given 'refname' is acceptable, and exits with a non-zero +status if it is not. A reference is used in git to specify branches and tags. A -branch head is stored under `$GIT_DIR/refs/heads` directory, and -a tag is stored under `$GIT_DIR/refs/tags` directory. git -imposes the following rules on how refs are named: +branch head is stored under the `$GIT_DIR/refs/heads` directory, and +a tag is stored under the `$GIT_DIR/refs/tags` directory. git +imposes the following rules on how references are named: -. It can include slash `/` for hierarchical (directory) +. They can include slash `/` for hierarchical (directory) grouping, but no slash-separated component can begin with a - dot `.`; + dot `.`. -. It cannot have two consecutive dots `..` anywhere; +. They cannot have two consecutive dots `..` anywhere. -. It cannot have ASCII control character (i.e. bytes whose +. They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 `DEL`), space, tilde `~`, caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`, - or open bracket `[` anywhere; + or open bracket `[` anywhere. -. It cannot end with a slash `/`. +. They cannot end with a slash `/`. -These rules makes it easy for shell script based tools to parse -refnames, pathname expansion by the shell when a refname is used +These rules make it easy for shell script based tools to parse +reference names, pathname expansion by the shell when a reference name is used unquoted (by mistake), and also avoids ambiguities in certain -refname expressions (see linkgit:git-rev-parse[1]). Namely: +reference name expressions (see linkgit:git-rev-parse[1]): -. double-dot `..` are often used as in `ref1..ref2`, and in some - context this notation means `{caret}ref1 ref2` (i.e. not in - ref1 and in ref2). +. A double-dot `..` is often used as in `ref1..ref2`, and in some + contexts this notation means `{caret}ref1 ref2` (i.e. not in + `ref1` and in `ref2`). -. tilde `~` and caret `{caret}` are used to introduce postfix +. A tilde `~` and caret `{caret}` are used to introduce the postfix 'nth parent' and 'peel onion' operation. -. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s +. A colon `:` is used as in `srcref:dstref` to mean "use srcref\'s value and store it in dstref" in fetch and push operations. It may also be used to select a specific object such as with 'git-cat-file': "git cat-file blob v1.3.3:refs.c". From 5c928c06e251b651202f94aaac56cacd3f57c484 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 25 Mar 2009 17:27:28 +0100 Subject: [PATCH 33/95] Guard a few Makefile variables against user environments Some variables are not initialized in the Makefile, but appended to. If the user has those variables in her environment, it will break the build. The variable names were found using these commands: $ s='[ \t]'; $ S='[^ \t]'; $ comm -23 \ <(sed -n "s/^$s*\($S*\)$s$s*+=.*/\1/p" < Makefile | sort | uniq) \ <(sed -n "s/^$s*\($S*\)$s$s*=.*/\1/p" < Makefile | sort | uniq) This fixes msysGit issue 216. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Makefile b/Makefile index 320c89786c..7867eaccdb 100644 --- a/Makefile +++ b/Makefile @@ -263,6 +263,18 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ BASIC_CFLAGS = BASIC_LDFLAGS = +# Guard against environment variables +BUILTIN_OBJS = +BUILT_INS = +COMPAT_CFLAGS = +COMPAT_OBJS = +LIB_H = +LIB_OBJS = +PROGRAMS = +SCRIPT_PERL = +SCRIPT_SH = +TEST_PROGRAMS = + SCRIPT_SH += git-am.sh SCRIPT_SH += git-bisect.sh SCRIPT_SH += git-filter-branch.sh From 5d83f9c19810229bb765ef63864e4f252e83ad61 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Wed, 25 Mar 2009 18:19:46 +0100 Subject: [PATCH 34/95] diff --no-index: Do not generate patch output if other output is requested Previously, 'git diff --no-index --stat a b' generated patch output in addition to the --stat output (or whatever other output format was requested). Now only the requested output is generated, and patch output remains the default. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- diff-no-index.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diff-no-index.c b/diff-no-index.c index 2d541d9aba..a3e47a76e4 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -201,8 +201,6 @@ void diff_no_index(struct rev_info *revs, no_index ? "--no-index" : "[--no-index]"); diff_setup(&revs->diffopt); - if (!revs->diffopt.output_format) - revs->diffopt.output_format = DIFF_FORMAT_PATCH; for (i = 1; i < argc - 2; ) { int j; if (!strcmp(argv[i], "--no-index")) @@ -248,6 +246,8 @@ void diff_no_index(struct rev_info *revs, revs->diffopt.paths = argv + argc - 2; revs->diffopt.nr_paths = 2; revs->diffopt.skip_stat_unmatch = 1; + if (!revs->diffopt.output_format) + revs->diffopt.output_format = DIFF_FORMAT_PATCH; DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS); DIFF_OPT_SET(&revs->diffopt, NO_INDEX); From 80f0e53d6bdde5d9be016e5cfbb5ff7c0257a00e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Wed, 25 Mar 2009 12:48:30 +0100 Subject: [PATCH 35/95] t7005-editor: Use $SHELL_PATH in the editor scripts The test sets up various shell scripts and uses them as commit message editors. On Windows, we need a shebang line in order to recognize the files as executable shell scripts. This adds it. Signed-off-by: Johannes Sixt --- t/t7005-editor.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 2f8404afbb..e83bc8fd89 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -7,6 +7,7 @@ test_description='GIT_EDITOR, core.editor, and stuff' for i in GIT_EDITOR core_editor EDITOR VISUAL vi do cat >e-$i.sh <<-EOF + #!$SHELL_PATH echo "Edited by $i" >"\$1" EOF chmod +x e-$i.sh From fb9a2beab2002894fb970cba4e32ebb1c41176b2 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Wed, 25 Mar 2009 13:21:15 +0100 Subject: [PATCH 36/95] t7502-commit: Skip SIGTERM test on Windows The implementation of exec on Windows is just a rough approximation of the POSIX behavior. In particular, no real process "overlay" happens (a new process is spawned instead and the parent process waits until the child terminates). In particular, the process ID cannot be taken by the exec'd process. But there is one test in t7502-commit.sh that depends on this. We have to skip it on Windows. Signed-off-by: Johannes Sixt --- t/t7502-commit.sh | 2 +- t/test-lib.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index ad42c78d7c..56cd866019 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <>negative && ! "$SHELL_PATH" -c '\'' echo kill -TERM $$ >> .git/FAKE_EDITOR diff --git a/t/test-lib.sh b/t/test-lib.sh index b4b626e837..572301df1b 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -689,10 +689,12 @@ case $(uname -s) in } # no POSIX permissions # backslashes in pathspec are converted to '/' + # exec does not inherit the PID ;; *) test_set_prereq POSIXPERM test_set_prereq BSLASHPSPEC + test_set_prereq EXECKEEPSPID ;; esac From b2655cdae953d619d488b69b7d49e4204e5682dc Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 25 Mar 2009 13:14:03 -0700 Subject: [PATCH 37/95] builtin-push.c: Fix typo: "anythig" -> "anything" Signed-off-by: Kevin Ballard Signed-off-by: Junio C Hamano --- builtin-push.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-push.c b/builtin-push.c index 8f4fa5b09e..bbf019850e 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -73,7 +73,7 @@ static const char *warn_unconfigured_push_msg[] = { "", "You can specify what action you want to take in this case, and", "avoid seeing this message again, by configuring 'push.default' to:", - " 'nothing' : Do not push anythig", + " 'nothing' : Do not push anything", " 'matching' : Push all matching branches (default)", " 'tracking' : Push the current branch to whatever it is tracking", " 'current' : Push the current branch" From d5b0c97d138201c59b30cb759cedabb70b7bae81 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 25 Mar 2009 15:51:01 -0600 Subject: [PATCH 38/95] git-filter-branch: avoid collisions with variables in eval'ed commands Avoid using simple variable names like 'i', since user commands are eval'ed and may clash with and overwrite our values. Signed-off-by: Elijah Newren Acked-by: Petr Baudis Signed-off-by: Junio C Hamano --- git-filter-branch.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 20f6f51750..b90d3df3a7 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -272,10 +272,10 @@ test $commits -eq 0 && die "Found nothing to rewrite" # Rewrite the commits -i=0 +git_filter_branch__commit_count=0 while read commit parents; do - i=$(($i+1)) - printf "\rRewrite $commit ($i/$commits)" + git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1)) + printf "\rRewrite $commit ($git_filter_branch__commit_count/$commits)" case "$filter_subdir" in "") From 98e1a4186acd4b71da1daae5c522cb6ac6d1d904 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 25 Mar 2009 15:22:13 -0600 Subject: [PATCH 39/95] Correct missing SP characters in grammar comment at top of fast-import.c Signed-off-by: Elijah Newren Acked-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- fast-import.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fast-import.c b/fast-import.c index beeac0d004..db44da3e09 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1,4 +1,5 @@ /* +(See Documentation/git-fast-import.txt for maintained documentation.) Format of STDIN stream: stream ::= cmd*; @@ -18,8 +19,8 @@ Format of STDIN stream: new_commit ::= 'commit' sp ref_str lf mark? - ('author' sp name '<' email '>' when lf)? - 'committer' sp name '<' email '>' when lf + ('author' sp name sp '<' email '>' sp when lf)? + 'committer' sp name sp '<' email '>' sp when lf commit_msg ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)? ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)* @@ -43,7 +44,7 @@ Format of STDIN stream: new_tag ::= 'tag' sp tag_str lf 'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf - ('tagger' sp name '<' email '>' when lf)? + ('tagger' sp name sp '<' email '>' sp when lf)? tag_msg; tag_msg ::= data; From 4fa535a179e771cd5a16d5ab05e97e7bb52739ef Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Wed, 25 Mar 2009 19:23:42 +0100 Subject: [PATCH 40/95] Grammar fixes to "merge" and "patch-id" docs Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- Documentation/git-merge.txt | 2 +- Documentation/git-patch-id.txt | 2 +- Documentation/merge-strategies.txt | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index cc0d30fe7e..427ad9083e 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -41,7 +41,7 @@ include::merge-strategies.txt[] If you tried a merge which resulted in a complex conflicts and -would want to start over, you can recover with 'git-reset'. +want to start over, you can recover with 'git-reset'. CONFIGURATION ------------- diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt index 477785e134..253fc0fc25 100644 --- a/Documentation/git-patch-id.txt +++ b/Documentation/git-patch-id.txt @@ -20,7 +20,7 @@ IOW, you can use this thing to look for likely duplicate commits. When dealing with 'git-diff-tree' output, it takes advantage of the fact that the patch is prefixed with the object name of the -commit, and outputs two 40-byte hexadecimal string. The first +commit, and outputs two 40-byte hexadecimal strings. The first string is the patch ID, and the second string is the commit ID. This can be used to make a mapping from patch ID to commit ID. diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 1276f858ad..4365b7e842 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -3,15 +3,15 @@ MERGE STRATEGIES resolve:: This can only resolve two heads (i.e. the current branch - and another branch you pulled from) using 3-way merge + and another branch you pulled from) using a 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast. recursive:: - This can only resolve two heads using 3-way merge - algorithm. When there are more than one common - ancestors that can be used for 3-way merge, it creates a + This can only resolve two heads using a 3-way merge + algorithm. When there is more than one common + ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without @@ -22,11 +22,11 @@ recursive:: pulling or merging one branch. octopus:: - This resolves more than two-head case, but refuses to do - complex merge that needs manual resolution. It is + This resolves cases with more than two heads, but refuses to do + a complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when - pulling or merging more than one branches. + pulling or merging more than one branch. ours:: This resolves any number of heads, but the result of the From 19fa5e8c4d62d445b822e0d0d87a4f995e6c863f Mon Sep 17 00:00:00 2001 From: "David J. Mellor" Date: Wed, 25 Mar 2009 20:44:44 -0700 Subject: [PATCH 41/95] Documentation: Remove spurious uses of "you" in git-bisect.txt. These were added by accident in a42dea3. This patch also rewords the description of how ranges of commits can be skipped. Signed-off-by: David J. Mellor Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index f74354f0fe..e5862b9dbb 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -151,7 +151,7 @@ $ git reset --hard HEAD~3 # try 3 revisions before what # was suggested ------------ -Then you compile and test the chosen revision. Afterwards you mark +Then compile and test the chosen revision, and afterwards mark the revision as good or bad in the usual manner. Bisect skip @@ -175,8 +175,8 @@ using the "''..''" notation. For example: $ git bisect skip v2.5..v2.6 ------------ -This tells the bisect process that no commit between `v2.5` excluded and -`v2.6` included should be tested. +This tells the bisect process that no commit after `v2.5`, up to and +including `v2.6`, should be tested. Note that if you also want to skip the first commit of the range you would issue the command: From ebeec7dbc564cb83edd8faee87890c47b6f0da43 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 25 Mar 2009 17:53:23 -0600 Subject: [PATCH 42/95] fast-export: Avoid dropping files from commits When exporting a subset of commits on a branch that do not go back to a root commit (e.g. master~2..master), we still want each exported commit to have the same files in the exported tree as in the original tree. Previously, when given such a range, we would omit master~2 as a parent of master~1, but we would still diff against master~2 when selecting the list of files to include in master~1. This would result in only files that had changed in the given range showing up in the resulting export. In such cases, we should diff master~1 against the root instead (i.e. use diff_root_tree_sha1 instead of diff_tree_sha1). There's a special case to consider here: incremental exports (i.e. exports where the --import-marks flag is specified). If master~2 is an imported mark, then we still want to diff master~1 against master~2 when selecting the list of files to include. We can handle all cases, including the special case, by just checking whether master~2 corresponds to a known object mark when deciding what to diff against. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- builtin-fast-export.c | 3 ++- t/t9301-fast-export.sh | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/builtin-fast-export.c b/builtin-fast-export.c index fdf4ae9ebd..34a419c38e 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -221,7 +221,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) if (message) message += 2; - if (commit->parents) { + if (commit->parents && + get_object_mark(&commit->parents->item->object) != 0) { parse_commit(commit->parents->item); diff_tree_sha1(commit->parents->item->tree->object.sha1, commit->tree->object.sha1, "", &rev->diffopt); diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index 86c376088c..b860626bee 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -8,6 +8,9 @@ test_description='git fast-export' test_expect_success 'setup' ' + echo break it > file0 && + git add file0 && + test_tick && echo Wohlauf > file && git add file && test_tick && @@ -57,8 +60,8 @@ test_expect_success 'fast-export master~2..master' ' (cd new && git fast-import && test $MASTER != $(git rev-parse --verify refs/heads/partial) && - git diff master..partial && - git diff master^..partial^ && + git diff --exit-code master partial && + git diff --exit-code master^ partial^ && test_must_fail git rev-parse partial~2) ' From a8fac795ddaa004835fc688560cf19ca5500ce8d Mon Sep 17 00:00:00 2001 From: Carlo Marcelo Arenas Belon Date: Thu, 26 Mar 2009 00:08:09 -0700 Subject: [PATCH 43/95] documentation: update cvsimport description of "-r" for recent clone the "--use-separate-remote" option no longer exists, having since become the default for a clone. Signed-off-by: Carlo Marcelo Arenas Belon Signed-off-by: Junio C Hamano --- Documentation/git-cvsimport.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index b7a8c10b87..8f9ba74c8b 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -62,7 +62,7 @@ OPTIONS -r :: The git remote to import this CVS repository into. Moves all CVS branches into remotes// - akin to the 'git-clone' "--use-separate-remote" option. + akin to the way 'git-clone' uses 'origin' by default. -o :: When no remote is specified (via -r) the 'HEAD' branch From 9fe00538c693929d4dec29690fe7660106fe056a Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Thu, 26 Mar 2009 10:39:04 +0100 Subject: [PATCH 44/95] Grammar fix for "git merge" man page As spotted by the eagle eyes of Jeff King. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- Documentation/git-merge.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 427ad9083e..c04ae739ed 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -40,7 +40,7 @@ include::merge-options.txt[] include::merge-strategies.txt[] -If you tried a merge which resulted in a complex conflicts and +If you tried a merge which resulted in complex conflicts and want to start over, you can recover with 'git-reset'. CONFIGURATION From 6828f72ffee0d603b96bcde080ec13504f617669 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 26 Mar 2009 21:37:53 -0500 Subject: [PATCH 45/95] builtin-send-pack.c: avoid empty structure initialization The IRIX6.5 MIPSpro Compiler doesn't like it. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 91c36512a8..d5a1c48d0e 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -10,8 +10,7 @@ static const char send_pack_usage[] = "git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=] [--verbose] [--thin] [:] [...]\n" " --all and explicit specification are mutually exclusive."; -static struct send_pack_args args = { -}; +static struct send_pack_args args; static int feed_object(const unsigned char *sha1, int fd, int negative) { From bb2300976ba1491a54dc2b82819fae68d59d6e53 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:49:38 -0500 Subject: [PATCH 46/95] Documentation/Makefile: make most operations "quiet" This adapts the "quiet make" implementation from the main Makefile. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 84 +++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index 144ec32f12..3e1d175ee6 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -76,6 +76,32 @@ endif # yourself - yes, all 6 characters of it! # +QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir +QUIET_SUBDIR1 = + +ifneq ($(findstring $(MAKEFLAGS),w),w) +PRINT_DIR = --no-print-directory +else # "make -w" +NO_SUBDIR = : +endif + +ifneq ($(findstring $(MAKEFLAGS),s),s) +ifndef V + QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; + QUIET_XMLTO = @echo ' ' XMLTO $@; + QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; + QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; + QUIET_DBLATEX = @echo ' ' DBLATEX $@; + QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; + QUIET_GEN = @echo ' ' GEN $@; + QUIET_STDERR = 2> /dev/null + QUIET_SUBDIR0 = +@subdir= + QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ + $(MAKE) $(PRINT_DIR) -C $$subdir + export V +endif +endif + all: html man html: $(DOC_HTML) @@ -119,7 +145,7 @@ install-html: html sh ./install-webdoc.sh $(DESTDIR)$(htmldir) ../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE - $(MAKE) -C ../ GIT-VERSION-FILE + $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE -include ../GIT-VERSION-FILE @@ -127,8 +153,8 @@ install-html: html # Determine "include::" file references in asciidoc files. # doc.dep : $(wildcard *.txt) build-docdep.perl - $(RM) $@+ $@ - $(PERL_PATH) ./build-docdep.perl >$@+ + $(QUIET_GEN)$(RM) $@+ $@ && \ + $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \ mv $@+ $@ -include doc.dep @@ -146,8 +172,8 @@ cmds_txt = cmds-ancillaryinterrogators.txt \ $(cmds_txt): cmd-list.made cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) - $(RM) $@ - $(PERL_PATH) ./cmd-list.perl ../command-list.txt + $(QUIET_GEN)$(RM) $@ && \ + $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ date >$@ clean: @@ -158,79 +184,79 @@ clean: $(RM) $(cmds_txt) *.made $(MAN_HTML): %.html : %.txt - $(RM) $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \ - $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< + $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \ mv $@+ $@ %.1 %.5 %.7 : %.xml - $(RM) $@ + $(QUIET_XMLTO)$(RM) $@ && \ xmlto -m $(MANPAGE_XSL) man $< %.xml : %.txt - $(RM) $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ - $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< + $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \ mv $@+ $@ user-manual.xml: user-manual.txt user-manual.conf - $(ASCIIDOC) -b docbook -d book $< + $(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d book $< technical/api-index.txt: technical/api-index-skel.txt \ technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS)) - cd technical && sh ./api-index.sh + $(QUIET_GEN)cd technical && sh ./api-index.sh $(patsubst %,%.html,$(API_DOCS) technical/api-index): %.html : %.txt - $(ASCIIDOC) -b xhtml11 -f asciidoc.conf \ + $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \ $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt XSLT = docbook.xsl XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css user-manual.html: user-manual.xml - xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< + $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< git.info: user-manual.texi - $(MAKEINFO) --no-split -o $@ user-manual.texi + $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi user-manual.texi: user-manual.xml - $(RM) $@+ $@ + $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \ - $(PERL_PATH) fix-texi.perl >$@+ + $(PERL_PATH) fix-texi.perl >$@+ && \ mv $@+ $@ user-manual.pdf: user-manual.xml - $(RM) $@+ $@ - $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< + $(QUIET_DBLATEX)$(RM) $@+ $@ && \ + $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \ mv $@+ $@ gitman.texi: $(MAN_XML) cat-texi.perl - $(RM) $@+ $@ + $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \ - --to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+ + --to-stdout $(xml) &&) true) | $(PERL_PATH) cat-texi.perl $@ >$@+ && \ mv $@+ $@ gitman.info: gitman.texi - $(MAKEINFO) --no-split --no-validate $*.texi + $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml - $(RM) $@+ $@ - $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ + $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ + $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \ mv $@+ $@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt) - $(RM) $@+ $@ - sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ + $(QUIET_GEN)$(RM) $@+ $@ && \ + sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \ mv $@+ $@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt - $(ASCIIDOC) -b xhtml11 $*.txt + $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt WEBDOC_DEST = /pub/software/scm/git/docs $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt - $(RM) $@+ $@ - sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \ mv $@+ $@ install-webdoc : html From c6a5ad21e57ce38a0add04a2708ccf02ed17af39 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:49:39 -0500 Subject: [PATCH 47/95] Documentation/Makefile: break up texi pipeline Most shells define the exit value of a pipeline as the exit value of the last process. For each texi rule, run the DOCBOOK2X_TEXI tool and the "fixup" script in their own non-pipeline commands so that make will notice an error exit code. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index 3e1d175ee6..d145372393 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -178,7 +178,7 @@ cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) clean: $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 - $(RM) *.texi *.texi+ git.info gitman.info + $(RM) *.texi *.texi+ *.texi++ git.info gitman.info $(RM) howto-index.txt howto/*.html doc.dep $(RM) technical/api-*.html technical/api-index.txt $(RM) $(cmds_txt) *.made @@ -221,8 +221,9 @@ git.info: user-manual.texi user-manual.texi: user-manual.xml $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ - $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \ - $(PERL_PATH) fix-texi.perl >$@+ && \ + $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \ + $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \ + rm $@++ && \ mv $@+ $@ user-manual.pdf: user-manual.xml @@ -233,7 +234,9 @@ user-manual.pdf: user-manual.xml gitman.texi: $(MAN_XML) cat-texi.perl $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \ - --to-stdout $(xml) &&) true) | $(PERL_PATH) cat-texi.perl $@ >$@+ && \ + --to-stdout $(xml) &&) true) > $@++ && \ + $(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \ + rm $@++ && \ mv $@+ $@ gitman.info: gitman.texi From c30e9485238bb8e9daa4cbba5deb1f79c8da7dde Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:43:58 -0500 Subject: [PATCH 48/95] Documentation: move callouts.xsl to manpage-{base,normal}.xsl Each of manpage-base.xsl and manpage-normal.xsl gets a copy of the contents of callouts.xsl and the original is removed. The Makefile is adjusted to refer to manpage-normal.xsl instead of callouts.xsl. manpage-base.xsl will be later made into a common base for -normal and -1.72. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 2 +- .../{callouts.xsl => manpage-base.xsl} | 0 Documentation/manpage-normal.xsl | 30 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) rename Documentation/{callouts.xsl => manpage-base.xsl} (100%) create mode 100644 Documentation/manpage-normal.xsl diff --git a/Documentation/Makefile b/Documentation/Makefile index 144ec32f12..e1562e351c 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -41,7 +41,7 @@ man7dir=$(mandir)/man7 ASCIIDOC=asciidoc ASCIIDOC_EXTRA = -MANPAGE_XSL = callouts.xsl +MANPAGE_XSL = manpage-normal.xsl INSTALL?=install RM ?= rm -f DOC_REF = origin/man diff --git a/Documentation/callouts.xsl b/Documentation/manpage-base.xsl similarity index 100% rename from Documentation/callouts.xsl rename to Documentation/manpage-base.xsl diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl new file mode 100644 index 0000000000..6a361a2136 --- /dev/null +++ b/Documentation/manpage-normal.xsl @@ -0,0 +1,30 @@ + + + + + + + .sp + + + + + + + .br + + + + + + + + + + + + + + From ae8d09b8fa138aeb8ec3e20819360241dfb9f0b8 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:43:59 -0500 Subject: [PATCH 49/95] Documentation: use parametrized manpage-base.xsl with manpage-{1.72,normal}.xsl Parametrize the backslash and dot characters that are used to generate roff control sequences in manpage-base.xsl. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/manpage-1.72.xsl | 29 +++++++++++------------- Documentation/manpage-base.xsl | 39 ++++++++++++++++---------------- Documentation/manpage-normal.xsl | 30 +++++++++++------------- 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/Documentation/manpage-1.72.xsl b/Documentation/manpage-1.72.xsl index 4065a3a27a..e24d26cd00 100644 --- a/Documentation/manpage-1.72.xsl +++ b/Documentation/manpage-1.72.xsl @@ -1,21 +1,18 @@ - - + + + + + + + + + - - - - - ⌂sp - - - - - - - ⌂br - - diff --git a/Documentation/manpage-base.xsl b/Documentation/manpage-base.xsl index 6a361a2136..6d3eb1912a 100644 --- a/Documentation/manpage-base.xsl +++ b/Documentation/manpage-base.xsl @@ -1,30 +1,31 @@ - - + + + + - + - .sp + + sp - + - .br - - - - - - - - - - - + + br diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl index 6a361a2136..e36472f5ad 100644 --- a/Documentation/manpage-normal.xsl +++ b/Documentation/manpage-normal.xsl @@ -1,21 +1,17 @@ - - - - - - - .sp - - - - - - - .br - + + - + + + +\ +. + + From 8fa2b45f3a70a1622c8fc5d35af148da5cab80d1 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:00 -0500 Subject: [PATCH 50/95] Documentation: rename docbook-xsl-172 attribute to git-asciidoc-no-roff It seems that the ability to use raw roff codes in asciidoc.conf was eliminated by docbook-xsl 1.72.0 _and later_. Unlike the 1.72.0-specific XSLT problem, this behavior was not reverted in later releases. This patch aims to make it clear that the affected asciidoc attribute (flag) can be reasonably used with docbook-xsl versions other than 1.72.0. Also, document which make variables should be set for various versions of asciidoc and docbook-xsl. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 29 ++++++++++++++++++++++++++++- Documentation/asciidoc.conf | 8 ++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index e1562e351c..d71760b807 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -59,12 +59,39 @@ endif -include ../config.mak.autogen -include ../config.mak +# +# For asciidoc ... +# -7.1.2, no extra settings are needed. +# 8.0-, set ASCIIDOC8. +# + +# +# For docbook-xsl ... +# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) +# 1.69.0-1.71.1, no extra settings are needed? +# 1.72.0, set DOCBOOK_XSL_172. +# 1.73.0-, set ASCIIDOC_NO_ROFF +# + +# +# If you had been using DOCBOOK_XSL_172 in an attempt to get rid +# of 'the ".ft C" problem' in your generated manpages, and you +# instead ended up with weird characters around callouts, try +# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). +# + ifdef ASCIIDOC8 ASCIIDOC_EXTRA += -a asciidoc7compatible endif ifdef DOCBOOK_XSL_172 -ASCIIDOC_EXTRA += -a docbook-xsl-172 +ASCIIDOC_EXTRA += -a git-asciidoc-no-roff MANPAGE_XSL = manpage-1.72.xsl +else + ifdef ASCIIDOC_NO_ROFF + # docbook-xsl after 1.72 needs the regular XSL, but will not + # pass-thru raw roff codes from asciidoc.conf, so turn them off. + ASCIIDOC_EXTRA += -a git-asciidoc-no-roff + endif endif # diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 1e735df3bb..ce1b1755ae 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -27,7 +27,7 @@ ifdef::backend-docbook[] endif::backend-docbook[] ifdef::backend-docbook[] -ifndef::docbook-xsl-172[] +ifndef::git-asciidoc-no-roff[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] @@ -42,9 +42,9 @@ ifdef::doctype-manpage[] endif::doctype-manpage[] {title#} -endif::docbook-xsl-172[] +endif::git-asciidoc-no-roff[] -ifdef::docbook-xsl-172[] +ifdef::git-asciidoc-no-roff[] ifdef::doctype-manpage[] # The following two small workarounds insert a simple paragraph after screen [listingblock] @@ -62,7 +62,7 @@ ifdef::doctype-manpage[] {title#} endif::doctype-manpage[] -endif::docbook-xsl-172[] +endif::git-asciidoc-no-roff[] endif::backend-docbook[] ifdef::doctype-manpage[] From 9d8d13a8c52c55ad4695b659cbffa61e4c3a3774 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:01 -0500 Subject: [PATCH 51/95] Documentation: move quieting params into manpage-base.xsl Move a couple of XSL parameters that act to silence informational/warning messages generated when running xmlto from manpage-1.72.xsl to manpage-base.xsl. Since unused parameters are silently ignored, there is no problem if some version of docbook-xsl does not know about these parameters. The only problem might be if a version of docbook-xsl uses the parameters for alternate functionality. Since both parameters have fairly specific names such a situation is unlikely. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/manpage-1.72.xsl | 4 ---- Documentation/manpage-base.xsl | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/manpage-1.72.xsl b/Documentation/manpage-1.72.xsl index e24d26cd00..b4d315cb8c 100644 --- a/Documentation/manpage-1.72.xsl +++ b/Documentation/manpage-1.72.xsl @@ -11,8 +11,4 @@ - - - - diff --git a/Documentation/manpage-base.xsl b/Documentation/manpage-base.xsl index 6d3eb1912a..a264fa6160 100644 --- a/Documentation/manpage-base.xsl +++ b/Documentation/manpage-base.xsl @@ -3,6 +3,10 @@ + + + + From 34c800b8fcbd85c276cb102b3e60d170aa9e55e0 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:02 -0500 Subject: [PATCH 52/95] Documentation: move "spurious .sp" code into manpage-base.xsl The "spurious .sp" code should be independent of docbook-xsl versions. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/manpage-base.xsl | 13 +++++++++++++ Documentation/manpage-normal.xsl | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/manpage-base.xsl b/Documentation/manpage-base.xsl index a264fa6160..16e2e40976 100644 --- a/Documentation/manpage-base.xsl +++ b/Documentation/manpage-base.xsl @@ -32,4 +32,17 @@ br + + + + + + + + + + + diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl index e36472f5ad..a48f5b11f3 100644 --- a/Documentation/manpage-normal.xsl +++ b/Documentation/manpage-normal.xsl @@ -10,17 +10,4 @@ \ . - - - - - - - - - - - From dad3211503e2760a0e704b3c617849ba298a76e7 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:03 -0500 Subject: [PATCH 53/95] Documentation: asciidoc.conf: always use for [blocktext] Make the docbook-xsl-no-raw-roff variant match the no-docbook-xsl-no-raw-roff variant in terms of which XML tag is used to wrap listing block text (delimited with lines of dashes). e920b56 (Tweak asciidoc output to work with broken docbook-xsl, 2006-03-05) says docbook-xsl 1.68 needs . This usages was in the old, 1.72-only section. But since it is now the "roff-less" section, it probably makes sense to make it symmetric with the "roff-ful" section. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/asciidoc.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index ce1b1755ae..9963f2da81 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -49,9 +49,9 @@ ifdef::doctype-manpage[] # The following two small workarounds insert a simple paragraph after screen [listingblock] {title} - + | - + {title#} [verseblock] From 0c04f5273579da4b8308c125b1eb4b8f888bffab Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:04 -0500 Subject: [PATCH 54/95] Documentation: asciidoc.conf: fix verse block with block titles No files use the variant of block-title with verse-block, but such a case would have generated broken docbook XML ( is not allowed inside ). This fixes the potential deviation from valid docbook XML. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/asciidoc.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 9963f2da81..dc76e7f073 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -59,8 +59,9 @@ ifdef::doctype-manpage[] {title%} {title#} | - + {title#} +{title%} endif::doctype-manpage[] endif::git-asciidoc-no-roff[] endif::backend-docbook[] From 5121a6d99368906292dfdf7fe0047fb89c4c1969 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Fri, 27 Mar 2009 01:44:05 -0500 Subject: [PATCH 55/95] Documentation: option to render literal text as bold for manpages This allows manpages viewed on a tty to render inline literal text in a manner that is distinct from the surrounding text. The initial implementation (pre-mailing-list) of this patch included a conditional variant of the XSLT code in manpage-base.xsl and use xmlto's --stringparam option to optionally enable the functionality. It turns out that --stringparam is broken in all versions of xmlto except for the pre-release, SVN version. Since xmlto is a shell script the patch to fix it is simple enough, but I instead opted to use xmlto's "module" functionality. Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 6 +++++- Documentation/manpage-bold-literal.xsl | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Documentation/manpage-bold-literal.xsl diff --git a/Documentation/Makefile b/Documentation/Makefile index d71760b807..1c94531874 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -42,6 +42,7 @@ man7dir=$(mandir)/man7 ASCIIDOC=asciidoc ASCIIDOC_EXTRA = MANPAGE_XSL = manpage-normal.xsl +XMLTO_EXTRA = INSTALL?=install RM ?= rm -f DOC_REF = origin/man @@ -93,6 +94,9 @@ else ASCIIDOC_EXTRA += -a git-asciidoc-no-roff endif endif +ifdef MAN_BOLD_LITERAL +XMLTO_EXTRA += -m manpage-bold-literal.xsl +endif # # Please note that there is a minor bug in asciidoc. @@ -192,7 +196,7 @@ $(MAN_HTML): %.html : %.txt %.1 %.5 %.7 : %.xml $(RM) $@ - xmlto -m $(MANPAGE_XSL) man $< + xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt $(RM) $@+ $@ diff --git a/Documentation/manpage-bold-literal.xsl b/Documentation/manpage-bold-literal.xsl new file mode 100644 index 0000000000..608eb5df62 --- /dev/null +++ b/Documentation/manpage-bold-literal.xsl @@ -0,0 +1,17 @@ + + + + + + + fB + + + fR + + + From 2d266f9d623625e0a28fbe3c3615707500e9448f Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 26 Mar 2009 18:29:25 +0100 Subject: [PATCH 56/95] Documentation: format-patch --root clarifications Users were confused about the meaning and use of the --root option. Notably, since 68c2ec7 (format-patch: show patch text for the root commit, 2009-01-10), --root has nothing to do with showing the patch text for the root commit any more. Shorten and clarify the corresponding paragraph in the DESCRIPTION section, document --root under OPTIONS, and add an explicit note that root commits are formatted regardless. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 11a7d77261..1f577b8016 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -39,15 +39,11 @@ There are two ways to specify which commits to operate on. REVISIONS" section in linkgit:git-rev-parse[1]) means the commits in the specified range. -A single commit, when interpreted as a -expression, means "everything that leads to that commit", but -if you write 'git format-patch ', the previous rule -applies to that command line and you do not get "everything -since the beginning of the time". If you want to format -everything since project inception to one commit, say "git -format-patch \--root " to make it clear that it is the -latter case. If you want to format a single commit, you can do -this with "git format-patch -1 ". +The first rule takes precedence in the case of a single . To +apply the second rule, i.e., format everything since the beginning of +history up until , use the '\--root' option: "git format-patch +\--root ". If you want to format only itself, you +can do this with "git format-patch -1 ". By default, each output file is numbered sequentially from 1, and uses the first line of the commit message (massaged for pathname safety) as @@ -170,6 +166,13 @@ not add any suffix. applied. By default the contents of changes in those files are encoded in the patch. +--root:: + Treat the revision argument as a , even if it + is just a single commit (that would normally be treated as a + ). Note that root commits included in the specified + range are always formatted as creation patches, independently + of this flag. + CONFIGURATION ------------- You can specify extra mail header lines to be added to each message From 3f7d99282d336824b789a5ccb2523a5d84f9be2e Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Wed, 18 Mar 2009 19:05:56 +0100 Subject: [PATCH 57/95] rebase: fix typo (force_rebas -> force-rebas) Signed-off-by: Michele Ballabio Signed-off-by: Junio C Hamano --- git-rebase.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-rebase.sh b/git-rebase.sh index 0ade699228..b83fd3f970 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -319,7 +319,7 @@ do --root) rebase_root=t ;; - -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force_rebas|--force-rebase) + -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase) force_rebase=t ;; -*) From d7d9c2d04962b5aec34ec891d82dd74262306c56 Mon Sep 17 00:00:00 2001 From: Michael Hendricks Date: Thu, 26 Mar 2009 10:51:05 -0600 Subject: [PATCH 58/95] format-patch: add arbitrary email headers format-patch supports the format.headers configuration for adding arbitrary email headers to the patches it outputs. This patch adds support for an --add-header argument which makes the same feature available from the command line. This is useful when the content of custom email headers must change from branch to branch. This patch has been sponsored by Grant Street Group Signed-off-by: Michael Hendricks Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 5 +++++ builtin-log.c | 2 ++ t/t4014-format-patch.sh | 15 +++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index c2eb5fab4c..51fd716902 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -161,6 +161,11 @@ if that is not set. Add a "Cc:" header to the email headers. This is in addition to any configured headers, and may be used multiple times. +--add-header=
:: + Add an arbitrary header to the email headers. This is in addition + to any configured headers, and may be used multiple times. + For example, --add-header="Organization: git-foo" + --cover-letter:: In addition to the patches, generate a cover letter file containing the shortlog and the overall diffstat. You can diff --git a/builtin-log.c b/builtin-log.c index c7a5772594..27bc0dce23 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -918,6 +918,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) cover_letter = 1; else if (!strcmp(argv[i], "--no-binary")) no_binary_diff = 1; + else if (!prefixcmp(argv[i], "--add-header=")) + add_header(argv[i] + 13); else argv[j++] = argv[i]; } diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index f187d15e32..11061ddd5b 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -128,6 +128,21 @@ test_expect_success 'additional command line cc' ' grep "^ *S. E. Cipient $" patch5 ' +test_expect_success 'command line headers' ' + + git config --unset-all format.headers && + git format-patch --add-header="Cc: R. E. Cipient " --stdout master..side | sed -e "/^$/q" >patch6 && + grep "^Cc: R. E. Cipient $" patch6 +' + +test_expect_success 'configuration headers and command line headers' ' + + git config --replace-all format.headers "Cc: R. E. Cipient " && + git format-patch --add-header="Cc: S. E. Cipient " --stdout master..side | sed -e "/^$/q" >patch7 && + grep "^Cc: R. E. Cipient ,$" patch7 && + grep "^ *S. E. Cipient $" patch7 +' + test_expect_success 'multiple files' ' rm -rf patches/ && From 81db4abf84ec7fbebeb08f6ad506138da2e7e4cd Mon Sep 17 00:00:00 2001 From: Emil Sit Date: Fri, 27 Mar 2009 21:57:18 -0400 Subject: [PATCH 59/95] test-lib: Clean up comments and Makefile. Bring documentation in test-lib and clean target in Makefile in-line with abc5d372. Signed-off-by: Emil Sit Signed-off-by: Junio C Hamano --- t/Makefile | 2 +- t/test-lib.sh | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/t/Makefile b/t/Makefile index ed49c20b16..9149373032 100644 --- a/t/Makefile +++ b/t/Makefile @@ -24,7 +24,7 @@ pre-clean: $(RM) -r test-results clean: - $(RM) -r 'trash directory' test-results + $(RM) -r 'trash directory'.* test-results aggregate-results-and-cleanup: $(T) $(MAKE) aggregate-results diff --git a/t/test-lib.sh b/t/test-lib.sh index fc0e1932e6..1b4f216385 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -441,14 +441,6 @@ test_done () { fi case "$test_failure" in 0) - # We could: - # cd .. && rm -fr 'trash directory' - # but that means we forbid any tests that use their own - # subdirectory from calling test_done without coming back - # to where they started from. - # The Makefile provided will clean this test area so - # we will leave things as they are. - say_color pass "passed all $msg" test -d "$remove_trash" && From a1b1ae0571f6b57117678aeaa1939d97c992a254 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 28 Mar 2009 00:55:52 -0700 Subject: [PATCH 60/95] Update draft release notes to 1.6.3 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.3.txt | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/RelNotes-1.6.3.txt b/Documentation/RelNotes-1.6.3.txt index 0d8260a842..f0a2e41c71 100644 --- a/Documentation/RelNotes-1.6.3.txt +++ b/Documentation/RelNotes-1.6.3.txt @@ -22,12 +22,12 @@ branch pointed at by its HEAD, gets a large warning. You can choose what should happen upon such a push by setting the configuration variable receive.denyDeleteCurrent in the receiving repository. -In a future release, the default of "git push" without further -arguments might be changed. Currently, it will push all matching -refspecs to the current remote. A configuration variable push.default -has been introduced to select the default behaviour. To ease the -transition, a big warning is issued if this is not configured and a -git push without arguments is attempted. +When the user does not tell "git push" what to push, it has always +pushed matching refs. For some people it is unexpected, and a new +configuration variable push.default has been introduced to allow +changing a different default behaviour. To advertise the new feature, +a big warning is issued if this is not configured and a git push without +arguments is attempted. Updates since v1.6.2 @@ -46,6 +46,9 @@ Updates since v1.6.2 repositories. It may not be useful in practice; meant primarily for testing. +* http transport learned to prompt and use password when fetching from or + pushing to http://user@host.xz/ URL. + * (msysgit) progress output that is sent over the sideband protocol can be handled appropriately in Windows console. @@ -99,6 +102,8 @@ Updates since v1.6.2 * Test scripts can be run under valgrind. +* Test scripts can be run with installed git. + * Makefile learned 'coverage' option to run the test suites with coverage tracking enabled. @@ -111,11 +116,20 @@ release, unless otherwise noted. Here are fixes that this release has, but have not been backported to v1.6.2.X series. +* "git-blame -S" did not quite work near the commits that were given + on the command line correctly (jc/maint-1.6.0-blame-s). + +* The initial checkout did not read the attributes from the .gitattribute + file that is being checked out. + +* git-diff feeds files in work-tree representation to external diff and + textconv (js/maint-diff-temp-smudge). + * git-gc spent excessive amount of time to decide if an object appears in a locally existing pack (if needed, backport by merging 69e020a). --- exec >/var/tmp/1 -O=v1.6.2.1-213-g7d4e3a7 +O=v1.6.2.1-399-gaa72a14 echo O=$(git describe master) git shortlog --no-merges $O..master ^maint From 4f821012c3feb7c0a36be3849e971fbeff4fbc3b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 28 Mar 2009 22:10:08 -0700 Subject: [PATCH 61/95] git-svn: fix ls-tree usage with dash-prefixed paths To find the blob object name given a tree and pathname, we were incorrectly calling "git ls-tree" with a "--" argument followed by the pathname of the file we wanted to get. git ls-tree -- --dashed/path/name.c Unlike many command-line interfaces, the "--" alone does not symbolize the end of non-option arguments on the command-line. ls-tree interprets the "--" as a prefix to match against, thus the entire contents of the --dashed/* hierarchy would be returned because the "--" matches "--dashed" and every path under it. Thanks to Anton Gyllenberg for pointing me toward the Twisted repository as a real-world example of this case. Signed-off-by: Eric Wong --- git-svn.perl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 8be6be00c6..f21cfb462d 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3387,15 +3387,18 @@ sub delete_entry { return undef if ($gpath eq ''); # remove entire directories. - if (command('ls-tree', $self->{c}, '--', $gpath) =~ /^040000 tree/) { + my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath") + =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/); + if ($tree) { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, - $self->{c}, '--', $gpath); + $tree); local $/ = "\0"; while (<$ls>) { chomp; - $self->{gii}->remove($_); - print "\tD\t$_\n" unless $::_q; + my $rmpath = "$gpath/$_"; + $self->{gii}->remove($rmpath); + print "\tD\t$rmpath\n" unless $::_q; } print "\tD\t$gpath/\n" unless $::_q; command_close_pipe($ls, $ctx); @@ -3414,8 +3417,8 @@ sub open_file { goto out if is_path_ignored($path); my $gpath = $self->git_path($path); - ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath) - =~ /^(\d{6}) blob ([a-f\d]{40})\t/); + ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath") + =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/); unless (defined $mode && defined $blob) { die "$path was not found in commit $self->{c} (r$rev)\n"; } From 18d5cf908fe89c780872acc8a9f11d061e4556b6 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 29 Mar 2009 20:34:50 +0100 Subject: [PATCH 62/95] git-svn: don't output git commits in quiet mode Ideally only errors should be output in this mode so fetch can be run from cron and normally produce no output. Without this change it would output a single line on each git commit, e.g. r1909 = 32ef87860662526d4a62f903949ed21e0341079e (u2_10_12_branch) Signed-off-by: Simon Arlott Acked-by: Eric Wong --- git-svn.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index f21cfb462d..e5c3dfe5d2 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2331,13 +2331,13 @@ sub do_git_commit { $self->{last_rev} = $log_entry->{revision}; $self->{last_commit} = $commit; - print "r$log_entry->{revision}"; + print "r$log_entry->{revision}" unless $::_q; if (defined $log_entry->{svm_revision}) { - print " (\@$log_entry->{svm_revision})"; + print " (\@$log_entry->{svm_revision})" unless $::_q; $self->rev_map_set($log_entry->{svm_revision}, $commit, 0, $self->svm_uuid); } - print " = $commit ($self->{ref_id})\n"; + print " = $commit ($self->{ref_id})\n" unless $::_q; if (--$_gc_nr == 0) { $_gc_nr = $_gc_period; gc(); From 41a5c70f2caf5c22859574f0503afbdb3728a89c Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Mon, 23 Mar 2009 12:53:06 +0000 Subject: [PATCH 63/95] test-suite: adding a test for fast-export with tag variants Signed-off-by: Erik Faye-Lund Signed-off-by: Junio C Hamano --- t/t9301-fast-export.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index 86c376088c..2e31f67465 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -259,4 +259,20 @@ test_expect_success 'cope with tagger-less tags' ' ' +test_expect_success 'set-up a few more tags for tag export tests' ' + git checkout -f master && + HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` && + git tag tree_tag -m "tagging a tree" $HEAD_TREE && + git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE && + git tag tag-obj_tag -m "tagging a tag" tree_tag-obj && + git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj +' + +# NEEDSWORK: not just check return status, but validate the output +# two tests commented out due to crash and thus unreliable return code +test_expect_failure 'tree_tag' 'git fast-export tree_tag' +test_expect_failure 'tree_tag-obj' 'git fast-export tree_tag-obj' +test_expect_failure 'tag-obj_tag' 'git fast-export tag-obj_tag' +test_expect_failure 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' + test_done From 2d07f6d4b728d19d115b89123224268718f34efd Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Mon, 23 Mar 2009 12:53:07 +0000 Subject: [PATCH 64/95] builtin-fast-export.c: turn error into warning fast-import doesn't have a syntax to support tree-objects (and some other object-types), so fast-export shouldn't handle them. However, aborting the operation is a bit drastic. This patch turns the error into a warning instead. Signed-off-by: Erik Faye-Lund Signed-off-by: Junio C Hamano --- builtin-fast-export.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builtin-fast-export.c b/builtin-fast-export.c index fdf4ae9ebd..8a6cf5e649 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -378,8 +378,10 @@ static void get_tags_and_duplicates(struct object_array *pending, } break; default: - die ("Unexpected object of type %s", - typename(e->item->type)); + warning("%s: Unexpected object of type %s, skipping.", + e->name, + typename(e->item->type)); + continue; } if (commit->util) /* more than one name for the same object */ From c0582c53bcf4e83bba70e1ad23abbad31f96ebc8 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Mon, 23 Mar 2009 12:53:08 +0000 Subject: [PATCH 65/95] builtin-fast-export.c: fix crash on tagged trees If a tag object points to a tree (or another unhandled type), the commit- pointer is left uninitialized and later dereferenced. This patch adds a default case to the switch that issues a warning and skips the object. Signed-off-by: Erik Faye-Lund Signed-off-by: Junio C Hamano --- builtin-fast-export.c | 4 ++++ t/t9301-fast-export.sh | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 8a6cf5e649..1ec459f057 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -375,6 +375,10 @@ static void get_tags_and_duplicates(struct object_array *pending, case OBJ_BLOB: handle_object(tag->object.sha1); continue; + default: + warning("Tag points to object of unexpected type %s, skipping.", + typename(tag->object.type)); + continue; } break; default: diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index 2e31f67465..b1f75ceea4 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -269,9 +269,8 @@ test_expect_success 'set-up a few more tags for tag export tests' ' ' # NEEDSWORK: not just check return status, but validate the output -# two tests commented out due to crash and thus unreliable return code -test_expect_failure 'tree_tag' 'git fast-export tree_tag' -test_expect_failure 'tree_tag-obj' 'git fast-export tree_tag-obj' +test_expect_success 'tree_tag' 'git fast-export tree_tag' +test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj' test_expect_failure 'tag-obj_tag' 'git fast-export tag-obj_tag' test_expect_failure 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' From 1982467d9229e3c92157f2a41363365dcb866e86 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Mon, 23 Mar 2009 12:53:09 +0000 Subject: [PATCH 66/95] builtin-fast-export.c: handle nested tags When tags that points to tags are passed to fast-export, an error is given, saying "Tag [TAGNAME] points nowhere?". This fix calls parse_object() on the object before referencing it's tag, to ensure the tag-info is fully initialized. In addition, it inserts a comment to point out where nested tags are handled. This is consistent with the comment for signed tags. Signed-off-by: Erik Faye-Lund Signed-off-by: Junio C Hamano --- builtin-fast-export.c | 5 ++++- t/t9301-fast-export.sh | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 1ec459f057..f171ee4a2b 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -362,7 +362,10 @@ static void get_tags_and_duplicates(struct object_array *pending, break; case OBJ_TAG: tag = (struct tag *)e->item; + + /* handle nested tags */ while (tag && tag->object.type == OBJ_TAG) { + parse_object(tag->object.sha1); string_list_append(full_name, extra_refs)->util = tag; tag = (struct tag *)tag->tagged; } @@ -375,7 +378,7 @@ static void get_tags_and_duplicates(struct object_array *pending, case OBJ_BLOB: handle_object(tag->object.sha1); continue; - default: + default: /* OBJ_TAG (nested tags) is already handled */ warning("Tag points to object of unexpected type %s, skipping.", typename(tag->object.type)); continue; diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index b1f75ceea4..4a87f36258 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -271,7 +271,7 @@ test_expect_success 'set-up a few more tags for tag export tests' ' # NEEDSWORK: not just check return status, but validate the output test_expect_success 'tree_tag' 'git fast-export tree_tag' test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj' -test_expect_failure 'tag-obj_tag' 'git fast-export tag-obj_tag' -test_expect_failure 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' +test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag' +test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' test_done From 63801da88d8638eb6cf26d6305a721ad3731e216 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 29 Mar 2009 22:42:27 +0200 Subject: [PATCH 67/95] import-zips: fix thinko Embarrassingly, the common prefix calculation did not work properly, due to a mistake in the assignment: instead of assigning the dirname of the current file name, the dirname of the current common prefix needs to be assigned to common prefix, when the current prefix does not match the current file name. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/fast-import/import-zips.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py index c674fa2d1b..7051a83a59 100755 --- a/contrib/fast-import/import-zips.py +++ b/contrib/fast-import/import-zips.py @@ -44,7 +44,8 @@ for zipfile in argv[1:]: common_prefix = name[:name.rfind('/') + 1] else: while not name.startswith(common_prefix): - common_prefix = name[:name.rfind('/') + 1] + last_slash = common_prefix[:-1].rfind('/') + 1 + common_prefix = common_prefix[:last_slash] mark[name] = ':' + str(next_mark) next_mark += 1 From b8fee3a3884b4a18c2f0b5313255dd180c44ab78 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 28 Mar 2009 23:10:45 -0700 Subject: [PATCH 68/95] git-svn: fix ls-tree usage with dash-prefixed paths To find the blob object name given a tree and pathname, we were incorrectly calling "git ls-tree" with a "--" argument followed by the pathname of the file we wanted to get. git ls-tree -- --dashed/path/name.c Unlike many command-line interfaces, the "--" alone does not symbolize the end of non-option arguments on the command-line. ls-tree interprets the "--" as a prefix to match against, thus the entire contents of the --dashed/* hierarchy would be returned because the "--" matches "--dashed" and every path under it. Thanks to Anton Gyllenberg for pointing me toward the Twisted repository as a real-world example of this case. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 959eb52f3f..931d1a37bc 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3384,15 +3384,18 @@ sub delete_entry { return undef if ($gpath eq ''); # remove entire directories. - if (command('ls-tree', $self->{c}, '--', $gpath) =~ /^040000 tree/) { + my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath") + =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/); + if ($tree) { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, - $self->{c}, '--', $gpath); + $tree); local $/ = "\0"; while (<$ls>) { chomp; - $self->{gii}->remove($_); - print "\tD\t$_\n" unless $::_q; + my $rmpath = "$gpath/$_"; + $self->{gii}->remove($rmpath); + print "\tD\t$rmpath\n" unless $::_q; } print "\tD\t$gpath/\n" unless $::_q; command_close_pipe($ls, $ctx); @@ -3411,8 +3414,8 @@ sub open_file { goto out if is_path_ignored($path); my $gpath = $self->git_path($path); - ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath) - =~ /^(\d{6}) blob ([a-f\d]{40})\t/); + ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath") + =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/); unless (defined $mode && defined $blob) { die "$path was not found in commit $self->{c} (r$rev)\n"; } From 6e1825186bd052fc1f77b7c8c9a31fbb9a67d90c Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Sat, 28 Mar 2009 21:39:10 -0400 Subject: [PATCH 69/95] send-email: refactor and ensure prompting doesn't loop forever Several places in send-email prompt for input, and will do so forever when the input is EOF. This is poor behavior when send-email is run unattended (say from cron). This patch refactors the prompting to an ask() function which takes a prompt, an optional default, and an optional regex to validate the input. The function returns on EOF, or if a default is provided and the user simply types return, or if the input passes the validating regex (which accepts all input by default). The ask() function gives up after 10 tries in case of invalid input. There are four callers of the function: 1) "Who should the emails appear to be from?" which provides a default sender. Previously the user would have to type ctrl-d to accept the default. Now the user can just hit return, or type ctrl-d. 2) "Who should the emails be sent to?". Previously this prompt passed a second argument ("") to $term->readline() which was ignored. I believe the intent was to allow the user to just hit return. Now the user can do so, or type ctrl-d. 3) "Message-ID to be used as In-Reply-To for the first email?". Previously this prompt passed a second argument (effectively undef) to $term->readline() which was ignored. I believe the intent was the same as for (2), to allow the user to just hit return. Now the user can do so, or type ctrl-d. 4) "Send this email?". Previously this prompt would loop forever until it got a valid reply. Now it stops prompting on EOF or a valid reply. In the case where confirm = "inform", it now defaults to "y" on EOF or the user hitting return, otherwise an invalid reply causes send-email to terminate. A followup patch adds tests for the new functionality. Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- git-send-email.perl | 66 +++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/git-send-email.perl b/git-send-email.perl index 546d2ebc0c..5916c86b68 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -606,32 +606,40 @@ EOT do_edit(@files); } +sub ask { + my ($prompt, %arg) = @_; + my $valid_re = $arg{valid_re} || ""; # "" matches anything + my $default = $arg{default}; + my $resp; + my $i = 0; + while ($i++ < 10) { + $resp = $term->readline($prompt); + if (!defined $resp) { # EOF + print "\n"; + return defined $default ? $default : undef; + } + if ($resp eq '' and defined $default) { + return $default; + } + if ($resp =~ /$valid_re/) { + return $resp; + } + } + return undef; +} + my $prompting = 0; if (!defined $sender) { $sender = $repoauthor || $repocommitter || ''; - - while (1) { - $_ = $term->readline("Who should the emails appear to be from? [$sender] "); - last if defined $_; - print "\n"; - } - - $sender = $_ if ($_); + $sender = ask("Who should the emails appear to be from? [$sender] ", + default => $sender); print "Emails will be sent from: ", $sender, "\n"; $prompting++; } if (!@to) { - - - while (1) { - $_ = $term->readline("Who should the emails be sent to? ", ""); - last if defined $_; - print "\n"; - } - - my $to = $_; - push @to, parse_address_line($to); + my $to = ask("Who should the emails be sent to? "); + push @to, parse_address_line($to) if defined $to; # sanitized/validated later $prompting++; } @@ -651,13 +659,8 @@ sub expand_aliases { @bcclist = expand_aliases(@bcclist); if ($thread && !defined $initial_reply_to && $prompting) { - while (1) { - $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to); - last if defined $_; - print "\n"; - } - - $initial_reply_to = $_; + $initial_reply_to = ask( + "Message-ID to be used as In-Reply-To for the first email? "); } if (defined $initial_reply_to) { $initial_reply_to =~ s/^\s*readline( - "Send this email? ([y]es|[n]o|[q]uit|[a]ll): " - )); - last if /^(?:yes|y|no|n|quit|q|all|a)/i; - print "\n"; - } + $_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ", + valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i, + default => $ask_default); + die "Send this email reply required" unless defined $_; if (/^n/i) { return; } elsif (/^q/i) { From c18f75a1e96ff0f028edf94effd10cf56d892f22 Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Sat, 28 Mar 2009 21:39:11 -0400 Subject: [PATCH 70/95] send-email: add tests for refactored prompting Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- t/t9001-send-email.sh | 52 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index e426c96fb7..b4de98c1f2 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -421,8 +421,8 @@ test_confirm () { --from="Example " \ --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ - $@ \ - $patches | grep "Send this email" + $@ $patches > stdout && + grep "Send this email" stdout } test_expect_success '--confirm=always' ' @@ -444,8 +444,10 @@ test_expect_success '--confirm=compose' ' test_expect_success 'confirm by default (due to cc)' ' CONFIRM=$(git config --get sendemail.confirm) && git config --unset sendemail.confirm && - test_confirm && - git config sendemail.confirm $CONFIRM + test_confirm + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" ' test_expect_success 'confirm by default (due to --compose)' ' @@ -457,6 +459,48 @@ test_expect_success 'confirm by default (due to --compose)' ' test $ret = "0" ' +test_expect_success 'confirm detects EOF (inform assumes y)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm detects EOF (auto causes failure)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + GIT_SEND_EMAIL_NOTTY=1 \ + test_must_fail git send-email \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm doesnt loop forever' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + yes "bogus" | GIT_SEND_EMAIL_NOTTY=1 \ + test_must_fail git send-email \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + test_expect_success '--compose adds MIME for utf8 body' ' clean_fake_sendmail && (echo "#!$SHELL_PATH" && From 7b60d0d3e4d9bb8995a010b0304ec92d0fdff69c Mon Sep 17 00:00:00 2001 From: Allan Caffee Date: Mon, 30 Mar 2009 10:13:45 -0400 Subject: [PATCH 71/95] Documentation: update graph api example. As of commit 03300c0 the graph API uses '*' for all nodes including merges. This updates the example in the documentation to match. Signed-off-by: Allan Caffee Signed-off-by: Junio C Hamano --- Documentation/technical/api-history-graph.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/technical/api-history-graph.txt b/Documentation/technical/api-history-graph.txt index e9559790a3..d66e61b1ec 100644 --- a/Documentation/technical/api-history-graph.txt +++ b/Documentation/technical/api-history-graph.txt @@ -148,22 +148,22 @@ outputting that information, if desired. ------------ * * -M +* |\ * | | | * | \ \ | \ \ -M-. \ \ +*-. \ \ |\ \ \ \ | | * | | | | | | | * | | | | | * -| | | | | M +| | | | | * | | | | | |\ | | | | | | * | * | | | | | -| | | | | M \ +| | | | | * \ | | | | | |\ | | | | | * | | | | | | | * | | | From abfd5fa8725ef1a0ffddb0d1a768cbbfbc74a972 Mon Sep 17 00:00:00 2001 From: Nico -telmich- Schottelius Date: Mon, 30 Mar 2009 13:58:21 +0200 Subject: [PATCH 72/95] git-tag(1): add hint about commit messages If a tag is not annotated, git tag displays the commit message instead. Add this hint to the manpage to unhide this secret. Signed-off-by: Nico Schottelius Signed-off-by: Junio C Hamano --- Documentation/git-tag.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 046ab3542b..1f34948167 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -63,6 +63,7 @@ OPTIONS are printed when using -l. The default is not to print any annotation lines. If no number is given to `-n`, only the first line is printed. + If the tag is not annotated, the commit message is displayed instead. -l :: List tags with names that match the given pattern (or all if no pattern is given). From 67f1fe5f08d3f6146cf13f8a65ceeab1509581a8 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Mon, 16 Feb 2009 17:34:57 +0100 Subject: [PATCH 73/95] bash completion: only show 'log --merge' if merging The gitk completion only shows --merge if MERGE_HEAD is present. Do it the same way for git-log completion. Signed-off-by: Thomas Rast Acked-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 554a03ff4f..0bb74c05e5 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -937,6 +937,11 @@ _git_log () __git_has_doubledash && return local cur="${COMP_WORDS[COMP_CWORD]}" + local g="$(git rev-parse --git-dir 2>/dev/null)" + local merge="" + if [ -f $g/MERGE_HEAD ]; then + merge="--merge" + fi case "$cur" in --pretty=*) __gitcomp " @@ -968,7 +973,7 @@ _git_log () --decorate --diff-filter= --color-words --walk-reflogs --parents --children --full-history - --merge + $merge " return ;; From ba7906f2f4c332f814d270d2e16b0010516fc53e Mon Sep 17 00:00:00 2001 From: "Daniel Cheng (aka SDiZ)" Date: Mon, 30 Mar 2009 19:27:37 +0800 Subject: [PATCH 74/95] Fix bash completion in path with spaces Signed-off-by: Daniel Cheng (aka SDiZ) Trivially-acked-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 0bb74c05e5..8fc01fb497 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -939,7 +939,7 @@ _git_log () local cur="${COMP_WORDS[COMP_CWORD]}" local g="$(git rev-parse --git-dir 2>/dev/null)" local merge="" - if [ -f $g/MERGE_HEAD ]; then + if [ -f "$g/MERGE_HEAD" ]; then merge="--merge" fi case "$cur" in @@ -1681,7 +1681,7 @@ _gitk () local cur="${COMP_WORDS[COMP_CWORD]}" local g="$(git rev-parse --git-dir 2>/dev/null)" local merge="" - if [ -f $g/MERGE_HEAD ]; then + if [ -f "$g/MERGE_HEAD" ]; then merge="--merge" fi case "$cur" in From 76d3cc50b518d1c28d802ad2917063d8a5d34419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Mon, 30 Mar 2009 12:11:40 +0200 Subject: [PATCH 75/95] Documentation: enhance branch..{remote,merge} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation for branch.*.merge is very dense, so add a simple explanation on top of it. And branch.*.remote also affects 'git push'. Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- Documentation/config.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 750675530c..a6fc8da0bf 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -473,10 +473,14 @@ branch.autosetuprebase:: This option defaults to never. branch..remote:: - When in branch , it tells 'git-fetch' which remote to fetch. - If this option is not given, 'git-fetch' defaults to remote "origin". + When in branch , it tells 'git-fetch' and 'git-push' which + remote to fetch from/push to. It defaults to `origin` if no remote is + configured. `origin` is also used if you are not on any branch. branch..merge:: + Defines, together with branch..remote, the upstream branch + for the given branch. It tells 'git-fetch'/'git-pull' which + branch to merge from. When in branch , it tells 'git-fetch' the default refspec to be marked for merging in FETCH_HEAD. The value is handled like the remote part of a refspec, and must match a From 01eadafccbeae485503f5373dc60cc5a04877c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Mon, 30 Mar 2009 12:11:41 +0200 Subject: [PATCH 76/95] Documentation: push.default applies to all remotes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit push.default is not only for the current remote but setting the default behaviour for all remotes. Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- Documentation/config.txt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index a6fc8da0bf..ad22cb875e 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1202,19 +1202,14 @@ push.default:: Defines the action git push should take if no refspec is given on the command line, no refspec is configured in the remote, and no refspec is implied by any of the options given on the command - line. -+ -The term `current remote` means the remote configured for the current -branch, or `origin` if no remote is configured. `origin` is also used -if you are not on any branch. Possible values are: + line. Possible values are: + * `nothing` do not push anything. -* `matching` push all matching branches to the current remote. +* `matching` push all matching branches. All branches having the same name in both ends are considered to be - matching. This is the current default value. + matching. This is the default. * `tracking` push the current branch to the branch it is tracking. -* `current` push the current branch to a branch of the same name on the - current remote. +* `current` push the current branch to a branch of the same name. rebase.stat:: Whether to show a diffstat of what changed upstream since the last From 8c7f78823888306c1cceafcf5fd26739eef99ce3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 30 Mar 2009 13:29:31 -0700 Subject: [PATCH 77/95] Update draft release notes to 1.6.2.2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.2.2.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/RelNotes-1.6.2.2.txt b/Documentation/RelNotes-1.6.2.2.txt index 28bfa5399b..4f4c47341f 100644 --- a/Documentation/RelNotes-1.6.2.2.txt +++ b/Documentation/RelNotes-1.6.2.2.txt @@ -27,9 +27,16 @@ Fixes since v1.6.2.1 * 'git-submodule add' did not tolerate extra slashes and ./ in the path it accepted from the command line; it now is more lenient. +* git-svn misbehaved when the project contained a path that began with + two dashes. + +* import-zips script (in contrib) did not compute the common directory + prefix correctly. + +Many small documentation updates are included as well. --- exec >/var/tmp/1 -O=v1.6.2.1-23-g67c176f +O=v1.6.2.1-46-gb19293d echo O=$(git describe maint) git shortlog --no-merges $O..maint From 49750f30767b3eb4683e8d2f4d742354dd5d03d3 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Mon, 30 Mar 2009 19:31:41 +0100 Subject: [PATCH 78/95] git-svn: add a double quiet option to hide git commits People may expect/prefer -q to still show git commits, so this change allows a second -q to hide them. Signed-off-by: Michael Poole Signed-off-by: Simon Arlott Acked-by: Eric Wong --- Documentation/git-svn.txt | 3 ++- git-svn.perl | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index cda3389331..8163a19843 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -385,7 +385,8 @@ config key: svn.authorsfile -q:: --quiet:: - Make 'git-svn' less verbose. + Make 'git-svn' less verbose. Specify a second time to make it + even less verbose. --repack[=]:: --repack-flags=:: diff --git a/git-svn.perl b/git-svn.perl index e5c3dfe5d2..d9197989d2 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -68,6 +68,7 @@ my ($_stdin, $_help, $_edit, $_prefix, $_no_checkout, $_url, $_verbose, $_git_format, $_commit_url, $_tag); $Git::SVN::_follow_parent = 1; +$_q ||= 0; my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username, 'config-dir=s' => \$Git::SVN::Ra::config_dir, 'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache, @@ -80,7 +81,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent, 'useSvnsyncProps' => \$Git::SVN::_use_svnsync_props, 'log-window-size=i' => \$Git::SVN::Ra::_log_window_size, 'no-checkout' => \$_no_checkout, - 'quiet|q' => \$_q, + 'quiet|q+' => \$_q, 'repack-flags|repack-args|repack-opts=s' => \$Git::SVN::_repack_flags, 'use-log-author' => \$Git::SVN::_use_log_author, @@ -2331,13 +2332,13 @@ sub do_git_commit { $self->{last_rev} = $log_entry->{revision}; $self->{last_commit} = $commit; - print "r$log_entry->{revision}" unless $::_q; + print "r$log_entry->{revision}" unless $::_q > 1; if (defined $log_entry->{svm_revision}) { - print " (\@$log_entry->{svm_revision})" unless $::_q; + print " (\@$log_entry->{svm_revision})" unless $::_q > 1; $self->rev_map_set($log_entry->{svm_revision}, $commit, 0, $self->svm_uuid); } - print " = $commit ($self->{ref_id})\n" unless $::_q; + print " = $commit ($self->{ref_id})\n" unless $::_q > 1; if (--$_gc_nr == 0) { $_gc_nr = $_gc_period; gc(); From e161acd11da05add6575a6931f4ff38a5685dd7d Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Wed, 1 Apr 2009 12:34:44 +0430 Subject: [PATCH 79/95] builtin-clone.c: make junk_pid static junk_pid is used only in builtin-clone.c. Signed-off-by: Ali Gholami Rudi Signed-off-by: Junio C Hamano --- builtin-clone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-clone.c b/builtin-clone.c index 0031b5f51c..736c72c236 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -270,7 +270,7 @@ static const struct ref *clone_local(const char *src_repo, static const char *junk_work_tree; static const char *junk_git_dir; -pid_t junk_pid; +static pid_t junk_pid; static void remove_junk(void) { From 50b5f420fe94399e3da867a0ff0585bc5d3fe86f Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Wed, 1 Apr 2009 15:52:25 +0430 Subject: [PATCH 80/95] builtin-clone.c: no need to strdup for setenv The setenv function makes a copy, itself. Signed-off-by: Ali Gholami Rudi Signed-off-by: Junio C Hamano --- builtin-clone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-clone.c b/builtin-clone.c index 736c72c236..880373f279 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -406,7 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) atexit(remove_junk); sigchain_push_common(remove_junk_on_signal); - setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); + setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1); if (safe_create_leading_directories_const(git_dir) < 0) die("could not create leading directories of '%s'", git_dir); From bf637803a799451e7feb596422932dd60f0384e1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 31 Mar 2009 02:18:36 +0200 Subject: [PATCH 81/95] mailmap: resurrect lower-casing of email addresses Commit 0925ce4(Add map_user() and clear_mailmap() to mailmap) broke the lower-casing of email addresses. This mostly did not matter if your .mailmap has only lower-case email addresses; However, we did not require .mailmap to contain lowercase-only email addresses. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- mailmap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mailmap.c b/mailmap.c index f12bb45a3f..6be91b60df 100644 --- a/mailmap.c +++ b/mailmap.c @@ -50,6 +50,15 @@ static void add_mapping(struct string_list *map, { struct mailmap_entry *me; int index; + char *p; + + if (old_email) + for (p = old_email; *p; p++) + *p = tolower(*p); + if (new_email) + for (p = new_email; *p; p++) + *p = tolower(*p); + if (old_email == NULL) { old_email = new_email; new_email = NULL; From 2346431e476ab9f095f0dd2921f63fa071039bb8 Mon Sep 17 00:00:00 2001 From: Chris Johnsen Date: Wed, 1 Apr 2009 03:50:34 -0500 Subject: [PATCH 82/95] Documentation: use "spurious .sp" XSLT if DOCBOOK_SUPPRESS_SP is set With this change, the "spurious .sp" suppression XSLT code is disabled by default. It can be enabled by defining DOCBOOK_SUPPRESS_SP. The "spurious .sp" XSLT fragment was used to work around a bug first released in docbook-xsl 1.69.1. Modern versions of docbook-xsl are negatively affected by the code (some empty lines are omitted from manpage output; see ). The key revisions in the docbook SVN repo seem to be 5144 (before docbook-xsl 1.69.1) and 6359 (before docbook-xsl 1.71.1). Testing done with asciidoc 8.3.1 and docbook-xsl 1.74.0. Signed-off-by: Chris Johnsen Signed-off-by: Junio C Hamano --- Documentation/Makefile | 7 ++++++- Documentation/RelNotes-1.6.3.txt | 5 +++++ Documentation/manpage-base.xsl | 13 ------------- Documentation/manpage-suppress-sp.xsl | 21 +++++++++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 Documentation/manpage-suppress-sp.xsl diff --git a/Documentation/Makefile b/Documentation/Makefile index dae3174667..dba97dc21d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -69,7 +69,9 @@ endif # # For docbook-xsl ... # -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) -# 1.69.0-1.71.1, no extra settings are needed? +# 1.69.0, no extra settings are needed? +# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? +# 1.71.1, no extra settings are needed? # 1.72.0, set DOCBOOK_XSL_172. # 1.73.0-, set ASCIIDOC_NO_ROFF # @@ -97,6 +99,9 @@ endif ifdef MAN_BOLD_LITERAL XMLTO_EXTRA += -m manpage-bold-literal.xsl endif +ifdef DOCBOOK_SUPPRESS_SP +XMLTO_EXTRA += -m manpage-suppress-sp.xsl +endif # # Please note that there is a minor bug in asciidoc. diff --git a/Documentation/RelNotes-1.6.3.txt b/Documentation/RelNotes-1.6.3.txt index 0d8260a842..95405907b8 100644 --- a/Documentation/RelNotes-1.6.3.txt +++ b/Documentation/RelNotes-1.6.3.txt @@ -102,6 +102,11 @@ Updates since v1.6.2 * Makefile learned 'coverage' option to run the test suites with coverage tracking enabled. +* Building the manpages with docbook-xsl between 1.69.1 and 1.71.1 now + requires setting DOCBOOK_SUPPRESS_SP to work around a docbook-xsl bug. + This workaround used to be enabled by default, but causes problems + with newer versions of docbook-xsl. + Fixes since v1.6.2 ------------------ diff --git a/Documentation/manpage-base.xsl b/Documentation/manpage-base.xsl index 16e2e40976..a264fa6160 100644 --- a/Documentation/manpage-base.xsl +++ b/Documentation/manpage-base.xsl @@ -32,17 +32,4 @@ br - - - - - - - - - - - diff --git a/Documentation/manpage-suppress-sp.xsl b/Documentation/manpage-suppress-sp.xsl new file mode 100644 index 0000000000..a63c7632a8 --- /dev/null +++ b/Documentation/manpage-suppress-sp.xsl @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + From fd94836923708581ca3f9b5c42a6d600c2f631dc Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 31 Mar 2009 08:29:23 -0400 Subject: [PATCH 83/95] fix portability problem with IS_RUN_COMMAND_ERR Some old versions of gcc don't seem to like us negating an enum constant. Let's work around it by negating the other half of the comparison instead. Reported by Pierre Poissinger on gcc 2.9. Signed-off-by: Junio C Hamano --- run-command.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-command.h b/run-command.h index 15e870a65e..e345502843 100644 --- a/run-command.h +++ b/run-command.h @@ -10,7 +10,7 @@ enum { ERR_RUN_COMMAND_WAITPID_SIGNAL, ERR_RUN_COMMAND_WAITPID_NOEXIT, }; -#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK) +#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK) struct child_process { const char **argv; From 5906f54e474c6e8aabb0f6b955d446b509cde06e Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Tue, 31 Mar 2009 12:22:11 -0400 Subject: [PATCH 84/95] send-email: don't attempt to prompt if tty is closed Attempting to prompt when the tty is closed (typically when running from cron) is pointless and emits a warning. This patch causes ask() to return early, squelching the warning. Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- git-send-email.perl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/git-send-email.perl b/git-send-email.perl index 5916c86b68..d790660bcf 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -612,6 +612,9 @@ sub ask { my $default = $arg{default}; my $resp; my $i = 0; + return defined $default ? $default : undef + unless defined $term->IN and defined fileno($term->IN) and + defined $term->OUT and defined fileno($term->OUT); while ($i++ < 10) { $resp = $term->readline($prompt); if (!defined $resp) { # EOF From dc1460aa8de64f62b4612b6d2546ed7b88050de2 Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Tue, 31 Mar 2009 12:22:12 -0400 Subject: [PATCH 85/95] send-email: ask_default should apply to all emails, not just the first Commit 6e18251 made the "Send this email?" prompt assume yes if confirm = "inform" when it was unable to get a valid response. However, the "yes" assumption only worked correctly for the first email. This commit fixes the issue and confirms the fix by modifying the existing test for the prompt to send multiple emails. Reported by Matthieu Moy Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- git-send-email.perl | 3 +-- t/t9001-send-email.sh | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/git-send-email.perl b/git-send-email.perl index d790660bcf..fc153f9459 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -687,7 +687,7 @@ if ($compose && $compose > 0) { # Variables we set as part of the loop over files our ($message_id, %mail, $subject, $reply_to, $references, $message, - $needs_confirm, $message_num); + $needs_confirm, $message_num, $ask_default); sub extract_valid_address { my $address = shift; @@ -845,7 +845,6 @@ X-Mailer: git-send-email $gitversion if ($needs_confirm && !$dry_run) { print "\n$header\n"; - my $ask_default; if ($needs_confirm eq "inform") { $confirm_unconfigured = 0; # squelch this message for the rest of this run $ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index b4de98c1f2..195ff8b27b 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -462,12 +462,14 @@ test_expect_success 'confirm by default (due to --compose)' ' test_expect_success 'confirm detects EOF (inform assumes y)' ' CONFIRM=$(git config --get sendemail.confirm) && git config --unset sendemail.confirm && + rm -fr outdir && + git format-patch -2 -o outdir && GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --from="Example " \ --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ - $patches < /dev/null + outdir/*.patch < /dev/null ret="$?" git config sendemail.confirm ${CONFIRM:-never} test $ret = "0" From 5bd27ebb18f2dd745d1226b59b9f863c63c15fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Wei=C3=9F?= Date: Tue, 31 Mar 2009 18:57:01 +0200 Subject: [PATCH 86/95] Documentation: Remove an odd "instead" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Holger Weiß Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 0e14e732fd..307f2521b4 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -112,7 +112,7 @@ then the cloned repository will become corrupt. --origin :: -o :: Instead of using the remote name 'origin' to keep track - of the upstream repository, use instead. + of the upstream repository, use . --upload-pack :: -u :: From 75fd877e150ecca74f9749bfd6bfa9a6b425ab57 Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Wed, 1 Apr 2009 22:24:28 +0200 Subject: [PATCH 87/95] Cleanup warning about known issues in cvsimport documentation Not all statements were complete sentences. Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- Documentation/git-cvsimport.txt | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index e1fd047bb5..d7bab13f6c 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -173,24 +173,26 @@ ISSUES Problems related to timestamps: * If timestamps of commits in the cvs repository are not stable enough - to be used for ordering commits + to be used for ordering commits changes may show up in the wrong + order. * If any files were ever "cvs import"ed more than once (e.g., import of - more than one vendor release) + more than one vendor release) the HEAD contains the wrong content. * If the timestamp order of different files cross the revision order - within the commit matching time window + within the commit matching time window the order of commits may be + wrong. Problems related to branches: - * Branches on which no commits have been made are not imported + * Branches on which no commits have been made are not imported. * All files from the branching point are added to a branch even if - never added in cvs - * files added to the source branch *after* a daughter branch was - created: If previously no commit was made on the daugther branch they - will erroneously be added to the daughter branch in git + never added in cvs. + * This applies to files added to the source branch *after* a daughter + branch was created: if previously no commit was made on the daughter + branch they will erroneously be added to the daughter branch in git. Problems related to tags: -* Multiple tags on the same revision are not imported +* Multiple tags on the same revision are not imported. If you suspect that any of these issues may apply to the repository you want to import consider using these alternative tools which proved to be From 5288dd58356e53d61e2b3804fc7d8d23c3a46ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Tue, 31 Mar 2009 17:30:39 +0200 Subject: [PATCH 88/95] Mailmap: Allow empty email addresses to be mapped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While it makes no sense to map some email address to an empty one, doing things the other way around can be useful. For example when using filter-branch with an env-filter that employs a mailmap to fix up an import that created such broken commits with empty email addresses. Signed-off-by: Björn Steinbrink Signed-off-by: Junio C Hamano --- mailmap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mailmap.c b/mailmap.c index f12bb45a3f..654c6295cb 100644 --- a/mailmap.c +++ b/mailmap.c @@ -90,7 +90,8 @@ static void add_mapping(struct string_list *map, old_name, old_email, new_name, new_email); } -static char *parse_name_and_email(char *buffer, char **name, char **email) +static char *parse_name_and_email(char *buffer, char **name, + char **email, int allow_empty_email) { char *left, *right, *nstart, *nend; *name = *email = 0; @@ -99,7 +100,7 @@ static char *parse_name_and_email(char *buffer, char **name, char **email) return NULL; if ((right = strchr(left+1, '>')) == NULL) return NULL; - if (left+1 == right) + if (!allow_empty_email && (left+1 == right)) return NULL; /* remove whitespace from beginning and end of name */ @@ -150,8 +151,8 @@ static int read_single_mailmap(struct string_list *map, const char *filename, ch } continue; } - if ((name2 = parse_name_and_email(buffer, &name1, &email1)) != NULL) - parse_name_and_email(name2, &name2, &email2); + if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL) + parse_name_and_email(name2, &name2, &email2, 1); if (email1) add_mapping(map, name1, email1, name2, email2); From 0e5e69a355b7bdd1af6ca33ac7ee35299bda368e Mon Sep 17 00:00:00 2001 From: "Wesley J. Landaker" Date: Wed, 1 Apr 2009 16:05:01 -0600 Subject: [PATCH 89/95] Documentation: git-svn: fix trunk/fetch svn-remote key typo Fix the git-svn documentation svn-remote example section talking about tags and branches by using the proper key "fetch" instead of "trunk". Using "trunk" actually might be nice, but it doesn't currently work. The fetch line for the trunk was also reordered to be at the top of the list, since most people think about the trunk/tags/branches trio in that logical order. Signed-off-by: Wesley J. Landaker Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- Documentation/git-svn.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 8163a19843..b7b1af813d 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -673,9 +673,9 @@ listed below are allowed: ------------------------------------------------------------------------ [svn-remote "project-a"] url = http://server.org/svn + fetch = trunk/project-a:refs/remotes/project-a/trunk branches = branches/*/project-a:refs/remotes/project-a/branches/* tags = tags/*/project-a:refs/remotes/project-a/tags/* - trunk = trunk/project-a:refs/remotes/project-a/trunk ------------------------------------------------------------------------ Keep in mind that the '*' (asterisk) wildcard of the local ref From 3b3637c3f1d752e6e6d559f30cc53bbec18537ef Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Tue, 31 Mar 2009 12:22:13 -0400 Subject: [PATCH 90/95] send-email: correct two tests which were going interactive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c18f75a (send-email: add tests for refactored prompting, 2009-03-28) added two tests which went interactive under the dash shell. This patch corrects the issue, reported by Björn Steinbrink. Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- t/t9001-send-email.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 195ff8b27b..84238f7197 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -478,7 +478,8 @@ test_expect_success 'confirm detects EOF (inform assumes y)' ' test_expect_success 'confirm detects EOF (auto causes failure)' ' CONFIRM=$(git config --get sendemail.confirm) && git config sendemail.confirm auto && - GIT_SEND_EMAIL_NOTTY=1 \ + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && test_must_fail git send-email \ --from="Example " \ --to=nobody@example.com \ @@ -492,8 +493,9 @@ test_expect_success 'confirm detects EOF (auto causes failure)' ' test_expect_success 'confirm doesnt loop forever' ' CONFIRM=$(git config --get sendemail.confirm) && git config sendemail.confirm auto && - yes "bogus" | GIT_SEND_EMAIL_NOTTY=1 \ - test_must_fail git send-email \ + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && + yes "bogus" | test_must_fail git send-email \ --from="Example " \ --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ From a61c0ffa4474ad6dcec18a5454630371106710f4 Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Tue, 31 Mar 2009 12:22:14 -0400 Subject: [PATCH 91/95] send-email: ensure quoted addresses are rfc2047 encoded sanitize_address assumes that quoted addresses (e.g., "first last" Signed-off-by: Junio C Hamano --- git-send-email.perl | 3 ++- t/t9001-send-email.sh | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/git-send-email.perl b/git-send-email.perl index fc153f9459..6bbdfec849 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -776,12 +776,13 @@ sub sanitize_address } # if recipient_name is already quoted, do nothing - if ($recipient_name =~ /^(".*"|=\?utf-8\?q\?.*\?=)$/) { + if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) { return $recipient; } # rfc2047 is needed if a non-ascii char is included if ($recipient_name =~ /[^[:ascii:]]/) { + $recipient_name =~ s/^"(.*)"$/$1/; $recipient_name = quote_rfc2047($recipient_name); } diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 84238f7197..192b97b2d6 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -505,6 +505,19 @@ test_expect_success 'confirm doesnt loop forever' ' test $ret = "0" ' +test_expect_success 'utf8 Cc is rfc2047 encoded' ' + clean_fake_sendmail && + rm -fr outdir && + git format-patch -1 -o outdir --cc="àéìöú " && + git send-email \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/*.patch && + grep "^Cc:" msgtxt1 | + grep "=?utf-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= " +' + test_expect_success '--compose adds MIME for utf8 body' ' clean_fake_sendmail && (echo "#!$SHELL_PATH" && From 3346330d708b9b786b16167cbbd4a3637b3a3517 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 2 Apr 2009 12:21:57 -0700 Subject: [PATCH 92/95] GIT 1.6.2.2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.2.2.txt | 15 +++++++++------ GIT-VERSION-GEN | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Documentation/RelNotes-1.6.2.2.txt b/Documentation/RelNotes-1.6.2.2.txt index 4f4c47341f..fafa9986b0 100644 --- a/Documentation/RelNotes-1.6.2.2.txt +++ b/Documentation/RelNotes-1.6.2.2.txt @@ -7,9 +7,15 @@ Fixes since v1.6.2.1 * A longstanding confusing description of what --pickaxe option of git-diff does has been clarified in the documentation. +* "git-blame -S" did not quite work near the commits that were given + on the command line correctly. + * "git diff --pickaxe-regexp" did not count overlapping matches correctly. +* "git diff" did not feed files in work-tree representation to external + diff and textconv. + * "git-fetch" in a repository that was not cloned from anywhere said it cannot find 'origin', which was hard to understand for new people. @@ -33,10 +39,7 @@ Fixes since v1.6.2.1 * import-zips script (in contrib) did not compute the common directory prefix correctly. -Many small documentation updates are included as well. +* miscompilation of negated enum constants by old gcc (2.9) affected the + codepaths to spawn subprocesses. ---- -exec >/var/tmp/1 -O=v1.6.2.1-46-gb19293d -echo O=$(git describe maint) -git shortlog --no-merges $O..maint +Many small documentation updates are included as well. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index e6097c23aa..ac2f24795c 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.6.2.1 +DEF_VER=v1.6.2.2 LF=' ' From e96f3689ecd95997a2a474c2b7f21b0a67f138b1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 2 Apr 2009 13:42:24 -0700 Subject: [PATCH 93/95] Update draft release notes to 1.6.3 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.3.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/RelNotes-1.6.3.txt b/Documentation/RelNotes-1.6.3.txt index bcbd7c5a21..db6956205d 100644 --- a/Documentation/RelNotes-1.6.3.txt +++ b/Documentation/RelNotes-1.6.3.txt @@ -62,6 +62,10 @@ Updates since v1.6.2 with the 'edit' action in git-add -i/-p, you can abort the editor to tell git not to apply it. +* The number of commits shown in "you are ahead/behind your upstream" + messages given by "git checkout" and "git status" used to count merge + commits; now it doesn't. + * git-archive learned --output= option. * git-bisect shows not just the number of remaining commits whose goodness @@ -77,11 +81,17 @@ Updates since v1.6.2 * git-clone runs post-checkout hook when run without --no-checkout. +* git-fast-export choked when seeing a tag that does not point at commit. + * git-format-patch can be told to use attachment with a new configuration, format.attach. * git-format-patch can be told to produce deep or shallow message threads. +* git-format-patch learned format.headers configuration to add extra + header fields to the output. This behaviour is similar to the existing + --add-header=
option of the command. + * git-grep learned to highlight the found substrings in color. * git-imap-send learned to work around Thunderbird's inability to easily @@ -95,6 +105,11 @@ Updates since v1.6.2 * Output from git-remote command has been vastly improved. +* git-repack (invoked from git-gc) did not work as nicely as it should in + a repository that borrows objects from neighbours via alternates + mechanism especially when some packs are marked with the ".keep" flag + to prevent them from being repacked. + * git-send-email learned --confirm option to review the Cc: list before sending the messages out. @@ -110,7 +125,9 @@ Updates since v1.6.2 * Building the manpages with docbook-xsl between 1.69.1 and 1.71.1 now requires setting DOCBOOK_SUPPRESS_SP to work around a docbook-xsl bug. This workaround used to be enabled by default, but causes problems - with newer versions of docbook-xsl. + with newer versions of docbook-xsl. In addition, there are a few more + knobs you can tweak to work around issues with various versions of the + docbook-xsl package. See comments in Documentation/Makefile for details. Fixes since v1.6.2 ------------------ @@ -129,6 +146,6 @@ v1.6.2.X series. --- exec >/var/tmp/1 -O=v1.6.2.1-399-gaa72a14 +O=v1.6.2.2-403-g8130949 echo O=$(git describe master) git shortlog --no-merges $O..master ^maint From 96beef8c2efaab06f703991ed7802b8cef4c00e3 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 4 Apr 2009 22:59:26 +0200 Subject: [PATCH 94/95] sha1-lookup: add new "sha1_pos" function to efficiently lookup sha1 This function has been copied from the "patch_pos" function in "patch-ids.c" but an additional parameter has been added. The new parameter is a function pointer, that is used to access the sha1 of an element in the table. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- sha1-lookup.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ sha1-lookup.h | 7 ++++ 2 files changed, 108 insertions(+) diff --git a/sha1-lookup.c b/sha1-lookup.c index da357479cf..055dd87dc1 100644 --- a/sha1-lookup.c +++ b/sha1-lookup.c @@ -1,6 +1,107 @@ #include "cache.h" #include "sha1-lookup.h" +static uint32_t take2(const unsigned char *sha1) +{ + return ((sha1[0] << 8) | sha1[1]); +} + +/* + * Conventional binary search loop looks like this: + * + * do { + * int mi = (lo + hi) / 2; + * int cmp = "entry pointed at by mi" minus "target"; + * if (!cmp) + * return (mi is the wanted one) + * if (cmp > 0) + * hi = mi; "mi is larger than target" + * else + * lo = mi+1; "mi is smaller than target" + * } while (lo < hi); + * + * The invariants are: + * + * - When entering the loop, lo points at a slot that is never + * above the target (it could be at the target), hi points at a + * slot that is guaranteed to be above the target (it can never + * be at the target). + * + * - We find a point 'mi' between lo and hi (mi could be the same + * as lo, but never can be the same as hi), and check if it hits + * the target. There are three cases: + * + * - if it is a hit, we are happy. + * + * - if it is strictly higher than the target, we update hi with + * it. + * + * - if it is strictly lower than the target, we update lo to be + * one slot after it, because we allow lo to be at the target. + * + * When choosing 'mi', we do not have to take the "middle" but + * anywhere in between lo and hi, as long as lo <= mi < hi is + * satisfied. When we somehow know that the distance between the + * target and lo is much shorter than the target and hi, we could + * pick mi that is much closer to lo than the midway. + */ +/* + * The table should contain "nr" elements. + * The sha1 of element i (between 0 and nr - 1) should be returned + * by "fn(i, table)". + */ +int sha1_pos(const unsigned char *sha1, void *table, size_t nr, + sha1_access_fn fn) +{ + size_t hi = nr; + size_t lo = 0; + size_t mi = 0; + + if (!nr) + return -1; + + if (nr != 1) { + size_t lov, hiv, miv, ofs; + + for (ofs = 0; ofs < 18; ofs += 2) { + lov = take2(fn(0, table) + ofs); + hiv = take2(fn(nr - 1, table) + ofs); + miv = take2(sha1 + ofs); + if (miv < lov) + return -1; + if (hiv < miv) + return -1 - nr; + if (lov != hiv) { + /* + * At this point miv could be equal + * to hiv (but sha1 could still be higher); + * the invariant of (mi < hi) should be + * kept. + */ + mi = (nr - 1) * (miv - lov) / (hiv - lov); + if (lo <= mi && mi < hi) + break; + die("oops"); + } + } + if (18 <= ofs) + die("cannot happen -- lo and hi are identical"); + } + + do { + int cmp; + cmp = hashcmp(fn(mi, table), sha1); + if (!cmp) + return mi; + if (cmp > 0) + hi = mi; + else + lo = mi + 1; + mi = (hi + lo) / 2; + } while (lo < hi); + return -lo-1; +} + /* * Conventional binary search loop looks like this: * diff --git a/sha1-lookup.h b/sha1-lookup.h index 3249a81b3d..20af285681 100644 --- a/sha1-lookup.h +++ b/sha1-lookup.h @@ -1,6 +1,13 @@ #ifndef SHA1_LOOKUP_H #define SHA1_LOOKUP_H +typedef const unsigned char *sha1_access_fn(size_t index, void *table); + +extern int sha1_pos(const unsigned char *sha1, + void *table, + size_t nr, + sha1_access_fn fn); + extern int sha1_entry_pos(const void *table, size_t elem_size, size_t key_offset, From 5289bae17f24805cc8507129e21d794b0b56264c Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 4 Apr 2009 22:59:31 +0200 Subject: [PATCH 95/95] patch-ids: use the new generic "sha1_pos" function to lookup sha1 instead of the specific one from which the new one has been copied. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- patch-ids.c | 93 +++-------------------------------------------------- 1 file changed, 5 insertions(+), 88 deletions(-) diff --git a/patch-ids.c b/patch-ids.c index 3be5d3165e..5717257051 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -1,6 +1,7 @@ #include "cache.h" #include "diff.h" #include "commit.h" +#include "sha1-lookup.h" #include "patch-ids.h" static int commit_patch_id(struct commit *commit, struct diff_options *options, @@ -15,99 +16,15 @@ static int commit_patch_id(struct commit *commit, struct diff_options *options, return diff_flush_patch_id(options, sha1); } -static uint32_t take2(const unsigned char *id) +static const unsigned char *patch_id_access(size_t index, void *table) { - return ((id[0] << 8) | id[1]); + struct patch_id **id_table = table; + return id_table[index]->patch_id; } -/* - * Conventional binary search loop looks like this: - * - * do { - * int mi = (lo + hi) / 2; - * int cmp = "entry pointed at by mi" minus "target"; - * if (!cmp) - * return (mi is the wanted one) - * if (cmp > 0) - * hi = mi; "mi is larger than target" - * else - * lo = mi+1; "mi is smaller than target" - * } while (lo < hi); - * - * The invariants are: - * - * - When entering the loop, lo points at a slot that is never - * above the target (it could be at the target), hi points at a - * slot that is guaranteed to be above the target (it can never - * be at the target). - * - * - We find a point 'mi' between lo and hi (mi could be the same - * as lo, but never can be the same as hi), and check if it hits - * the target. There are three cases: - * - * - if it is a hit, we are happy. - * - * - if it is strictly higher than the target, we update hi with - * it. - * - * - if it is strictly lower than the target, we update lo to be - * one slot after it, because we allow lo to be at the target. - * - * When choosing 'mi', we do not have to take the "middle" but - * anywhere in between lo and hi, as long as lo <= mi < hi is - * satisfied. When we somehow know that the distance between the - * target and lo is much shorter than the target and hi, we could - * pick mi that is much closer to lo than the midway. - */ static int patch_pos(struct patch_id **table, int nr, const unsigned char *id) { - int hi = nr; - int lo = 0; - int mi = 0; - - if (!nr) - return -1; - - if (nr != 1) { - unsigned lov, hiv, miv, ofs; - - for (ofs = 0; ofs < 18; ofs += 2) { - lov = take2(table[0]->patch_id + ofs); - hiv = take2(table[nr-1]->patch_id + ofs); - miv = take2(id + ofs); - if (miv < lov) - return -1; - if (hiv < miv) - return -1 - nr; - if (lov != hiv) { - /* - * At this point miv could be equal - * to hiv (but id could still be higher); - * the invariant of (mi < hi) should be - * kept. - */ - mi = (nr-1) * (miv - lov) / (hiv - lov); - if (lo <= mi && mi < hi) - break; - die("oops"); - } - } - if (18 <= ofs) - die("cannot happen -- lo and hi are identical"); - } - - do { - int cmp; - cmp = hashcmp(table[mi]->patch_id, id); - if (!cmp) - return mi; - if (cmp > 0) - hi = mi; - else - lo = mi + 1; - mi = (hi + lo) / 2; - } while (lo < hi); - return -lo-1; + return sha1_pos(id, table, nr, patch_id_access); } #define BUCKET_SIZE 190 /* 190 * 21 = 3990, with slop close enough to 4K */