This filters the list for annotated|signed tags of the given object. Example, john$ git tag -s v1.0-john v1.0 john$ git tag -l --points-at v1.0 v1.0-john Signed-off-by: Tom Grennan <tmgrennan@xxxxxxxxx> --- Documentation/git-tag.txt | 5 +++- builtin/tag.c | 59 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 53ff5f6..b9ec75c 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>] 'git tag' -d <tagname>... -'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>...] +'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>] [<pattern>...] 'git tag' -v <tagname>... DESCRIPTION @@ -86,6 +86,9 @@ OPTIONS --contains <commit>:: Only list tags which contain the specified commit. +--points-at <object>:: + Only list annotated or signed tags of the given object. + -m <msg>:: --message=<msg>:: Use the given tag message (instead of prompting). diff --git a/builtin/tag.c b/builtin/tag.c index 31f02e8..7568d6c 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -19,7 +19,8 @@ static const char * const git_tag_usage[] = { "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", "git tag -d <tagname>...", - "git tag -l [-n[<num>]] [<pattern>...]", + "git tag -l [-n[<num>]] [<pattern>...] \\\n\t\t" + "[--contains <commit>] [--points-at <object>]", "git tag -v <tagname>...", NULL }; @@ -28,6 +29,7 @@ struct tag_filter { const char **patterns; int lines; struct commit_list *with_commit; + const unsigned char *points_at; }; static int match_pattern(const char **patterns, const char *ref) @@ -105,16 +107,28 @@ static int show_reference(const char *refname, const unsigned char *sha1, return 0; } + buf = read_sha1_file(sha1, &type, &size); + if (!buf || !size) + return 0; + + if (filter->points_at) { + unsigned char tagged_sha1[20]; + if (memcmp("object ", buf, 7) \ + || buf[47] != '\n' \ + || get_sha1_hex(buf + 7, tagged_sha1) \ + || memcmp(filter->points_at, tagged_sha1, 20)) { + free(buf); + return 0; + } + } + if (!filter->lines) { printf("%s\n", refname); + free(buf); return 0; } printf("%-15s ", refname); - buf = read_sha1_file(sha1, &type, &size); - if (!buf || !size) - return 0; - /* skip header */ sp = strstr(buf, "\n\n"); if (!sp) { @@ -143,16 +157,20 @@ static int show_reference(const char *refname, const unsigned char *sha1, } static int list_tags(const char **patterns, int lines, - struct commit_list *with_commit) + struct commit_list *with_commit, + unsigned char *points_at) { struct tag_filter filter; filter.patterns = patterns; filter.lines = lines; filter.with_commit = with_commit; + filter.points_at = points_at; for_each_tag_ref(show_reference, (void *) &filter); + if (points_at) + free(points_at); return 0; } @@ -375,12 +393,28 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name) return check_refname_format(sb->buf, 0); } +int parse_opt_points_at(const struct option *opt, const char *arg, int unset) +{ + unsigned char *sha1; + + if (!arg) + return -1; + sha1 = xmalloc(20); + if (get_sha1(arg, sha1)) { + free(sha1); + return error("malformed object name %s", arg); + } + *(unsigned char **)opt->value = sha1; + return 0; +} + int cmd_tag(int argc, const char **argv, const char *prefix) { struct strbuf buf = STRBUF_INIT; struct strbuf ref = STRBUF_INIT; unsigned char object[20], prev[20]; const char *object_ref, *tag; + unsigned char *points_at; struct ref_lock *lock; struct create_tag_options opt; char *cleanup_arg = NULL; @@ -417,6 +451,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix) PARSE_OPT_LASTARG_DEFAULT, parse_opt_with_commit, (intptr_t)"HEAD", }, + { + OPTION_CALLBACK, 0, "points-at", &points_at, "object", + "print only annotated|signed tags of the object", + PARSE_OPT_LASTARG_DEFAULT, + parse_opt_points_at, (intptr_t)"HEAD", + }, OPT_END() }; @@ -443,11 +483,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix) usage_with_options(git_tag_usage, options); if (list) return list_tags(argv, lines == -1 ? 0 : lines, - with_commit); + with_commit, points_at); if (lines != -1) die(_("-n option is only allowed with -l.")); - if (with_commit) - die(_("--contains option is only allowed with -l.")); + if (with_commit || points_at) + die(_("--contains and --points-at options " + "are only allowed with -l.")); if (delete) return for_each_tag_name(argv, delete_tag); if (verify) -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html