Skip to content

Commit e45a859

Browse files
committed
Merge branch 'js/for-each-ref-remote-name-and-ref'
The "--format=..." option "git for-each-ref" takes learned to show the name of the 'remote' repository and the ref at the remote side that is affected for 'upstream' and 'push' via "%(push:remotename)" and friends. * js/for-each-ref-remote-name-and-ref: for-each-ref: test :remotename and :remoteref for-each-ref: let upstream/push report the remote ref name for-each-ref: let upstream/push optionally report the remote name This is the final iteration that made it into upstream Git's master branch and that started out as 8148ee4 (Merge branch 'mingw/ref-filter-remote-name', 2017-10-29). Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 6ea0daa + f3c2140 commit e45a859

File tree

5 files changed

+120
-15
lines changed

5 files changed

+120
-15
lines changed

Documentation/git-for-each-ref.txt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,25 @@ upstream::
145145
(behind), "<>" (ahead and behind), or "=" (in sync). `:track`
146146
also prints "[gone]" whenever unknown upstream ref is
147147
encountered. Append `:track,nobracket` to show tracking
148-
information without brackets (i.e "ahead N, behind M"). Has
149-
no effect if the ref does not have tracking information
150-
associated with it. All the options apart from `nobracket`
151-
are mutually exclusive, but if used together the last option
152-
is selected.
148+
information without brackets (i.e "ahead N, behind M").
149+
+
150+
For any remote-tracking branch `%(upstream)`, `%(upstream:remotename)`
151+
and `%(upstream:remoteref)` refer to the name of the remote and the
152+
name of the tracked remote ref, respectively. In other words, the
153+
remote-tracking branch can be updated explicitly and individually by
154+
using the refspec `%(upstream:remoteref):%(upstream)` to fetch from
155+
`%(upstream:remotename)`.
156+
+
157+
Has no effect if the ref does not have tracking information associated
158+
with it. All the options apart from `nobracket` are mutually exclusive,
159+
but if used together the last option is selected.
153160

154161
push::
155162
The name of a local ref which represents the `@{push}`
156163
location for the displayed ref. Respects `:short`, `:lstrip`,
157-
`:rstrip`, `:track`, and `:trackshort` options as `upstream`
158-
does. Produces an empty string if no `@{push}` ref is
159-
configured.
164+
`:rstrip`, `:track`, `:trackshort`, `:remotename`, and `:remoteref`
165+
options as `upstream` does. Produces an empty string if no `@{push}`
166+
ref is configured.
160167

161168
HEAD::
162169
'*' if HEAD matches current ref (the checked out branch), ' '

