Skip to content

Commit aa05409

Browse files
jiangxingitster
authored andcommitted
send-pack: extension for client-side status report
This is the client-side extension for status report of git-push. The "proc-receive" hook may receive a command for a pseudo-reference with a zero-old as its old-oid, while the result of the hook may point to an alternate reference and the reference may exist already with a non-zero old-oid. Git client may receive a report with extened status as the following example: ok refs/for/master/topic\0ref=refs/pull/123/head old-oid=... Parse the key-value pairs in the extended status after the null character of the report, and show the proper reference name, old-oid and new-oid to the user. Suggested-by: Junio C Hamano <[email protected]> Signed-off-by: Jiang Xin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 81a1ff5 commit aa05409

File tree

6 files changed

+112
-41
lines changed

6 files changed

+112
-41
lines changed

remote.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cache.h"
22
#include "config.h"
3+
#include "connect.h"
34
#include "remote.h"
45
#include "refs.h"
56
#include "refspec.h"
@@ -2311,3 +2312,30 @@ void apply_push_cas(struct push_cas_option *cas,
23112312
for (ref = remote_refs; ref; ref = ref->next)
23122313
apply_cas(cas, remote, ref);
23132314
}
2315+
2316+
void update_ref_from_remote_status(struct ref *ref)
2317+
{
2318+
char *val;
2319+
char c;
2320+
int len;
2321+
2322+
if (!ref->remote_status)
2323+
return;
2324+
2325+
val = (char *)parse_feature_value(ref->remote_status, "old-oid", &len);
2326+
if (val && len) {
2327+
c = *(val+len);
2328+
*(val+len) = '\0';
2329+
get_oid_hex(val, &ref->old_oid);
2330+
*(val+len) = c;
2331+
}
2332+
val = (char *)parse_feature_value(ref->remote_status, "new-oid", &len);
2333+
if (val && len) {
2334+
c = *(val+len);
2335+
*(val+len) = '\0';
2336+
get_oid_hex(val, &ref->new_oid);
2337+
*(val+len) = c;
2338+
}
2339+
if (parse_feature_request(ref->remote_status, "forced-update"))
2340+
ref->forced_update = 1;
2341+
}

remote.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,7 @@ int parseopt_push_cas_option(const struct option *, const char *arg, int unset);
345345
int is_empty_cas(const struct push_cas_option *);
346346
void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
347347

348+
/* Parse key-value pairs of remote_status and update the reference accordingly */
349+
void update_ref_from_remote_status(struct ref *ref);
350+
348351
#endif

send-pack.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ static int receive_status(struct packet_reader *reader, struct ref *refs)
159159
while (1) {
160160
const char *refname;
161161
char *msg;
162+
char *extended_status = NULL;
163+
int len;
164+
162165
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
163166
break;
164167
if (!starts_with(reader->line, "ok ") && !starts_with(reader->line, "ng ")) {
@@ -167,10 +170,13 @@ static int receive_status(struct packet_reader *reader, struct ref *refs)
167170
break;
168171
}
169172

173+
len = strlen(reader->line);
170174
refname = reader->line + 3;
171175
msg = strchr(refname, ' ');
172176
if (msg)
173177
*msg++ = '\0';
178+
if (reader->pktlen > len)
179+
extended_status = (char *)reader->line + len + 1;
174180

175181
/* first try searching at our hint, falling back to all refs */
176182
if (hint)
@@ -194,7 +200,12 @@ static int receive_status(struct packet_reader *reader, struct ref *refs)
194200
hint->status = REF_STATUS_REMOTE_REJECT;
195201
ret = -1;
196202
}
197-
hint->remote_status = xstrdup_or_null(msg);
203+
if (msg) {
204+
hint->remote_status = xstrdup(msg);
205+
} else if (extended_status) {
206+
hint->remote_status = xstrdup(extended_status);
207+
update_ref_from_remote_status(hint);
208+
}
198209
/* start our next search from the next ref */
199210
hint = hint->next;
200211
}

