unsigned int length;
} objectname;
struct refname_atom refname;
+ char *head;
} u;
} *used_atom;
static int used_atom_cnt, need_tagged, need_symref;
}
}
+static void head_atom_parser(struct used_atom *atom, const char *arg)
+{
+ struct object_id unused;
+
+ atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, unused.hash, NULL);
+}
static struct {
const char *name;
{ "push", FIELD_STR, remote_ref_atom_parser },
{ "symref", FIELD_STR, refname_atom_parser },
{ "flag" },
- { "HEAD" },
+ { "HEAD", FIELD_STR, head_atom_parser },
{ "color", FIELD_STR, color_atom_parser },
{ "align", FIELD_STR, align_atom_parser },
{ "end" },
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);
}
} else if (!deref && grab_objectname(name, ref->objectname.hash, v, atom)) {
continue;
} else if (!strcmp(name, "HEAD")) {
- const char *head;
- struct object_id oid;
-
- head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- oid.hash, NULL);
- if (head && !strcmp(ref->refname, head))
+ if (atom->u.head && !strcmp(ref->refname, atom->u.head))
v->s = "*";
else
v->s = " ";
return match_pattern(filter, 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
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);
}