New capability "report-status-v2" for git-push
The new introduced "proc-receive" hook may handle a command for a pseudo-reference with a zero-old as its old-oid, while the hook may create or update a reference with different name, different new-oid, and different old-oid (the reference may exist already with a non-zero old-oid). Current "report-status" protocol cannot report the status for such reference rewrite. Add new capability "report-status-v2" and new report protocol which is not backward compatible for report of git-push. If a user pushes to a pseudo-reference "refs/for/master/topic", and "receive-pack" creates two new references "refs/changes/23/123/1" and "refs/changes/24/124/1", for client without the knowledge of "report-status-v2", "receive-pack" will only send "ok/ng" directives in the report, such as: ok ref/for/master/topic But for client which has the knowledge of "report-status-v2", "receive-pack" will use "option" directives to report more attributes for the reference given by the above "ok/ng" directive. ok refs/for/master/topic option refname refs/changes/23/123/1 option new-oid <new-oid> ok refs/for/master/topic option refname refs/changes/24/124/1 option new-oid <new-oid> The client will report two new created references to the end user. Suggested-by: Junio C Hamano <gitster@pobox.com> Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
195d6eaea3
commit
63518a574a
101
send-pack.c
101
send-pack.c
@ -153,25 +153,79 @@ static int receive_status(struct packet_reader *reader, struct ref *refs)
|
||||
{
|
||||
struct ref *hint;
|
||||
int ret;
|
||||
struct ref_push_report *report = NULL;
|
||||
int new_report = 0;
|
||||
int once = 0;
|
||||
|
||||
hint = NULL;
|
||||
ret = receive_unpack_status(reader);
|
||||
while (1) {
|
||||
struct object_id old_oid, new_oid;
|
||||
const char *head;
|
||||
const char *refname;
|
||||
char *msg;
|
||||
char *p;
|
||||
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
|
||||
break;
|
||||
if (!starts_with(reader->line, "ok ") && !starts_with(reader->line, "ng ")) {
|
||||
error("invalid ref status from remote: %s", reader->line);
|
||||
head = reader->line;
|
||||
p = strchr(head, ' ');
|
||||
if (!p) {
|
||||
error("invalid status line from remote: %s", reader->line);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
refname = reader->line + 3;
|
||||
msg = strchr(refname, ' ');
|
||||
if (msg)
|
||||
*msg++ = '\0';
|
||||
if (!strcmp(head, "option")) {
|
||||
const char *key, *val;
|
||||
|
||||
if (!hint || !(report || new_report)) {
|
||||
if (!once++)
|
||||
error("'option' without a matching 'ok/ng' directive");
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
if (new_report) {
|
||||
if (!hint->report) {
|
||||
hint->report = xcalloc(1, sizeof(struct ref_push_report));
|
||||
report = hint->report;
|
||||
} else {
|
||||
report = hint->report;
|
||||
while (report->next)
|
||||
report = report->next;
|
||||
report->next = xcalloc(1, sizeof(struct ref_push_report));
|
||||
report = report->next;
|
||||
}
|
||||
new_report = 0;
|
||||
}
|
||||
key = p;
|
||||
p = strchr(key, ' ');
|
||||
if (p)
|
||||
*p++ = '\0';
|
||||
val = p;
|
||||
if (!strcmp(key, "refname"))
|
||||
report->ref_name = xstrdup_or_null(val);
|
||||
else if (!strcmp(key, "old-oid") && val &&
|
||||
!parse_oid_hex(val, &old_oid, &val))
|
||||
report->old_oid = oiddup(&old_oid);
|
||||
else if (!strcmp(key, "new-oid") && val &&
|
||||
!parse_oid_hex(val, &new_oid, &val))
|
||||
report->new_oid = oiddup(&new_oid);
|
||||
else if (!strcmp(key, "forced-update"))
|
||||
report->forced_update = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
report = NULL;
|
||||
new_report = 0;
|
||||
if (strcmp(head, "ok") && strcmp(head, "ng")) {
|
||||
error("invalid ref status from remote: %s", head);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
refname = p;
|
||||
p = strchr(refname, ' ');
|
||||
if (p)
|
||||
*p++ = '\0';
|
||||
/* first try searching at our hint, falling back to all refs */
|
||||
if (hint)
|
||||
hint = find_ref_by_name(hint, refname);
|
||||
@ -179,22 +233,27 @@ static int receive_status(struct packet_reader *reader, struct ref *refs)
|
||||
hint = find_ref_by_name(refs, refname);
|
||||
if (!hint) {
|
||||
warning("remote reported status on unknown ref: %s",
|
||||
refname);
|
||||
refname);
|
||||
continue;
|
||||
}
|
||||
if (hint->status != REF_STATUS_EXPECTING_REPORT) {
|
||||
if (hint->status != REF_STATUS_EXPECTING_REPORT &&
|
||||
hint->status != REF_STATUS_OK &&
|
||||
hint->status != REF_STATUS_REMOTE_REJECT) {
|
||||
warning("remote reported status on unexpected ref: %s",
|
||||
refname);
|
||||
refname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reader->line[0] == 'o' && reader->line[1] == 'k')
|
||||
hint->status = REF_STATUS_OK;
|
||||
else
|
||||
if (!strcmp(head, "ng")) {
|
||||
hint->status = REF_STATUS_REMOTE_REJECT;
|
||||
hint->remote_status = xstrdup_or_null(msg);
|
||||
/* start our next search from the next ref */
|
||||
hint = hint->next;
|
||||
if (p)
|
||||
hint->remote_status = xstrdup(p);
|
||||
else
|
||||
hint->remote_status = "failed";
|
||||
} else {
|
||||
hint->status = REF_STATUS_OK;
|
||||
hint->remote_status = xstrdup_or_null(p);
|
||||
new_report = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -369,7 +428,9 @@ int send_pack(struct send_pack_args *args,
|
||||
struct packet_reader reader;
|
||||
|
||||
/* Does the other end support the reporting? */
|
||||
if (server_supports("report-status"))
|
||||
if (server_supports("report-status-v2"))
|
||||
status_report = 2;
|
||||
else if (server_supports("report-status"))
|
||||
status_report = 1;
|
||||
if (server_supports("delete-refs"))
|
||||
allow_deleting_refs = 1;
|
||||
@ -418,8 +479,10 @@ int send_pack(struct send_pack_args *args,
|
||||
|
||||
use_push_options = push_options_supported && args->push_options;
|
||||
|
||||
if (status_report)
|
||||
if (status_report == 1)
|
||||
strbuf_addstr(&cap_buf, " report-status");
|
||||
else if (status_report == 2)
|
||||
strbuf_addstr(&cap_buf, " report-status-v2");
|
||||
if (use_sideband)
|
||||
strbuf_addstr(&cap_buf, " side-band-64k");
|
||||
if (quiet_supported && (args->quiet || !args->progress))
|
||||
|
Reference in New Issue
Block a user