From 1702ae6f61412fa7d858701a7724a5cbf4aeea3e Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Thu, 27 Aug 2020 11:45:50 -0400 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- ...t-0036-report-multi-rewrite-for-one-ref.sh | 22 ++++++++--- transport.c | 37 +++++++++++++++---- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh b/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh index 8eec3a1ed8..73283d81e8 100644 --- a/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh +++ b/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh @@ -78,10 +78,14 @@ test_expect_success "proc-receive: check remote-tracking #1 ($PROTOCOL)" ' grep -v -e refs/remotes -e refs/heads -e refs/tags >out && make_user_friendly_and_stable_output actual && cat >expect <<-EOF && - refs/t/for/master/topic + refs/t/changes/24/124/1 + refs/t/changes/25/125/1 + refs/t/for/master/topic EOF test_cmp expect actual && - git -C workbench update-ref -d refs/t/for/master/topic + git -C workbench update-ref -d refs/t/for/master/topic && + git -C workbench update-ref -d refs/t/changes/24/124/1 && + git -C workbench update-ref -d refs/t/changes/25/125/1 ' 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)" ' grep -v -e refs/remotes -e refs/heads -e refs/tags >out && make_user_friendly_and_stable_output actual && cat >expect <<-EOF && - refs/t/for/master/topic + refs/t/changes/24/124/1 + refs/t/changes/25/125/1 + refs/t/for/master/topic EOF test_cmp expect actual && - git -C workbench update-ref -d refs/t/for/master/topic + git -C workbench update-ref -d refs/t/for/master/topic && + git -C workbench update-ref -d refs/t/changes/24/124/1 && + git -C workbench update-ref -d refs/t/changes/25/125/1 ' 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)" ' grep -v -e refs/remotes -e refs/heads -e refs/tags >out && make_user_friendly_and_stable_output actual && cat >expect <<-EOF && - refs/t/for/master/topic + refs/t/changes/23/123/1 + refs/t/changes/24/124/2 EOF test_cmp expect actual && - git -C workbench update-ref -d refs/t/for/master/topic + git -C workbench update-ref -d refs/t/changes/24/124/1 && + git -C workbench update-ref -d refs/t/changes/25/125/2 ' diff --git a/transport.c b/transport.c index e146de6c4e..a69f2cf806 100644 --- a/transport.c +++ b/transport.c @@ -437,28 +437,49 @@ int transport_refs_pushed(struct ref *ref) return 0; } -void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) +static void update_one_tracking_ref(struct remote *remote, char *refname, + struct object_id *new_oid, int deletion, + int verbose) { struct refspec_item rs; - if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) - return; - - rs.src = ref->name; + rs.src = refname; rs.dst = NULL; if (!remote_find_tracking(remote, &rs)) { if (verbose) fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); - if (ref->deletion) { + if (deletion) delete_ref(NULL, rs.dst, NULL, 0); - } else - update_ref("update by push", rs.dst, &ref->new_oid, + else + update_ref("update by push", rs.dst, new_oid, NULL, 0, 0); free(rs.dst); } } +void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) +{ + char *refname; + struct object_id *new_oid; + struct ref_push_report *report; + + if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) + return; + + report = ref->report; + if (!report) + update_one_tracking_ref(remote, ref->name, &ref->new_oid, + ref->deletion, verbose); + else + for (; report; report = report->next) { + refname = report->ref_name ? (char *)report->ref_name : ref->name; + new_oid = report->new_oid ? report->new_oid : &ref->new_oid; + update_one_tracking_ref(remote, refname, new_oid, + is_null_oid(new_oid), verbose); + } +} + static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, struct ref_push_report *report,