[--points-at=<object>]
[--merged[=<object>]] [--no-merged[=<object>]]
[--contains[=<object>]] [--no-contains[=<object>]]
+ [--exclude=<pattern> ...]
DESCRIPTION
-----------
Do not print a newline after formatted refs where the format expands
to the empty string.
+--exclude=<pattern>::
+ If one or more patterns are given, only refs which do not match
+ any excluded pattern(s) are shown. Matching is done using the
+ same rules as `<pattern>` above.
+
FIELD NAMES
-----------
OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
OPT__COLOR(&format.use_color, N_("respect format colors")),
+ OPT_REF_FILTER_EXCLUDE(&filter),
OPT_REF_SORT(&sorting_options),
OPT_CALLBACK(0, "points-at", &filter.points_at,
N_("object"), N_("print only refs which points at the given object"),
filter->ignore_case);
}
+static int filter_exclude_match(struct ref_filter *filter, const char *refname)
+{
+ if (!filter->exclude.nr)
+ return 0;
+ if (filter->match_as_path)
+ return match_name_as_path(filter->exclude.v, refname,
+ filter->ignore_case);
+ return match_pattern(filter->exclude.v, refname, filter->ignore_case);
+}
+
/*
* This is the same as for_each_fullref_in(), but it tries to iterate
* only over the patterns we'll care about. Note that it _doesn't_ do a full
if (!filter_pattern_match(filter, refname))
return 0;
+ if (filter_exclude_match(filter, refname))
+ return 0;
+
if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
return 0;
void ref_filter_clear(struct ref_filter *filter)
{
+ strvec_clear(&filter->exclude);
oid_array_clear(&filter->points_at);
free_commit_list(filter->with_commit);
free_commit_list(filter->no_commit);
#include "refs.h"
#include "commit.h"
#include "string-list.h"
+#include "strvec.h"
/* Quoting styles */
#define QUOTE_NONE 0
struct ref_filter {
const char **name_patterns;
+ struct strvec exclude;
struct oid_array points_at;
struct commit_list *with_commit;
struct commit_list *no_commit;
#define REF_FILTER_INIT { \
.points_at = OID_ARRAY_INIT, \
+ .exclude = STRVEC_INIT, \
}
#define REF_FORMAT_INIT { \
.use_color = -1, \
#define OPT_REF_SORT(var) \
OPT_STRING_LIST(0, "sort", (var), \
N_("key"), N_("field name to sort on"))
+#define OPT_REF_FILTER_EXCLUDE(var) \
+ OPT_STRVEC(0, "exclude", &(var)->exclude, \
+ N_("pattern"), N_("exclude refs which match pattern"))
/*
* API for filtering a set of refs. Based on the type of refs the user
test_cmp expected actual
'
+cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with prefix exclusions' '
+ for tag in foo/one foo/two foo/three bar baz
+ do
+ git tag "$tag" || return 1
+ done &&
+ test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/ --exclude=refs/tags/foo >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/foo/one
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with pattern exclusions' '
+ for tag in foo/one foo/two foo/three bar baz
+ do
+ git tag "$tag" || return 1
+ done &&
+ test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/ --exclude="refs/tags/foo/t*" >actual &&
+ test_cmp expected actual
+'
+
cat >expected <<\EOF
'refs/heads/main'
'refs/remotes/origin/main'