t/t5411/common-test-cases.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,9 @@ test_expect_success "report update of all special refs" '
673673
remote: post-receive< <ZERO-OID> <COMMIT-A> refs/review/a/b/c/topic
674674
remote: post-receive< <COMMIT-B> <COMMIT-A> refs/for/master/topic
675675
To <URL/of/upstream.git>
676-
* [new reference] HEAD -> refs/for/next/topic
676+
* [new reference] HEAD -> refs/pull/123/head
677677
* [new reference] HEAD -> refs/review/a/b/c/topic
678-
* [new reference] HEAD -> refs/for/master/topic
678+
+ <OID-B>...<OID-A> HEAD -> refs/pull/124/head (forced update)
679679
EOF
680680
test_cmp expect actual &&
681681
git -C "$upstream" show-ref >out &&
@@ -738,7 +738,7 @@ test_expect_success "report mixed refs update" '
738738
* [new branch] HEAD -> baz
739739
* [new reference] HEAD -> refs/for/next/topic
740740
* [new branch] HEAD -> foo
741-
* [new reference] HEAD -> refs/for/master/topic
741+
<OID-A>..<OID-B> HEAD -> refs/for/master/topic
742742
EOF
743743
test_cmp expect actual &&
744744
git -C "$upstream" show-ref >out &&
@@ -812,8 +812,8 @@ test_expect_success "report test: fallthrough" '
812812
<OID-A>..<OID-B> <COMMIT-B> -> bar
813813
- [deleted] foo
814814
+ <OID-B>...<OID-A> HEAD -> master (forced update)
815-
* [new reference] HEAD -> refs/for/master/topic
816-
* [new reference] HEAD -> refs/for/next/topic
815+
<OID-A>..<OID-B> HEAD -> refs/pull/123/head
816+
+ <OID-B>...<OID-A> HEAD -> refs/pull/124/head (forced update)
817817
EOF
818818
test_cmp expect actual &&
819819
git -C "$upstream" show-ref >out &&

