rev-parse --glob

Add --glob=<glob-pattern> option to rev-parse and everything that
accepts its options. This option matches all refs that match given
shell glob pattern (complete with some DWIM logic).

Example:

'git log --branches --not --glob=remotes/origin'

To show what you have that origin doesn't.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ilari Liusvaara
2010-01-20 11:48:25 +02:00
committed by Junio C Hamano
parent 5b15950ac4
commit d08bae7e22
9 changed files with 223 additions and 2 deletions

45
refs.c
View File

@ -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,35 @@ 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(each_ref_fn fn, const char *pattern, void *cb_data)
{
struct strbuf real_pattern = STRBUF_INIT;
struct ref_filter filter;
const char *has_glob_specials;
int ret;
if (prefixcmp(pattern, "refs/"))
strbuf_addstr(&real_pattern, "refs/");
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_rawref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref("refs/", fn, 0,