aboutsummaryrefslogtreecommitdiffstats
path: root/ref-filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ref-filter.c')
-rw-r--r--ref-filter.c85
1 files changed, 75 insertions, 10 deletions
diff --git a/ref-filter.c b/ref-filter.c
index 3742abbf85..ae6ecbd1cf 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -221,7 +221,7 @@ static void objectname_atom_parser(struct used_atom *atom, const char *arg)
static void refname_atom_parser(struct used_atom *atom, const char *arg)
{
- return refname_atom_parser_internal(&atom->u.refname, arg, atom->name);
+ refname_atom_parser_internal(&atom->u.refname, arg, atom->name);
}
static align_type parse_align_position(const char *s)
@@ -1258,13 +1258,17 @@ char *get_head_description(void)
state.branch);
else if (state.detached_from) {
if (state.detached_at)
- /* TRANSLATORS: make sure this matches
- "HEAD detached at " in wt-status.c */
+ /*
+ * TRANSLATORS: make sure this matches "HEAD
+ * detached at " in wt-status.c
+ */
strbuf_addf(&desc, _("(HEAD detached at %s)"),
state.detached_from);
else
- /* TRANSLATORS: make sure this matches
- "HEAD detached from " in wt-status.c */
+ /*
+ * TRANSLATORS: make sure this matches "HEAD
+ * detached from " in wt-status.c
+ */
strbuf_addf(&desc, _("(HEAD detached from %s)"),
state.detached_from);
}
@@ -1620,7 +1624,7 @@ static int match_pattern(const struct ref_filter *filter, const char *refname)
skip_prefix(refname, "refs/", &refname));
for (; *patterns; patterns++) {
- if (!wildmatch(*patterns, refname, flags, NULL))
+ if (!wildmatch(*patterns, refname, flags))
return 1;
}
return 0;
@@ -1651,7 +1655,7 @@ static int match_name_as_path(const struct ref_filter *filter, const char *refna
refname[plen] == '/' ||
p[plen-1] == '/'))
return 1;
- if (!wildmatch(p, refname, WM_PATHNAME, NULL))
+ if (!wildmatch(p, refname, WM_PATHNAME))
return 1;
}
return 0;
@@ -1668,6 +1672,68 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
}
/*
+ * Find the longest prefix of pattern we can pass to
+ * `for_each_fullref_in()`, namely the part of pattern preceding the
+ * first glob character. (Note that `for_each_fullref_in()` is
+ * perfectly happy working with a prefix that doesn't end at a
+ * pathname component boundary.)
+ */
+static void find_longest_prefix(struct strbuf *out, const char *pattern)
+{
+ const char *p;
+
+ for (p = pattern; *p && !is_glob_special(*p); p++)
+ ;
+
+ strbuf_add(out, pattern, p - pattern);
+}
+
+/*
+ * 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
+ * pattern match, so the callback still has to match each ref individually.
+ */
+static int for_each_fullref_in_pattern(struct ref_filter *filter,
+ each_ref_fn cb,
+ void *cb_data,
+ int broken)
+{
+ struct strbuf prefix = STRBUF_INIT;
+ int ret;
+
+ if (!filter->match_as_path) {
+ /*
+ * in this case, the patterns are applied after
+ * prefixes like "refs/heads/" etc. are stripped off,
+ * so we have to look at everything:
+ */
+ return for_each_fullref_in("", cb, cb_data, broken);
+ }
+
+ if (!filter->name_patterns[0]) {
+ /* no patterns; we have to look at everything */
+ return for_each_fullref_in("", cb, cb_data, broken);
+ }
+
+ if (filter->name_patterns[1]) {
+ /*
+ * multiple patterns; in theory this could still work as long
+ * as the patterns are disjoint. We'd just make multiple calls
+ * to for_each_ref(). But if they're not disjoint, we'd end up
+ * reporting the same ref multiple times. So let's punt on that
+ * for now.
+ */
+ return for_each_fullref_in("", cb, cb_data, broken);
+ }
+
+ find_longest_prefix(&prefix, filter->name_patterns[0]);
+
+ ret = for_each_fullref_in(prefix.buf, cb, cb_data, broken);
+ strbuf_release(&prefix);
+ return ret;
+}
+
+/*
* Given a ref (sha1, refname), check if the ref belongs to the array
* of sha1s. If the given ref is a tag, check if the given tag points
* at one of the sha1s in the given sha1 array.
@@ -1825,8 +1891,7 @@ void ref_array_clear(struct ref_array *array)
for (i = 0; i < array->nr; i++)
free_array_item(array->items[i]);
- free(array->items);
- array->items = NULL;
+ FREE_AND_NULL(array->items);
array->nr = array->alloc = 0;
}
@@ -1913,7 +1978,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
else if (filter->kind == FILTER_REFS_TAGS)
ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata, broken);
else if (filter->kind & FILTER_REFS_ALL)
- ret = for_each_fullref_in("", ref_filter_handler, &ref_cbdata, broken);
+ ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata, broken);
if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
head_ref(ref_filter_handler, &ref_cbdata);
}