From f76734902bba47afff622068524a0c38f642d769 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:11:15 -0500 Subject: [PATCH 1/4] more terse push output This changes the output of send-pack to match the new, more terse fetch output. It looks like this: To git://host.tld/path/to/repo + f3325dc...3b91d1c hasforce -> mirror/hasforce (forced update) f3325dc..bb022dc master -> mirror/master ! [rejected] needsforce -> mirror/needsforce (non-fast forward) * [new branch] newbranch -> mirror/newbranch * [new tag] v1.0 -> v1.0 instead of: updating 'refs/heads/mirror/hasforce' using 'refs/heads/hasforce' from f3325dca9c4a34d74012c0e159254f454930cec7 to 3b91d1c310ca9d7b547b85466dd876e143498304 updating 'refs/heads/mirror/master' using 'refs/heads/master' from f3325dca9c4a34d74012c0e159254f454930cec7 to bb022dc363d5c2aa9aa3026beb9706d44fbe1328 error: remote 'refs/heads/mirror/needsforce' is not an ancestor of local 'refs/heads/needsforce'. Maybe you are not up-to-date and need to pull first? updating 'refs/heads/mirror/newbranch' using 'refs/heads/newbranch' from 0000000000000000000000000000000000000000 to 3b91d1c310ca9d7b547b85466dd876e143498304 updating 'refs/tags/v1.0' from 0000000000000000000000000000000000000000 to bb022dc363d5c2aa9aa3026beb9706d44fbe1328 Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 81 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index aedef09ef0..d74cc3c4a6 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -206,7 +206,18 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) } } -static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec) +static const char *prettify_ref(const char *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 int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec) { struct ref *ref; int new_refs; @@ -214,6 +225,7 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, int ask_for_status_report = 0; int allow_deleting_refs = 0; int expect_status_report = 0; + int shown_dest = 0; /* No funny business with the matcher */ remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL); @@ -245,21 +257,33 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, for (ref = remote_refs; ref; ref = ref->next) { char old_hex[60], *new_hex; int will_delete_ref; + const char *pretty_ref; + const char *pretty_peer; if (!ref->peer_ref) continue; + if (!shown_dest) { + fprintf(stderr, "To %s\n", dest); + shown_dest = 1; + } + + pretty_ref = prettify_ref(ref->name); + pretty_peer = prettify_ref(ref->peer_ref->name); will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1); if (will_delete_ref && !allow_deleting_refs) { - error("remote does not support deleting refs"); + fprintf(stderr, " ! %-*s %s (remote does not support deleting refs)\n", + SUMMARY_WIDTH, "[rejected]", pretty_ref); ret = -2; continue; } if (!will_delete_ref && !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) { if (args.verbose) - fprintf(stderr, "'%s': up-to-date\n", ref->name); + fprintf(stderr, " = %-*s %s -> %s\n", + SUMMARY_WIDTH, "[up to date]", + pretty_peer, pretty_ref); continue; } @@ -296,12 +320,9 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, * commits at the remote end and likely * we were not up to date to begin with. */ - error("remote '%s' is not a strict " - "subset of local ref '%s'. " - "maybe you are not up-to-date and " - "need to pull first?", - ref->name, - ref->peer_ref->name); + fprintf(stderr, " ! %-*s %s -> %s (non-fast forward)\n", + SUMMARY_WIDTH, "[rejected]", + pretty_peer, pretty_ref); ret = -2; continue; } @@ -325,14 +346,40 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, old_hex, new_hex, ref->name); } if (will_delete_ref) - fprintf(stderr, "deleting '%s'\n", ref->name); + fprintf(stderr, " - %-*s %s\n", + SUMMARY_WIDTH, "[deleting]", + pretty_ref); + else if (is_null_sha1(ref->old_sha1)) { + const char *msg; + + if (!prefixcmp(ref->name, "refs/tags/")) + msg = "[new tag]"; + else + msg = "[new branch]"; + fprintf(stderr, " * %-*s %s -> %s\n", + SUMMARY_WIDTH, msg, + pretty_peer, pretty_ref); + } else { - fprintf(stderr, "updating '%s'", ref->name); - if (strcmp(ref->name, ref->peer_ref->name)) - fprintf(stderr, " using '%s'", - ref->peer_ref->name); - fprintf(stderr, "\n from %s\n to %s\n", - old_hex, new_hex); + char quickref[83]; + char type = ' '; + const char *msg = ""; + + strcpy(quickref, find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV)); + if (ref_newer(ref->peer_ref->new_sha1, ref->old_sha1)) + strcat(quickref, ".."); + else { + strcat(quickref, "..."); + type = '+'; + msg = " (forced update)"; + } + strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + + fprintf(stderr, " %c %-*s %s -> %s%s\n", + type, + SUMMARY_WIDTH, quickref, + pretty_peer, pretty_ref, + msg); } } @@ -460,7 +507,7 @@ int send_pack(struct send_pack_args *my_args, verify_remote_names(nr_heads, heads); conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); - ret = do_send_pack(fd[0], fd[1], remote, nr_heads, heads); + ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads); close(fd[0]); close(fd[1]); ret |= finish_connect(conn); From 3b70da2b17dc5b7df644701a96a141d8f7c5ea15 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:11:41 -0500 Subject: [PATCH 2/4] receive-pack: don't mention successful updates The proposed updates are already shown to the user by send-pack, so there's no point. We continue to show errors, since they are unexpected. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- receive-pack.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/receive-pack.c b/receive-pack.c index 38e35c06b9..ed44b897f6 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -204,8 +204,6 @@ static const char *update(struct command *cmd) error("failed to delete %s", name); return "failed to delete"; } - fprintf(stderr, "%s: %s -> deleted\n", name, - sha1_to_hex(old_sha1)); return NULL; /* good */ } else { @@ -217,8 +215,6 @@ static const char *update(struct command *cmd) if (write_ref_sha1(lock, new_sha1, "push")) { return "failed to write"; /* error() already called */ } - fprintf(stderr, "%s: %s -> %s\n", name, - sha1_to_hex(old_sha1), sha1_to_hex(new_sha1)); return NULL; /* good */ } } From b50fa2bd061c3bb21f2918849ece43ac9ca2c504 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:12:18 -0500 Subject: [PATCH 3/4] send-pack: require --verbose to show update of tracking refs This is really an uninteresting detail, and it just takes attention away from the actual push updates and posssible errors. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index d74cc3c4a6..c1fd3f5fbb 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -195,7 +195,8 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) return; if (!remote_find_tracking(remote, &rs)) { - fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); + if (args.verbose) + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); if (is_null_sha1(ref->peer_ref->new_sha1)) { if (delete_ref(rs.dst, NULL)) error("Failed to delete"); From 6738c8194286fa0017f72cb57628dcae9ec07b27 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Nov 2007 01:38:12 -0800 Subject: [PATCH 4/4] send-pack: segfault fix on forced push When pushing to overwrite a ref that points at a commit we do not even have, the recent "terse push" patch tried to get a unique abbreviation for the non-existent (from our point of view) object, which resulted in strcpy(buf, NULL) and segfaulted. Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 5 +++-- t/t5405-send-pack-rewind.sh | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100755 t/t5405-send-pack-rewind.sh diff --git a/builtin-send-pack.c b/builtin-send-pack.c index c1fd3f5fbb..5a0f5c681c 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -365,8 +365,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest char quickref[83]; char type = ' '; const char *msg = ""; - - strcpy(quickref, find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV)); + const char *old_abb; + old_abb = find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV); + strcpy(quickref, old_abb ? old_abb : old_hex); if (ref_newer(ref->peer_ref->new_sha1, ref->old_sha1)) strcat(quickref, ".."); else { diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh new file mode 100755 index 0000000000..86abc62271 --- /dev/null +++ b/t/t5405-send-pack-rewind.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='forced push to replace commit we do not have' + +. ./test-lib.sh + +test_expect_success setup ' + + >file1 && git add file1 && test_tick && + git commit -m Initial && + + mkdir another && ( + cd another && + git init && + git fetch .. master:master + ) && + + >file2 && git add file2 && test_tick && + git commit -m Second + +' + +test_expect_success 'non forced push should die not segfault' ' + + ( + cd another && + git push .. master:master + test $? = 1 + ) + +' + +test_expect_success 'forced push should succeed' ' + + ( + cd another && + git push .. +master:master + ) + +' + +test_done