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 outputmaint
commit
1496553072
|
@ -195,7 +195,8 @@ 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)) {
|
||||||
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 (is_null_sha1(ref->peer_ref->new_sha1)) {
|
||||||
if (delete_ref(rs.dst, NULL))
|
if (delete_ref(rs.dst, NULL))
|
||||||
error("Failed to delete");
|
error("Failed to delete");
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue