Skip to content

Commit 812a588

Browse files
Damien Robertgitster
authored andcommitted
remote.c: fix handling of %(push:remoteref)
Looking at the value of %(push:remoteref) only handles the case when an explicit push refspec is passed. But it does not handle the fallback cases of looking at the configuration value of `push.default`. In particular, doing something like git config push.default current git for-each-ref --format='%(push)' git for-each-ref --format='%(push:remoteref)' prints a useful tracking ref for the first for-each-ref, but an empty string for the second. Since the intention of %(push:remoteref), from 9700fae (for-each-ref: let upstream/push report the remote ref name) is to get exactly which branch `git push` will push to, even in the fallback cases, fix this. To get the meaning of %(push:remoteref), `ref-filter.c` calls `remote_ref_for_branch`. We simply add a new static helper function, `branch_get_push_remoteref` that follows the logic of `branch_get_push_1`, and call it from `remote_ref_for_branch`. We also update t/6300-for-each-ref.sh to handle all `push.default` strategies. This involves testing `push.default=simple` twice, once where there is a matching upstream branch and once when there is none. Signed-off-by: Damien Robert <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e870325 commit 812a588

File tree

2 files changed

+111
-27
lines changed

2 files changed

+111
-27
lines changed

remote.c

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -516,28 +516,6 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
516516
return remote_for_branch(branch, explicit);
517517
}
518518

519-
const char *remote_ref_for_branch(struct branch *branch, int for_push)
520-
{
521-
if (branch) {
522-
if (!for_push) {
523-
if (branch->merge_nr) {
524-
return branch->merge_name[0];
525-
}
526-
} else {
527-
const char *dst, *remote_name =
528-
pushremote_for_branch(branch, NULL);
529-
struct remote *remote = remote_get(remote_name);
530-
531-
if (remote && remote->push.nr &&
532-
(dst = apply_refspecs(&remote->push,
533-
branch->refname))) {
534-
return dst;
535-
}
536-
}
537-
}
538-
return NULL;
539-
}
540-
541519
static struct remote *remote_get_1(const char *name,
542520
const char *(*get_default)(struct branch *, int *))
543521
{
@@ -1656,6 +1634,64 @@ static const char *tracking_for_push_dest(struct remote *remote,
16561634
return ret;
16571635
}
16581636

1637+
/**
1638+
* Return the local name of the remote tracking branch, as in
1639+
* %(push:remoteref), that corresponds to the ref we would push to given a
1640+
* bare `git push` while `branch` is checked out.
1641+
* See also branch_get_push_1 below.
1642+
*/
1643+
static const char *branch_get_push_remoteref(struct branch *branch)
1644+
{
1645+
struct remote *remote;
1646+
1647+
remote = remote_get(pushremote_for_branch(branch, NULL));
1648+
if (!remote)
1649+
return NULL;
1650+
1651+
if (remote->push.nr) {
1652+
return apply_refspecs(&remote->push, branch->refname);
1653+
}
1654+
1655+
if (remote->mirror)
1656+
return branch->refname;
1657+
1658+
switch (push_default) {
1659+
case PUSH_DEFAULT_NOTHING:
1660+
return NULL;
1661+
1662+
case PUSH_DEFAULT_MATCHING:
1663+
case PUSH_DEFAULT_CURRENT:
1664+
return branch->refname;
1665+
1666+
case PUSH_DEFAULT_UPSTREAM:
1667+
if (branch && branch->merge && branch->merge[0] &&
1668+
branch->merge[0]->dst)
1669+
return branch->merge[0]->src;
1670+
else
1671+
return NULL;
1672+
1673+
case PUSH_DEFAULT_UNSPECIFIED:
1674+
case PUSH_DEFAULT_SIMPLE:
1675+
{
1676+
const char *up, *cur;
1677+
1678+
up = branch_get_upstream(branch, NULL);
1679+
cur = tracking_for_push_dest(remote, branch->refname, NULL);
1680+
if (up && cur && !strcmp(cur, up))
1681+
return branch->refname;
1682+
else
1683+
return NULL;
1684+
1685+
}
1686+
}
1687+
BUG("unhandled push situation");
1688+
}
1689+
1690+
/**
1691+
* Return the tracking branch, as in %(push), that corresponds to the ref we
1692+
* would push to given a bare `git push` while `branch` is checked out.
1693+
* See also branch_get_push_remoteref above.
1694+
*/
16591695
static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
16601696
{
16611697
struct remote *remote;
@@ -1735,6 +1771,20 @@ static int ignore_symref_update(const char *refname)
17351771
return (flag & REF_ISSYMREF);
17361772
}
17371773

1774+
const char *remote_ref_for_branch(struct branch *branch, int for_push)
1775+
{
1776+
if (branch) {
1777+
if (!for_push) {
1778+
if (branch->merge_nr) {
1779+
return branch->merge_name[0];
1780+
}
1781+
} else {
1782+
return branch_get_push_remoteref(branch);
1783+
}
1784+
}
1785+
return NULL;
1786+
}
1787+
17381788
/*
17391789
* Create and return a list of (struct ref) consisting of copies of
17401790
* each remote_ref that matches refspec. refspec must be a pattern.

t/t6300-for-each-ref.sh

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -875,12 +875,46 @@ test_expect_success ':remotename and :remoteref' '
875875
git for-each-ref --format="${pair%=*}" \
876876
refs/heads/master >actual &&
877877
test_cmp expect actual
878-
done &&
879-
git branch push-simple &&
880-
git config branch.push-simple.pushRemote from &&
881-
actual="$(git for-each-ref \
878+
done
879+
)
880+
'
881+
882+
test_expect_success ':push:remoteref' '
883+
git init push-tests &&
884+
(
885+
cd push-tests &&
886+
test_commit initial &&
887+
git remote add from fifth.coffee:blub &&
888+
git config branch.master.remote from &&
889+
actual="$(git -c push.default=simple for-each-ref \
890+
--format="%(push:remotename),%(push:remoteref)" \
891+
refs/heads/master)" &&
892+
test from, = "$actual" &&
893+
git config branch.master.merge refs/heads/master &&
894+
actual="$(git -c push.default=simple for-each-ref \
895+
--format="%(push:remotename),%(push:remoteref)" \
896+
refs/heads/master)" &&
897+
test from,refs/heads/master = "$actual" &&
898+
git config branch.master.merge refs/heads/other &&
899+
actual="$(git -c push.default=simple for-each-ref \
900+
--format="%(push:remotename),%(push:remoteref)" \
901+
refs/heads/master)" &&
902+
test from, = "$actual" &&
903+
actual="$(git -c push.default=upstream for-each-ref \
904+
--format="%(push:remotename),%(push:remoteref)" \
905+
refs/heads/master)" &&
906+
test from,refs/heads/other = "$actual" &&
907+
actual="$(git -c push.default=current for-each-ref \
908+
--format="%(push:remotename),%(push:remoteref)" \
909+
refs/heads/master)" &&
910+
test from,refs/heads/master = "$actual" &&
911+
actual="$(git -c push.default=matching for-each-ref \
912+
--format="%(push:remotename),%(push:remoteref)" \
913+
refs/heads/master)" &&
914+
test from,refs/heads/master = "$actual" &&
915+
actual="$(git -c push.default=nothing for-each-ref \
882916
--format="%(push:remotename),%(push:remoteref)" \
883-
refs/heads/push-simple)" &&
917+
refs/heads/master)" &&
884918
test from, = "$actual"
885919
)
886920
'

0 commit comments

Comments
 (0)