transport: parse report options for tracking refs
When pushing a pseudo reference (such as "refs/for/master/topic"), may create or update one or more references. The real names of the references will be stored in the report options. Parse report options to create or update remote-tracking branches properly. Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jiang Xin committed
Aug 27, 2020 at 11:45 UTC
1702ae6f61412fa7d858701a7724a5cbf4aeea3e
2 files changed
+45
-14
t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh
+16
-6
@@ -78,10 +78,14 @@ test_expect_success "proc-receive: check remote-tracking #1 ($PROTOCOL)" '
78
grep -v -e refs/remotes -e refs/heads -e refs/tags >out &&
79
make_user_friendly_and_stable_output <out >actual &&
80
cat >expect <<-EOF &&
81
- <COMMIT-A> refs/t/for/master/topic
81
+ <COMMIT-A> refs/t/changes/24/124/1
82
+ <COMMIT-B> refs/t/changes/25/125/1
83
+ <COMMIT-B> refs/t/for/master/topic
84
EOF
85
test_cmp expect actual &&
84
- git -C workbench update-ref -d refs/t/for/master/topic
86
+ git -C workbench update-ref -d refs/t/for/master/topic &&
87
+ git -C workbench update-ref -d refs/t/changes/24/124/1 &&
88
+ git -C workbench update-ref -d refs/t/changes/25/125/1
89
'
90
91
test_expect_success "setup proc-receive hook (multiple rewrites for one ref, no refname for the 2nd rewrite, $PROTOCOL)" '
@@ -151,10 +155,14 @@ test_expect_success "proc-receive: check remote-tracking #2 ($PROTOCOL)" '
155
grep -v -e refs/remotes -e refs/heads -e refs/tags >out &&
156
make_user_friendly_and_stable_output <out >actual &&
157
cat >expect <<-EOF &&
154
- <COMMIT-A> refs/t/for/master/topic
158
+ <COMMIT-A> refs/t/changes/24/124/1
159
+ <COMMIT-A> refs/t/changes/25/125/1
160
+ <COMMIT-B> refs/t/for/master/topic
161
EOF
162
test_cmp expect actual &&
157
- git -C workbench update-ref -d refs/t/for/master/topic
163
+ git -C workbench update-ref -d refs/t/for/master/topic &&
164
+ git -C workbench update-ref -d refs/t/changes/24/124/1 &&
165
+ git -C workbench update-ref -d refs/t/changes/25/125/1
166
'
167
168
test_expect_success "setup proc-receive hook (multiple rewrites for one ref, $PROTOCOL)" '
@@ -210,8 +218,10 @@ test_expect_success "proc-receive: check remote-tracking #3 ($PROTOCOL)" '
218
grep -v -e refs/remotes -e refs/heads -e refs/tags >out &&
219
make_user_friendly_and_stable_output <out >actual &&
220
cat >expect <<-EOF &&
213
- <COMMIT-A> refs/t/for/master/topic
221
+ <COMMIT-A> refs/t/changes/23/123/1
222
+ <COMMIT-B> refs/t/changes/24/124/2
223
EOF
224
test_cmp expect actual &&
216
- git -C workbench update-ref -d refs/t/for/master/topic
225
+ git -C workbench update-ref -d refs/t/changes/24/124/1 &&
226
+ git -C workbench update-ref -d refs/t/changes/25/125/2
227
'
transport.c
+29
-8
@@ -437,28 +437,49 @@ int transport_refs_pushed(struct ref *ref)
437
return 0;
438
}
439
440
-void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
440
+static void update_one_tracking_ref(struct remote *remote, char *refname,
441
+ struct object_id *new_oid, int deletion,
442
+ int verbose)
443
{
444
struct refspec_item rs;
445
444
- if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
445
- return;
446
-
447
- rs.src = ref->name;
446
+ rs.src = refname;
447
rs.dst = NULL;
448
449
if (!remote_find_tracking(remote, &rs)) {
450
if (verbose)
451
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
453
- if (ref->deletion) {
452
+ if (deletion)
453
delete_ref(NULL, rs.dst, NULL, 0);
455
- } else
456
- update_ref("update by push", rs.dst, &ref->new_oid,
454
+ else
455
+ update_ref("update by push", rs.dst, new_oid,
456
NULL, 0, 0);
457
free(rs.dst);
458
}
459
}
460
461
+void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
462
+{
463
+ char *refname;
464
+ struct object_id *new_oid;
465
+ struct ref_push_report *report;
466
+
467
+ if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
468
+ return;
469
+
470
+ report = ref->report;
471
+ if (!report)
472
+ update_one_tracking_ref(remote, ref->name, &ref->new_oid,
473
+ ref->deletion, verbose);
474
+ else
475
+ for (; report; report = report->next) {
476
+ refname = report->ref_name ? (char *)report->ref_name : ref->name;
477
+ new_oid = report->new_oid ? report->new_oid : &ref->new_oid;
478
+ update_one_tracking_ref(remote, refname, new_oid,
479
+ is_null_oid(new_oid), verbose);
480
+ }
481
+}
482
+
483
static void print_ref_status(char flag, const char *summary,
484
struct ref *to, struct ref *from, const char *msg,
485
struct ref_push_report *report,