Skip to content

Commit 1a34728

Browse files
KarthikNayakgitster
authored andcommitted
ref-filter: add an 'rstrip=<N>' option to atoms which deal with refnames
Complimenting the existing 'lstrip=<N>' option, add an 'rstrip=<N>' option which strips `<N>` slash-separated path components from the end of the refname (e.g., `%(refname:rstrip=2)` turns `refs/tags/foo` into `refs`). Signed-off-by: Karthik Nayak <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1a0ca5e commit 1a34728

File tree

3 files changed

+81
-21
lines changed

3 files changed

+81
-21
lines changed

Documentation/git-for-each-ref.txt

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ refname::
9595
The name of the ref (the part after $GIT_DIR/).
9696
For a non-ambiguous short name of the ref append `:short`.
9797
The option core.warnAmbiguousRefs is used to select the strict
98-
abbreviation mode. If `lstrip=<N>` is appended, strips `<N>`
99-
slash-separated path components from the front of the refname
100-
(e.g. `%(refname:lstrip=2)` turns `refs/tags/foo` into `foo`.
98+
abbreviation mode. If `lstrip=<N>` (`rstrip=<N>`) is appended, strips `<N>`
99+
slash-separated path components from the front (back) of the refname
100+
(e.g. `%(refname:lstrip=2)` turns `refs/tags/foo` into `foo` and
101+
`%(refname:rstrip=2)` turns `refs/tags/foo` into `refs`).
101102
If `<N>` is a negative number, strip as many path components as
102-
necessary from the left to leave `-<N>` path components
103+
necessary from the specified end to leave `-<N>` path components
103104
(e.g. `%(refname:lstrip=-2)` turns
104-
`refs/tags/foo` into `tags/foo`). When the ref does not have
105+
`refs/tags/foo` into `tags/foo` and `%(refname:rstrip=-1)`
106+
turns `refs/tags/foo` into `refs`). When the ref does not have
105107
enough components, the result becomes an empty string if
106108
stripping with positive <N>, or it becomes the full refname if
107109
stripping with negative <N>. Neither is an error.
@@ -121,22 +123,23 @@ objectname::
121123

122124
upstream::
123125
The name of a local ref which can be considered ``upstream''
124-
from the displayed ref. Respects `:short` and `:lstrip` in the
125-
same way as `refname` above. Additionally respects `:track`
126-
to show "[ahead N, behind M]" and `:trackshort` to show the
127-
terse version: ">" (ahead), "<" (behind), "<>" (ahead and
128-
behind), or "=" (in sync). `:track` also prints "[gone]"
129-
whenever unknown upstream ref is encountered. Append
130-
`:track,nobracket` to show tracking information without
131-
brackets (i.e "ahead N, behind M"). Has no effect if the ref
132-
does not have tracking information associated with it. All
133-
the options apart from `nobracket` are mutually exclusive, but
134-
if used together the last option is selected.
126+
from the displayed ref. Respects `:short`, `:lstrip` and
127+
`:rstrip` in the same way as `refname` above. Additionally
128+
respects `:track` to show "[ahead N, behind M]" and
129+
`:trackshort` to show the terse version: ">" (ahead), "<"
130+
(behind), "<>" (ahead and behind), or "=" (in sync). `:track`
131+
also prints "[gone]" whenever unknown upstream ref is
132+
encountered. Append `:track,nobracket` to show tracking
133+
information without brackets (i.e "ahead N, behind M"). Has
134+
no effect if the ref does not have tracking information
135+
associated with it. All the options apart from `nobracket`
136+
are mutually exclusive, but if used together the last option
137+
is selected.
135138

136139
push::
137140
The name of a local ref which represents the `@{push}`
138141
location for the displayed ref. Respects `:short`, `:lstrip`,
139-
`:track`, and `:trackshort` options as `upstream`
142+
`:rstrip`, `:track`, and `:trackshort` options as `upstream`
140143
does. Produces an empty string if no `@{push}` ref is
141144
configured.
142145

@@ -178,8 +181,9 @@ if::
178181

179182
symref::
180183
The ref which the given symbolic ref refers to. If not a
181-
symbolic ref, nothing is printed. Respects the `:short` and
182-
`:lstrip` options in the same way as `refname` above.
184+
symbolic ref, nothing is printed. Respects the `:short`,
185+
`:lstrip` and `:rstrip` options in the same way as `refname`
186+
above.
183187

184188
In addition to the above, for commit and tag objects, the header
185189
field names (`tree`, `parent`, `object`, `type`, and `tag`) can

