diff options
author | Namhyung Kim <namhyung.kim@lge.com> | 2013-06-18 21:35:31 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-06-18 12:02:02 -0700 |
commit | 98c5c4ad01551b7764c9c8d8f67abfa9c5e595fe (patch) | |
tree | 39878887f07de4058c8b67f8690d056fc97611d5 /builtin/name-rev.c | |
parent | edca4152560522a431a51fc0a06147fc680b5b18 (diff) | |
download | git-98c5c4ad01551b7764c9c8d8f67abfa9c5e595fe.tar.gz git-98c5c4ad01551b7764c9c8d8f67abfa9c5e595fe.tar.xz |
name-rev: allow to specify a subpath for --refs option
When an user wants to filter specific ref using the --refs option,
the pattern needs to match the full ref, e.g. --refs=refs/tags/v1.*.
It'd be convenient to specify a subpath of ref pattern. For
example, --refs=origin/* can find refs/remotes/origin/master by
searching the pattern against its substrings in turn:
refs/remotes/origin/master
remotes/origin/master
origin/master
If it finds a match in a subpath, unambigous part of the ref path will
be removed in the output.
Signed-off-by: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/name-rev.c')
-rw-r--r-- | builtin/name-rev.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 623824797..87d485496 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -82,6 +82,20 @@ copy_data: } } +static int subpath_matches(const char *path, const char *filter) +{ + const char *subpath = path; + + while (subpath) { + if (!fnmatch(filter, subpath, 0)) + return subpath - path; + subpath = strchr(subpath, '/'); + if (subpath) + subpath++; + } + return -1; +} + struct name_ref_data { int tags_only; int name_only; @@ -92,13 +106,23 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void { struct object *o = parse_object(sha1); struct name_ref_data *data = cb_data; + int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; if (data->tags_only && prefixcmp(path, "refs/tags/")) return 0; - if (data->ref_filter && fnmatch(data->ref_filter, path, 0)) - return 0; + if (data->ref_filter) { + switch (subpath_matches(path, data->ref_filter)) { + case -1: /* did not match */ + return 0; + case 0: /* matched fully */ + break; + default: /* matched subpath */ + can_abbreviate_output = 1; + break; + } + } while (o && o->type == OBJ_TAG) { struct tag *t = (struct tag *) o; @@ -110,12 +134,10 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void if (o && o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; - if (!prefixcmp(path, "refs/heads/")) + if (can_abbreviate_output) + path = shorten_unambiguous_ref(path, 0); + else if (!prefixcmp(path, "refs/heads/")) path = path + 11; - else if (data->tags_only - && data->name_only - && !prefixcmp(path, "refs/tags/")) - path = path + 10; else if (!prefixcmp(path, "refs/")) path = path + 5; |