for-each-ref: add "upstream" format field
The logic for determining the upstream ref of a branch is somewhat complex to perform in a shell script. This patch provides a plumbing mechanism for scripts to access the C logic used internally by git-status, git-branch, etc. For example: $ git for-each-ref \ --format='%(refname:short) %(upstream:short)' \ refs/heads/ master origin/master Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Apr 7, 2009 at 03:09 UTC
8cae19d987b1bbd43258558f591e39d9d216dcb3
3 files changed
+41
Documentation/git-for-each-ref.txt
+5
@@ -85,6 +85,11 @@ objectsize::
85
objectname::
86
The object name (aka SHA-1).
87
88
+upstream::
89
+ The name of a local ref which can be considered ``upstream''
90
+ from the displayed ref. Respects `:short` in the same way as
91
+ `refname` above.
92
+
93
In addition to the above, for commit and tag objects, the header
94
field names (`tree`, `parent`, `object`, `type`, and `tag`) can
95
be used to specify the value in the header field.
builtin-for-each-ref.c
+14
@@ -8,6 +8,7 @@
8
#include "blob.h"
9
#include "quote.h"
10
#include "parse-options.h"
11
+#include "remote.h"
12
13
/* Quoting styles */
14
#define QUOTE_NONE 0
@@ -66,6 +67,7 @@ static struct {
67
{ "subject" },
68
{ "body" },
69
{ "contents" },
70
+ { "upstream" },
71
};
72
73
/*
@@ -682,6 +684,18 @@ static void populate_value(struct refinfo *ref)
684
685
if (!prefixcmp(name, "refname"))
686
refname = ref->refname;
687
+ else if(!prefixcmp(name, "upstream")) {
688
+ struct branch *branch;
689
+ /* only local branches may have an upstream */
690
+ if (prefixcmp(ref->refname, "refs/heads/"))
691
+ continue;
692
+ branch = branch_get(ref->refname + 11);
693
+
694
+ if (!branch || !branch->merge || !branch->merge[0] ||
695
+ !branch->merge[0]->dst)
696
+ continue;
697
+ refname = branch->merge[0]->dst;
698
+ }
699
else
700
continue;
701
t/t6300-for-each-ref.sh
+22
@@ -26,6 +26,13 @@ test_expect_success 'Create sample commit with known timestamp' '
26
git tag -a -m "Tagging at $datestamp" testtag
27
'
28
29
+test_expect_success 'Create upstream config' '
30
+ git update-ref refs/remotes/origin/master master &&
31
+ git remote add origin nowhere &&
32
+ git config branch.master.remote origin &&
33
+ git config branch.master.merge refs/heads/master
34
+'
35
+
36
test_atom() {
37
case "$1" in
38
head) ref=refs/heads/master ;;
@@ -39,6 +46,7 @@ test_atom() {
46
}
47
48
test_atom head refname refs/heads/master
49
+test_atom head upstream refs/remotes/origin/master
50
test_atom head objecttype commit
51
test_atom head objectsize 171
52
test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581
@@ -68,6 +76,7 @@ test_atom head contents 'Initial
76
'
77
78
test_atom tag refname refs/tags/testtag
79
+test_atom tag upstream ''
80
test_atom tag objecttype tag
81
test_atom tag objectsize 154
82
test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322
@@ -203,6 +212,7 @@ test_expect_success 'Check format "rfc2822" date fields output' '
212
213
cat >expected <<\EOF
214
refs/heads/master
215
+refs/remotes/origin/master
216
refs/tags/testtag
217
EOF
218
@@ -214,6 +224,7 @@ test_expect_success 'Verify ascending sort' '
224
225
cat >expected <<\EOF
226
refs/tags/testtag
227
+refs/remotes/origin/master
228
refs/heads/master
229
EOF
230
@@ -224,6 +235,7 @@ test_expect_success 'Verify descending sort' '
235
236
cat >expected <<\EOF
237
'refs/heads/master'
238
+'refs/remotes/origin/master'
239
'refs/tags/testtag'
240
EOF
241
@@ -244,6 +256,7 @@ test_expect_success 'Quoting style: python' '
256
257
cat >expected <<\EOF
258
"refs/heads/master"
259
+"refs/remotes/origin/master"
260
"refs/tags/testtag"
261
EOF
262
@@ -273,6 +286,15 @@ test_expect_success 'Check short refname format' '
286
test_cmp expected actual
287
'
288
289
+cat >expected <<EOF
290
+origin/master
291
+EOF
292
+
293
+test_expect_success 'Check short upstream format' '
294
+ git for-each-ref --format="%(upstream:short)" refs/heads >actual &&
295
+ test_cmp expected actual
296
+'
297
+
298
test_expect_success 'Check for invalid refname format' '
299
test_must_fail git for-each-ref --format="%(refname:INVALID)"
300
'