ref-filter.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ struct if_then_else {
3333
};
3434

3535
struct refname_atom {
36-
enum { R_NORMAL, R_SHORT, R_LSTRIP } option;
37-
int lstrip;
36+
enum { R_NORMAL, R_SHORT, R_LSTRIP, R_RSTRIP } option;
37+
int lstrip, rstrip;
3838
};
3939

4040
/*
@@ -95,6 +95,10 @@ static void refname_atom_parser_internal(struct refname_atom *atom,
9595
atom->option = R_LSTRIP;
9696
if (strtol_i(arg, 10, &atom->lstrip))
9797
die(_("Integer value expected refname:lstrip=%s"), arg);
98+
} else if (skip_prefix(arg, "rstrip=", &arg)) {
99+
atom->option = R_RSTRIP;
100+
if (strtol_i(arg, 10, &atom->rstrip))
101+
die(_("Integer value expected refname:rstrip=%s"), arg);
98102
} else
99103
die(_("unrecognized %%(%s) argument: %s"), name, arg);
100104
}
@@ -1125,12 +1129,45 @@ static const char *lstrip_ref_components(const char *refname, int len)
11251129
return start;
11261130
}
11271131

1132+
static const char *rstrip_ref_components(const char *refname, int len)
1133+
{
1134+
long remaining = len;
1135+
char *start = xstrdup(refname);
1136+
1137+
if (len < 0) {
1138+
int i;
1139+
const char *p = refname;
1140+
1141+
/* Find total no of '/' separated path-components */
1142+
for (i = 0; p[i]; p[i] == '/' ? i++ : *p++)
1143+
;
1144+
/*
1145+
* The number of components we need to strip is now
1146+
* the total minus the components to be left (Plus one
1147+
* because we count the number of '/', but the number
1148+
* of components is one more than the no of '/').
1149+
*/
1150+
remaining = i + len + 1;
1151+
}
1152+
1153+
while (remaining-- > 0) {
1154+
char *p = strrchr(start, '/');
1155+
if (p == NULL)
1156+
return "";
1157+
else
1158+
p[0] = '\0';
1159+
}
1160+
return start;
1161+
}
1162+
11281163
static const char *show_ref(struct refname_atom *atom, const char *refname)
11291164
{
11301165
if (atom->option == R_SHORT)
11311166
return shorten_unambiguous_ref(refname, warn_ambiguous_refs);
11321167
else if (atom->option == R_LSTRIP)
11331168
return lstrip_ref_components(refname, atom->lstrip);
1169+
else if (atom->option == R_RSTRIP)
1170+
return rstrip_ref_components(refname, atom->rstrip);
11341171
else
11351172
return refname;
11361173
}

t/t6300-for-each-ref.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,22 @@ test_atom head refname:lstrip=1 heads/master
5555
test_atom head refname:lstrip=2 master
5656
test_atom head refname:lstrip=-1 master
5757
test_atom head refname:lstrip=-2 heads/master
58+
test_atom head refname:rstrip=1 refs/heads
59+
test_atom head refname:rstrip=2 refs
60+
test_atom head refname:rstrip=-1 refs
61+
test_atom head refname:rstrip=-2 refs/heads
5862
test_atom head upstream refs/remotes/origin/master
5963
test_atom head upstream:short origin/master
6064
test_atom head upstream:lstrip=2 origin/master
6165
test_atom head upstream:lstrip=-2 origin/master
66+
test_atom head upstream:rstrip=2 refs/remotes
67+
test_atom head upstream:rstrip=-2 refs/remotes
6268
test_atom head push refs/remotes/myfork/master
6369
test_atom head push:short myfork/master
6470
test_atom head push:lstrip=1 remotes/myfork/master
6571
test_atom head push:lstrip=-1 master
72+
test_atom head push:rstrip=1 refs/remotes/myfork
73+
test_atom head push:rstrip=-1 refs
6674
test_atom head objecttype commit
6775
test_atom head objectsize 171
6876
test_atom head objectname $(git rev-parse refs/heads/master)
@@ -631,4 +639,15 @@ test_expect_success 'Verify usage of %(symref:lstrip) atom' '
631639
test_cmp expected actual
632640
'
633641

642+
cat >expected <<EOF
643+
refs
644+
refs/heads
645+
EOF
646+
647+
test_expect_success 'Verify usage of %(symref:rstrip) atom' '
648+
git for-each-ref --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
649+
git for-each-ref --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
650+
test_cmp expected actual
651+
'
652+
634653
test_done

0 commit comments

Comments
 (0)