@ -146,60 +146,67 @@ static void get_local_heads(void)
for_each_ref(one_local_ref, NULL);
for_each_ref(one_local_ref, NULL);
}
}
static struct ref *set_ref_error(struct ref *refs, const char *line)
{
struct ref *ref;
for (ref = refs; ref; ref = ref->next) {
const char *msg;
if (prefixcmp(line, ref->name))
continue;
msg = line + strlen(ref->name);
if (*msg++ != ' ')
continue;
ref->status = REF_STATUS_REMOTE_REJECT;
ref->error = xstrdup(msg);
ref->error[strlen(ref->error)-1] = '\0';
return ref;
}
return NULL;
}
/* a return value of -1 indicates that an error occurred,
* but we were able to set individual ref errors. A return
* value of -2 means we couldn't even get that far. */
static int receive_status(int in, struct ref *refs)
static int receive_status(int in, struct ref *refs)
{
{
struct ref *hint;
struct ref *hint;
char line[1000];
char line[1000];
int ret = 0;
int ret = 0;
int len = packet_read_line(in, line, sizeof(line));
int len = packet_read_line(in, line, sizeof(line));
if (len < 10 || memcmp(line, "unpack ", 7)) {
if (len < 10 || memcmp(line, "unpack ", 7))
fprintf(stderr, "did not receive status back\n");
return error("did not receive remote status");
return -2;
}
if (memcmp(line, "unpack ok\n", 10)) {
if (memcmp(line, "unpack ok\n", 10)) {
fputs(line, stderr);
char *p = line + strlen(line) - 1;
if (*p == '\n')
*p = '\0';
error("unpack failed: %s", line + 7);
ret = -1;
ret = -1;
}
}
hint = NULL;
hint = NULL;
while (1) {
while (1) {
char *refname;
char *msg;
len = packet_read_line(in, line, sizeof(line));
len = packet_read_line(in, line, sizeof(line));
if (!len)
if (!len)
break;
break;
if (len < 3 ||
if (len < 3 ||
(memcmp(line, "ok", 2) && memcmp(line, "ng", 2))) {
(memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3))) {
fprintf(stderr, "protocol error: %s\n", line);
fprintf(stderr, "protocol error: %s\n", line);
ret = -1;
ret = -1;
break;
break;
}
}
if (!memcmp(line, "ok", 2))
continue;
line[strlen(line)-1] = '\0';
refname = line + 3;
msg = strchr(refname, ' ');
if (msg)
*msg++ = '\0';
/* first try searching at our hint, falling back to all refs */
if (hint)
if (hint)
hint = set_ref_error(hint, line + 3);
hint = find_ref_by_name(hint, refname);
if (!hint)
if (!hint)
hint = set_ref_error(refs, line + 3);
hint = find_ref_by_name(refs, refname);
ret = -1;
if (!hint) {
warning("remote reported status on unknown ref: %s",
refname);
continue;
}
if (hint->status != REF_STATUS_EXPECTING_REPORT) {
warning("remote reported status on unexpected ref: %s",
refname);
continue;
}
if (line[0] == 'o' && line[1] == 'k')
hint->status = REF_STATUS_OK;
else {
hint->status = REF_STATUS_REMOTE_REJECT;
ret = -1;
}
if (msg)
hint->remote_status = xstrdup(msg);
/* start our next search from the next ref */
hint = hint->next;
}
}
return ret;
return ret;
}
}
@ -324,10 +331,14 @@ static void print_push_status(const char *dest, struct ref *refs)
"non-fast forward");
"non-fast forward");
break;
break;
case REF_STATUS_REMOTE_REJECT:
case REF_STATUS_REMOTE_REJECT:
if (ref->deletion)
print_ref_status('!', "[remote rejected]", ref,
print_ref_status('!', "[remote rejected]", ref, NULL, ref->error);
ref->deletion ? NULL : ref->peer_ref,
else
ref->remote_status);
print_ref_status('!', "[remote rejected]", ref, ref->peer_ref, ref->error);
break;
case REF_STATUS_EXPECTING_REPORT:
print_ref_status('!', "[remote failure]", ref,
ref->deletion ? NULL : ref->peer_ref,
"remote failed to report status");
break;
break;
case REF_STATUS_OK:
case REF_STATUS_OK:
print_ok_ref_status(ref);
print_ok_ref_status(ref);
@ -434,7 +445,6 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
hashcpy(ref->new_sha1, new_sha1);
hashcpy(ref->new_sha1, new_sha1);
if (!ref->deletion)
if (!ref->deletion)
new_refs++;
new_refs++;
ref->status = REF_STATUS_OK;
if (!args.dry_run) {
if (!args.dry_run) {
char *old_hex = sha1_to_hex(ref->old_sha1);
char *old_hex = sha1_to_hex(ref->old_sha1);
@ -451,6 +461,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
packet_write(out, "%s %s %s",
packet_write(out, "%s %s %s",
old_hex, new_hex, ref->name);
old_hex, new_hex, ref->name);
}
}
ref->status = expect_status_report ?
REF_STATUS_EXPECTING_REPORT :
REF_STATUS_OK;
}
}
packet_flush(out);
packet_flush(out);
@ -462,11 +475,8 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
}
}
close(out);
close(out);
if (expect_status_report) {
if (expect_status_report)
ret = receive_status(in, remote_refs);
ret = receive_status(in, remote_refs);
if (ret == -2)
return -1;
}
else
else
ret = 0;
ret = 0;