transport-helper.c

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -747,37 +747,39 @@ static int push_update_ref_status(struct strbuf *buf,
747747
msg = xstrdup(msg);
748748
strbuf_release(&msg_buf);
749749

750-
if (!strcmp(msg, "no match")) {
751-
status = REF_STATUS_NONE;
752-
FREE_AND_NULL(msg);
753-
}
754-
else if (!strcmp(msg, "up to date")) {
755-
status = REF_STATUS_UPTODATE;
756-
FREE_AND_NULL(msg);
757-
}
758-
else if (!strcmp(msg, "non-fast forward")) {
759-
status = REF_STATUS_REJECT_NONFASTFORWARD;
760-
FREE_AND_NULL(msg);
761-
}
762-
else if (!strcmp(msg, "already exists")) {
763-
status = REF_STATUS_REJECT_ALREADY_EXISTS;
764-
FREE_AND_NULL(msg);
765-
}
766-
else if (!strcmp(msg, "fetch first")) {
767-
status = REF_STATUS_REJECT_FETCH_FIRST;
768-
FREE_AND_NULL(msg);
769-
}
770-
else if (!strcmp(msg, "needs force")) {
771-
status = REF_STATUS_REJECT_NEEDS_FORCE;
772-
FREE_AND_NULL(msg);
773-
}
774-
else if (!strcmp(msg, "stale info")) {
775-
status = REF_STATUS_REJECT_STALE;
776-
FREE_AND_NULL(msg);
777-
}
778-
else if (!strcmp(msg, "forced update")) {
779-
forced = 1;
780-
FREE_AND_NULL(msg);
750+
if (status != REF_STATUS_OK) {
751+
if (!strcmp(msg, "no match")) {
752+
status = REF_STATUS_NONE;
753+
FREE_AND_NULL(msg);
754+
}
755+
else if (!strcmp(msg, "up to date")) {
756+
status = REF_STATUS_UPTODATE;
757+
FREE_AND_NULL(msg);
758+
}
759+
else if (!strcmp(msg, "non-fast forward")) {
760+
status = REF_STATUS_REJECT_NONFASTFORWARD;
761+
FREE_AND_NULL(msg);
762+
}
763+
else if (!strcmp(msg, "already exists")) {
764+
status = REF_STATUS_REJECT_ALREADY_EXISTS;
765+
FREE_AND_NULL(msg);
766+
}
767+
else if (!strcmp(msg, "fetch first")) {
768+
status = REF_STATUS_REJECT_FETCH_FIRST;
769+
FREE_AND_NULL(msg);
770+
}
771+
else if (!strcmp(msg, "needs force")) {
772+
status = REF_STATUS_REJECT_NEEDS_FORCE;
773+
FREE_AND_NULL(msg);
774+
}
775+
else if (!strcmp(msg, "stale info")) {
776+
status = REF_STATUS_REJECT_STALE;
777+
FREE_AND_NULL(msg);
778+
}
779+
else if (!strcmp(msg, "forced update")) {
780+
forced = 1;
781+
FREE_AND_NULL(msg);
782+
}
781783
}
782784
}
783785

@@ -802,6 +804,8 @@ static int push_update_ref_status(struct strbuf *buf,
802804
(*ref)->status = status;
803805
(*ref)->forced_update |= forced;
804806
(*ref)->remote_status = msg;
807+
if (status == REF_STATUS_OK && (*ref)->remote_status)
808+
update_ref_from_remote_status(*ref);
805809
return !(status == REF_STATUS_OK);
806810
}
807811

transport.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,30 @@ static void print_ref_status(char flag, const char *summary,
463463
struct ref *to, struct ref *from, const char *msg,
464464
int porcelain, int summary_width)
465465
{
466+
char *from_name = NULL;
467+
char *to_name = NULL;
468+
const char *val;
469+
int len;
470+
471+
if (from && from->remote_status) {
472+
val = parse_feature_value(from->remote_status, "ref", &len);
473+
if (val && len)
474+
from_name = xmemdupz(val, len);
475+
}
476+
if (to && to->remote_status) {
477+
val = parse_feature_value(to->remote_status, "ref", &len);
478+
if (val && len)
479+
to_name = xmemdupz(val, len);
480+
}
481+
466482
if (porcelain) {
467483
if (from)
468-
fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
484+
fprintf(stdout, "%c\t%s:%s\t", flag,
485+
from_name ? from_name : from->name,
486+
to_name ? to_name: to->name);
469487
else
470-
fprintf(stdout, "%c\t:%s\t", flag, to->name);
488+
fprintf(stdout, "%c\t:%s\t", flag,
489+
to_name ? to_name: to->name);
471490
if (msg)
472491
fprintf(stdout, "%s (%s)\n", summary, msg);
473492
else
@@ -481,16 +500,22 @@ static void print_ref_status(char flag, const char *summary,
481500
fprintf(stderr, " %s%c %-*s%s ", red, flag, summary_width,
482501
summary, reset);
483502
if (from)
484-
fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
503+
fprintf(stderr, "%s -> %s",
504+
prettify_refname(from_name ? from_name : from->name),
505+
prettify_refname(to_name ? to_name : to->name));
485506
else
486-
fputs(prettify_refname(to->name), stderr);
507+
fputs(prettify_refname(to_name ? to_name : to->name), stderr);
487508
if (msg) {
488509
fputs(" (", stderr);
489510
fputs(msg, stderr);
490511
fputc(')', stderr);
491512
}
492513
fputc('\n', stderr);
493514
}
515+
if (from_name)
516+
free(from_name);
517+
if (to_name)
518+
free(to_name);
494519
}
495520

496521
static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_width)

0 commit comments

Comments
 (0)