From: Jiang Xin <zhiyou.jx@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> --- ...t-0036-report-multi-rewrite-for-one-ref.sh | 22 +++++++--- transport.c | 40 ++++++++++++++----- 2 files changed, 46 insertions(+), 16 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 <out >actual && cat >expect <<-EOF && - <COMMIT-A> refs/t/for/master/topic + <COMMIT-A> refs/t/changes/24/124/1 + <COMMIT-B> refs/t/changes/25/125/1 + <COMMIT-B> 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 <out >actual && cat >expect <<-EOF && - <COMMIT-A> refs/t/for/master/topic + <COMMIT-A> refs/t/changes/24/124/1 + <COMMIT-A> refs/t/changes/25/125/1 + <COMMIT-B> 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 <out >actual && cat >expect <<-EOF && - <COMMIT-A> refs/t/for/master/topic + <COMMIT-A> refs/t/changes/23/123/1 + <COMMIT-B> 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 10f7dbbcd0..fe0c73fa88 100644 --- a/transport.c +++ b/transport.c @@ -436,28 +436,48 @@ 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_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, - NULL, 0, 0); + 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_options *options; + + if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) + return; + + options = ref->report.options; + if (!options) + update_tracking_ref(remote, ref->name, &ref->new_oid, + ref->deletion, verbose); + else + for (; options; options = options->next) { + refname = options->ref_name ? (char *)options->ref_name : ref->name; + new_oid = options->new_oid ? options->new_oid : &ref->new_oid; + update_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_options *options, -- 2.28.0