Skip to content

Commit 77d21f2

Browse files
jacob-kellergitster
authored andcommitted
describe: teach describe negative pattern matches
Teach git-describe the `--exclude` option which will allow specifying a glob pattern of tags to ignore. This can be combined with the `--match` patterns to enable more flexibility in determining which tags to consider. For example, suppose you wish to find the first official release tag that contains a certain commit. If we assume that official release tags are of the form "v*" and pre-release candidates include "*rc*" in their name, we can now find the first release tag that introduces the commit abcdef: git describe --contains --match="v*" --exclude="*rc*" abcdef Add documentation, tests, and completion for this change. Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 43f8080 commit 77d21f2

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

Documentation/git-describe.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ OPTIONS
8888
patterns will be considered. Use `--no-match` to clear and reset the
8989
list of patterns.
9090

91+
--exclude <pattern>::
92+
Do not consider tags matching the given `glob(7)` pattern, excluding
93+
the "refs/tags/" prefix. This can be used to narrow the tag space and
94+
find only tags matching some meaningful criteria. If given multiple
95+
times, a list of patterns will be accumulated and tags matching any
96+
of the patterns will be excluded. When combined with --match a tag will
97+
be considered when it matches at least one --match pattern and does not
98+
match any of the --exclude patterns. Use `--no-exclude` to clear and
99+
reset the list of patterns.
100+
91101
--always::
92102
Show uniquely abbreviated commit object as fallback.
93103

builtin/describe.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static int max_candidates = 10;
2929
static struct hashmap names;
3030
static int have_util;
3131
static struct string_list patterns = STRING_LIST_INIT_NODUP;
32+
static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
3233
static int always;
3334
static const char *dirty;
3435

@@ -129,6 +130,22 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
129130
if (!all && !is_tag)
130131
return 0;
131132

133+
/*
134+
* If we're given exclude patterns, first exclude any tag which match
135+
* any of the exclude pattern.
136+
*/
137+
if (exclude_patterns.nr) {
138+
struct string_list_item *item;
139+
140+
if (!is_tag)
141+
return 0;
142+
143+
for_each_string_list_item(item, &exclude_patterns) {
144+
if (!wildmatch(item->string, path + 10, 0, NULL))
145+
return 0;
146+
}
147+
}
148+
132149
/*
133150
* If we're given patterns, accept only tags which match at least one
134151
* pattern.
@@ -421,6 +438,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
421438
N_("consider <n> most recent tags (default: 10)")),
422439
OPT_STRING_LIST(0, "match", &patterns, N_("pattern"),
423440
N_("only consider tags matching <pattern>")),
441+
OPT_STRING_LIST(0, "exclude", &exclude_patterns, N_("pattern"),
442+
N_("do not consider tags matching <pattern>")),
424443
OPT_BOOL(0, "always", &always,
425444
N_("show abbreviated commit object as fallback")),
426445
{OPTION_STRING, 0, "dirty", &dirty, N_("mark"),
@@ -458,6 +477,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
458477
argv_array_push(&args, "--tags");
459478
for_each_string_list_item(item, &patterns)
460479
argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
480+
for_each_string_list_item(item, &exclude_patterns)
481+
argv_array_pushf(&args, "--exclude=refs/tags/%s", item->string);
461482
}
462483
if (argc)
463484
argv_array_pushv(&args, argv);

contrib/completion/git-completion.bash

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,7 @@ _git_describe ()
11981198
__gitcomp "
11991199
--all --tags --contains --abbrev= --candidates=
12001200
--exact-match --debug --long --match --always
1201+
--exclude
12011202
"
12021203
return
12031204
esac

t/t6120-describe.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ test_expect_success 'describe --contains and --match' '
218218
test_cmp expect actual
219219
'
220220

221+
test_expect_success 'describe --exclude' '
222+
echo "c~1" >expect &&
223+
tagged_commit=$(git rev-parse "refs/tags/A^0") &&
224+
test_must_fail git describe --contains --match="B" $tagged_commit &&
225+
git describe --contains --match="?" --exclude="A" $tagged_commit >actual &&
226+
test_cmp expect actual
227+
'
228+
221229
test_expect_success 'describe --contains and --no-match' '
222230
echo "A^0" >expect &&
223231
tagged_commit=$(git rev-parse "refs/tags/A^0") &&

0 commit comments

Comments
 (0)