ref-filter.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ static struct used_atom {
7676
char color[COLOR_MAXLEN];
7777
struct align align;
7878
struct {
79-
enum { RR_REF, RR_TRACK, RR_TRACKSHORT } option;
79+
enum {
80+
RR_REF, RR_TRACK, RR_TRACKSHORT, RR_REMOTE_NAME, RR_REMOTE_REF
81+
} option;
8082
struct refname_atom refname;
81-
unsigned int nobracket : 1;
83+
unsigned int nobracket : 1, push : 1, push_remote : 1;
8284
} remote_ref;
8385
struct {
8486
enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
@@ -138,6 +140,9 @@ static void remote_ref_atom_parser(const struct ref_format *format, struct used_
138140
struct string_list params = STRING_LIST_INIT_DUP;
139141
int i;
140142

143+
if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:"))
144+
atom->u.remote_ref.push = 1;
145+
141146
if (!arg) {
142147
atom->u.remote_ref.option = RR_REF;
143148
refname_atom_parser_internal(&atom->u.remote_ref.refname,
@@ -157,7 +162,13 @@ static void remote_ref_atom_parser(const struct ref_format *format, struct used_
157162
atom->u.remote_ref.option = RR_TRACKSHORT;
158163
else if (!strcmp(s, "nobracket"))
159164
atom->u.remote_ref.nobracket = 1;
160-
else {
165+
else if (!strcmp(s, "remotename")) {
166+
atom->u.remote_ref.option = RR_REMOTE_NAME;
167+
atom->u.remote_ref.push_remote = 1;
168+
} else if (!strcmp(s, "remoteref")) {
169+
atom->u.remote_ref.option = RR_REMOTE_REF;
170+
atom->u.remote_ref.push_remote = 1;
171+
} else {
161172
atom->u.remote_ref.option = RR_REF;
162173
refname_atom_parser_internal(&atom->u.remote_ref.refname,
163174
arg, atom->name);
@@ -1268,6 +1279,25 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
12681279
*s = ">";
12691280
else
12701281
*s = "<>";
1282+
} else if (atom->u.remote_ref.option == RR_REMOTE_NAME) {
1283+
int explicit;
1284+
const char *remote = atom->u.remote_ref.push ?
1285+
pushremote_for_branch(branch, &explicit) :
1286+
remote_for_branch(branch, &explicit);
1287+
if (explicit)
1288+
*s = xstrdup(remote);
1289+
else
1290+
*s = "";
1291+
} else if (atom->u.remote_ref.option == RR_REMOTE_REF) {
1292+
int explicit;
1293+
const char *merge;
1294+
1295+
merge = remote_ref_for_branch(branch, atom->u.remote_ref.push,
1296+
&explicit);
1297+
if (explicit)
1298+
*s = xstrdup(merge);
1299+
else
1300+
*s = "";
12711301
} else
12721302
die("BUG: unhandled RR_* enum");
12731303
}
@@ -1377,16 +1407,20 @@ static void populate_value(struct ref_array_item *ref)
13771407
if (refname)
13781408
fill_remote_ref_details(atom, refname, branch, &v->s);
13791409
continue;
1380-
} else if (starts_with(name, "push")) {
1410+
} else if (atom->u.remote_ref.push) {
13811411
const char *branch_name;
13821412
if (!skip_prefix(ref->refname, "refs/heads/",
13831413
&branch_name))
13841414
continue;
13851415
branch = branch_get(branch_name);
13861416

1387-
refname = branch_get_push(branch, NULL);
1388-
if (!refname)
1389-
continue;
1417+
if (atom->u.remote_ref.push_remote)
1418+
refname = NULL;
1419+
else {
1420+
refname = branch_get_push(branch, NULL);
1421+
if (!refname)
1422+
continue;
1423+
}
13901424
fill_remote_ref_details(atom, refname, branch, &v->s);
13911425
continue;
13921426
} else if (starts_with(name, "color:")) {

remote.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,36 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
675675
return remote_for_branch(branch, explicit);
676676
}
677677

678+
const char *remote_ref_for_branch(struct branch *branch, int for_push,
679+
int *explicit)
680+
{
681+
if (branch) {
682+
if (!for_push) {
683+
if (branch->merge_nr) {
684+
if (explicit)
685+
*explicit = 1;
686+
return branch->merge_name[0];
687+
}
688+
} else {
689+
const char *dst, *remote_name =
690+
pushremote_for_branch(branch, NULL);
691+
struct remote *remote = remote_get(remote_name);
692+
693+
if (remote && remote->push_refspec_nr &&
694+
(dst = apply_refspecs(remote->push,
695+
remote->push_refspec_nr,
696+
branch->refname))) {
697+
if (explicit)
698+
*explicit = 1;
699+
return dst;
700+
}
701+
}
702+
}
703+
if (explicit)
704+
*explicit = 0;
705+
return "";
706+
}
707+
678708
static struct remote *remote_get_1(const char *name,
679709
const char *(*get_default)(struct branch *, int *))
680710
{

remote.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ struct branch {
223223
struct branch *branch_get(const char *name);
224224
const char *remote_for_branch(struct branch *branch, int *explicit);
225225
const char *pushremote_for_branch(struct branch *branch, int *explicit);
226+
const char *remote_ref_for_branch(struct branch *branch, int for_push,
227+
int *explicit);
226228

227229
int branch_has_merge_config(struct branch *branch);
228230
int branch_merge_matches(struct branch *, int n, const char *);

t/t6300-for-each-ref.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,4 +766,36 @@ test_expect_success 'Verify usage of %(symref:rstrip) atom' '
766766
test_cmp expected actual
767767
'
768768

769+
test_expect_success ':remotename and :remoteref' '
770+
git init remote-tests &&
771+
(
772+
cd remote-tests &&
773+
test_commit initial &&
774+
git remote add from fifth.coffee:blub &&
775+
git config branch.master.remote from &&
776+
git config branch.master.merge refs/heads/stable &&
777+
git remote add to southridge.audio:repo &&
778+
git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
779+
git config branch.master.pushRemote to &&
780+
for pair in "%(upstream)=refs/remotes/from/stable" \
781+
"%(upstream:remotename)=from" \
782+
"%(upstream:remoteref)=refs/heads/stable" \
783+
"%(push)=refs/remotes/to/pushed/master" \
784+
"%(push:remotename)=to" \
785+
"%(push:remoteref)=refs/heads/pushed/master"
786+
do
787+
echo "${pair#*=}" >expect &&
788+
git for-each-ref --format="${pair%=*}" \
789+
refs/heads/master >actual &&
790+
test_cmp expect actual
791+
done &&
792+
git branch push-simple &&
793+
git config branch.push-simple.pushRemote from &&
794+
actual="$(git for-each-ref \
795+
--format="%(push:remotename),%(push:remoteref)" \
796+
refs/heads/push-simple)" &&
797+
test from, = "$actual"
798+
)
799+
'
800+
769801
test_done

0 commit comments

Comments
 (0)