for-each-ref: accept "%(push)" format

Just as we have "%(upstream)" to report the "@{upstream}" for each ref, this patch adds "%(push)" to match "@{push}". It supports the same tracking format modifiers as upstream (because you may want to know, for example, which branches have commits to push). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 21, 2015 at 00:45 UTC 29bc88505f22068d7ee6694240e6b13fddb5d059
3 files changed +33 -3
Documentation/git-for-each-ref.txt
+6
@@ -97,6 +97,12 @@ upstream::
97 or "=" (in sync). Has no effect if the ref does not have
98 tracking information associated with it.
99
100 +push::
101 + The name of a local ref which represents the `@{push}` location
102 + for the displayed ref. Respects `:short`, `:track`, and
103 + `:trackshort` options as `upstream` does. Produces an empty
104 + string if no `@{push}` ref is configured.
105 +
106 HEAD::
107 '*' if HEAD matches current ref (the checked out branch), ' '
108 otherwise.
builtin/for-each-ref.c
+15 -2
@@ -74,6 +74,7 @@ static struct {
74 { "contents:body" },
75 { "contents:signature" },
76 { "upstream" },
77 + { "push" },
78 { "symref" },
79 { "flag" },
80 { "HEAD" },
@@ -669,6 +670,16 @@ static void populate_value(struct refinfo *ref)
670 refname = branch_get_upstream(branch, NULL);
671 if (!refname)
672 continue;
673 + } else if (starts_with(name, "push")) {
674 + const char *branch_name;
675 + if (!skip_prefix(ref->refname, "refs/heads/",
676 + &branch_name))
677 + continue;
678 + branch = branch_get(branch_name);
679 +
680 + refname = branch_get_push(branch, NULL);
681 + if (!refname)
682 + continue;
683 } else if (starts_with(name, "color:")) {
684 char color[COLOR_MAXLEN] = "";
685
@@ -714,7 +725,8 @@ static void populate_value(struct refinfo *ref)
725 refname = shorten_unambiguous_ref(refname,
726 warn_ambiguous_refs);
727 else if (!strcmp(formatp, "track") &&
717 - starts_with(name, "upstream")) {
728 + (starts_with(name, "upstream") ||
729 + starts_with(name, "push"))) {
730 char buf[40];
731
732 if (stat_tracking_info(branch, &num_ours,
@@ -736,7 +748,8 @@ static void populate_value(struct refinfo *ref)
748 }
749 continue;
750 } else if (!strcmp(formatp, "trackshort") &&
739 - starts_with(name, "upstream")) {
751 + (starts_with(name, "upstream") ||
752 + starts_with(name, "push"))) {
753 assert(branch);
754
755 if (stat_tracking_info(branch, &num_ours,
t/t6300-for-each-ref.sh
+12 -1
@@ -28,7 +28,10 @@ test_expect_success setup '
28 git update-ref refs/remotes/origin/master master &&
29 git remote add origin nowhere &&
30 git config branch.master.remote origin &&
31 - git config branch.master.merge refs/heads/master
31 + git config branch.master.merge refs/heads/master &&
32 + git remote add myfork elsewhere &&
33 + git config remote.pushdefault myfork &&
34 + git config push.default current
35 '
36
37 test_atom() {
@@ -47,6 +50,7 @@ test_atom() {
50
51 test_atom head refname refs/heads/master
52 test_atom head upstream refs/remotes/origin/master
53 +test_atom head push refs/remotes/myfork/master
54 test_atom head objecttype commit
55 test_atom head objectsize 171
56 test_atom head objectname $(git rev-parse refs/heads/master)
@@ -83,6 +87,7 @@ test_atom head HEAD '*'
87
88 test_atom tag refname refs/tags/testtag
89 test_atom tag upstream ''
90 +test_atom tag push ''
91 test_atom tag objecttype tag
92 test_atom tag objectsize 154
93 test_atom tag objectname $(git rev-parse refs/tags/testtag)
@@ -347,6 +352,12 @@ test_expect_success 'Check that :track[short] works when upstream is invalid' '
352 test_cmp expected actual
353 '
354
355 +test_expect_success '%(push) supports tracking specifiers, too' '
356 + echo "[ahead 1]" >expected &&
357 + git for-each-ref --format="%(push:track)" refs/heads >actual &&
358 + test_cmp expected actual
359 +'
360 +
361 cat >expected <<EOF
362 $(git rev-parse --short HEAD)
363 EOF