Merge branch 'jk/terse-push' into aw/mirror-push

* jk/terse-push:
  send-pack: segfault fix on forced push
  send-pack: require --verbose to show update of tracking refs
  receive-pack: don't mention successful updates
  more terse push output
maint
Junio C Hamano 2007-11-09 01:10:10 -08:00
commit 1496553072
3 changed files with 109 additions and 22 deletions

View File

@ -195,6 +195,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
return; return;


if (!remote_find_tracking(remote, &rs)) { if (!remote_find_tracking(remote, &rs)) {
if (args.verbose)
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
if (is_null_sha1(ref->peer_ref->new_sha1)) { if (is_null_sha1(ref->peer_ref->new_sha1)) {
if (delete_ref(rs.dst, NULL)) if (delete_ref(rs.dst, NULL))
@ -206,7 +207,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; struct ref *ref;
int new_refs; int new_refs;
@ -214,6 +226,7 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec,
int ask_for_status_report = 0; int ask_for_status_report = 0;
int allow_deleting_refs = 0; int allow_deleting_refs = 0;
int expect_status_report = 0; int expect_status_report = 0;
int shown_dest = 0;


/* No funny business with the matcher */ /* No funny business with the matcher */
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL); remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);
@ -245,21 +258,33 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec,
for (ref = remote_refs; ref; ref = ref->next) { for (ref = remote_refs; ref; ref = ref->next) {
char old_hex[60], *new_hex; char old_hex[60], *new_hex;
int will_delete_ref; int will_delete_ref;
const char *pretty_ref;
const char *pretty_peer;


if (!ref->peer_ref) if (!ref->peer_ref)
continue; 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); will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);
if (will_delete_ref && !allow_deleting_refs) { 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; ret = -2;
continue; continue;
} }
if (!will_delete_ref && if (!will_delete_ref &&
!hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) { !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
if (args.verbose) 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; continue;
} }


@ -296,12 +321,9 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec,
* commits at the remote end and likely * commits at the remote end and likely
* we were not up to date to begin with. * we were not up to date to begin with.
*/ */
error("remote '%s' is not a strict " fprintf(stderr, " ! %-*s %s -> %s (non-fast forward)\n",
"subset of local ref '%s'. " SUMMARY_WIDTH, "[rejected]",
"maybe you are not up-to-date and " pretty_peer, pretty_ref);
"need to pull first?",
ref->name,
ref->peer_ref->name);
ret = -2; ret = -2;
continue; continue;
} }
@ -325,14 +347,41 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec,
old_hex, new_hex, ref->name); old_hex, new_hex, ref->name);
} }
if (will_delete_ref) 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 { else {
fprintf(stderr, "updating '%s'", ref->name); char quickref[83];
if (strcmp(ref->name, ref->peer_ref->name)) char type = ' ';
fprintf(stderr, " using '%s'", const char *msg = "";
ref->peer_ref->name); const char *old_abb;
fprintf(stderr, "\n from %s\n to %s\n", old_abb = find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV);
old_hex, new_hex); strcpy(quickref, old_abb ? old_abb : old_hex);
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 +509,7 @@ int send_pack(struct send_pack_args *my_args,
verify_remote_names(nr_heads, heads); verify_remote_names(nr_heads, heads);


conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); 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[0]);
close(fd[1]); close(fd[1]);
ret |= finish_connect(conn); ret |= finish_connect(conn);

View File

@ -204,8 +204,6 @@ static const char *update(struct command *cmd)
error("failed to delete %s", name); error("failed to delete %s", name);
return "failed to delete"; return "failed to delete";
} }
fprintf(stderr, "%s: %s -> deleted\n", name,
sha1_to_hex(old_sha1));
return NULL; /* good */ return NULL; /* good */
} }
else { else {
@ -217,8 +215,6 @@ static const char *update(struct command *cmd)
if (write_ref_sha1(lock, new_sha1, "push")) { if (write_ref_sha1(lock, new_sha1, "push")) {
return "failed to write"; /* error() already called */ 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 */ return NULL; /* good */
} }
} }

42
t/t5405-send-pack-rewind.sh Executable file
View File

@ -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