Skip to content

Commit 43f8080

Browse files
jacob-kellergitster
authored andcommitted
describe: teach --match to accept multiple patterns
Teach `--match` to be accepted multiple times, accumulating a list of patterns to match into a string list. Each pattern is inclusive, such that a tag need only match one of the provided patterns to be considered for matching. This extension is useful as it enables more flexibility in what tags match, and may avoid the need to run the describe command multiple times to get the same result. Add tests and update the documentation for this change. Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 96415b4 commit 43f8080

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

Documentation/git-describe.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ OPTIONS
8383
--match <pattern>::
8484
Only consider tags matching the given `glob(7)` pattern,
8585
excluding the "refs/tags/" prefix. This can be used to avoid
86-
leaking private tags from the repository.
86+
leaking private tags from the repository. If given multiple times, a
87+
list of patterns will be accumulated, and tags matching any of the
88+
patterns will be considered. Use `--no-match` to clear and reset the
89+
list of patterns.
8790

8891
--always::
8992
Show uniquely abbreviated commit object as fallback.

builtin/describe.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static int abbrev = -1; /* unspecified */
2828
static int max_candidates = 10;
2929
static struct hashmap names;
3030
static int have_util;
31-
static const char *pattern;
31+
static struct string_list patterns = STRING_LIST_INIT_NODUP;
3232
static int always;
3333
static const char *dirty;
3434

@@ -129,9 +129,24 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
129129
if (!all && !is_tag)
130130
return 0;
131131

132-
/* Accept only tags that match the pattern, if given */
133-
if (pattern && (!is_tag || wildmatch(pattern, path + 10, 0, NULL)))
134-
return 0;
132+
/*
133+
* If we're given patterns, accept only tags which match at least one
134+
* pattern.
135+
*/
136+
if (patterns.nr) {
137+
struct string_list_item *item;
138+
139+
if (!is_tag)
140+
return 0;
141+
142+
for_each_string_list_item(item, &patterns) {
143+
if (!wildmatch(item->string, path + 10, 0, NULL))
144+
break;
145+
146+
/* If we get here, no pattern matched. */
147+
return 0;
148+
}
149+
}
135150

136151
/* Is it annotated? */
137152
if (!peel_ref(path, peeled.hash)) {
@@ -404,7 +419,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
404419
N_("only output exact matches"), 0),
405420
OPT_INTEGER(0, "candidates", &max_candidates,
406421
N_("consider <n> most recent tags (default: 10)")),
407-
OPT_STRING(0, "match", &pattern, N_("pattern"),
422+
OPT_STRING_LIST(0, "match", &patterns, N_("pattern"),
408423
N_("only consider tags matching <pattern>")),
409424
OPT_BOOL(0, "always", &always,
410425
N_("show abbreviated commit object as fallback")),
@@ -430,6 +445,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
430445
die(_("--long is incompatible with --abbrev=0"));
431446

432447
if (contains) {
448+
struct string_list_item *item;
433449
struct argv_array args;
434450

435451
argv_array_init(&args);
@@ -440,8 +456,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
440456
argv_array_push(&args, "--always");
441457
if (!all) {
442458
argv_array_push(&args, "--tags");
443-
if (pattern)
444-
argv_array_pushf(&args, "--refs=refs/tags/%s", pattern);
459+
for_each_string_list_item(item, &patterns)
460+
argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
445461
}
446462
if (argc)
447463
argv_array_pushv(&args, argv);

t/t6120-describe.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ check_describe "test2-lightweight-*" --tags --match="test2-*"
182182

183183
check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^
184184

185+
check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^
186+
187+
check_describe "test2-lightweight-*" --long --tags --match="test1-*" --no-match --match="test2-*" HEAD^
188+
185189
test_expect_success 'name-rev with exact tags' '
186190
echo A >expect &&
187191
tag_object=$(git rev-parse refs/tags/A) &&
@@ -206,4 +210,19 @@ test_expect_success 'describe --contains with the exact tags' '
206210
test_cmp expect actual
207211
'
208212

213+
test_expect_success 'describe --contains and --match' '
214+
echo "A^0" >expect &&
215+
tagged_commit=$(git rev-parse "refs/tags/A^0") &&
216+
test_must_fail git describe --contains --match="B" $tagged_commit &&
217+
git describe --contains --match="B" --match="A" $tagged_commit >actual &&
218+
test_cmp expect actual
219+
'
220+
221+
test_expect_success 'describe --contains and --no-match' '
222+
echo "A^0" >expect &&
223+
tagged_commit=$(git rev-parse "refs/tags/A^0") &&
224+
git describe --contains --match="B" --no-match $tagged_commit >actual &&
225+
test_cmp expect actual
226+
'
227+
209228
test_done

0 commit comments

Comments
 (0)