aboutsummaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2010-01-22 16:08:16 -0800
committerJunio C Hamano <gitster@pobox.com>2010-01-22 16:08:16 -0800
commit78bc024ab075f4d5d9cc0b6540b538f3d93d04cb (patch)
treedfafe6826227f4ec130048dba711da3643722873 /refs.c
parent4ca1b623865a9dc100f95a7867e35a9f73d7507a (diff)
parente2b53e58081e6a30309625fc6194ccb42772846b (diff)
downloadgit-78bc024ab075f4d5d9cc0b6540b538f3d93d04cb.tar.xz
Merge branch 'il/rev-glob'
* il/rev-glob: Documentation: improve description of --glob=pattern and friends rev-parse --branches/--tags/--remotes=pattern rev-parse --glob
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 3e73a0a36d..503a8c2bd0 100644
--- a/refs.c
+++ b/refs.c
@@ -519,6 +519,13 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
return ref;
}
+/* The argument to filter_refs */
+struct ref_filter {
+ const char *pattern;
+ each_ref_fn *fn;
+ void *cb_data;
+};
+
int read_ref(const char *ref, unsigned char *sha1)
{
if (resolve_ref(ref, sha1, 1, NULL))
@@ -545,6 +552,15 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
}
+static int filter_refs(const char *ref, const unsigned char *sha, int flags,
+ void *data)
+{
+ struct ref_filter *filter = (struct ref_filter *)data;
+ if (fnmatch(filter->pattern, ref, 0))
+ return 0;
+ return filter->fn(ref, sha, flags, filter->cb_data);
+}
+
int peel_ref(const char *ref, unsigned char *sha1)
{
int flag;
@@ -674,6 +690,43 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
}
+int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
+ const char *prefix, void *cb_data)
+{
+ struct strbuf real_pattern = STRBUF_INIT;
+ struct ref_filter filter;
+ const char *has_glob_specials;
+ int ret;
+
+ if (!prefix && prefixcmp(pattern, "refs/"))
+ strbuf_addstr(&real_pattern, "refs/");
+ else if (prefix)
+ strbuf_addstr(&real_pattern, prefix);
+ strbuf_addstr(&real_pattern, pattern);
+
+ has_glob_specials = strpbrk(pattern, "?*[");
+ if (!has_glob_specials) {
+ /* Append impiled '/' '*' if not present. */
+ if (real_pattern.buf[real_pattern.len - 1] != '/')
+ strbuf_addch(&real_pattern, '/');
+ /* No need to check for '*', there is none. */
+ strbuf_addch(&real_pattern, '*');
+ }
+
+ filter.pattern = real_pattern.buf;
+ filter.fn = fn;
+ filter.cb_data = cb_data;
+ ret = for_each_ref(filter_refs, &filter);
+
+ strbuf_release(&real_pattern);
+ return ret;
+}
+
+int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+{
+ return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
+}
+
int for_each_rawref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref("refs/", fn, 0,