@matheusbsbs / matheus-bagliano / commits / 32c35cfb1e
Fork 0

git-tag: Add --contains option

This functions similarly to "git branch --contains"; it will show all tags that contain the specified commit, by sharing the same logic. The patch also adds documentation and tests for the new option. Signed-off-by: Jake Goulding <goulding@vivisimo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jake Goulding committed Jan 26, 2009 at 09:13 UTC 32c35cfb1e9c8523b9d60e5095f1c49ebaef0279
3 files changed +146 -3
Documentation/git-tag.txt
+4 -1
@@ -12,7 +12,7 @@ SYNOPSIS
12 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
13 <name> [<commit> | <object>]
14 'git tag' -d <name>...
15 -'git tag' [-n[<num>]] -l [<pattern>]
15 +'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
16 'git tag' -v <name>...
17
18 DESCRIPTION
@@ -68,6 +68,9 @@ OPTIONS
68 List tags with names that match the given pattern (or all if no pattern is given).
69 Typing "git tag" without arguments, also lists all tags.
70
71 +--contains <commit>::
72 + Only list tags which contain the specified commit.
73 +
74 -m <msg>::
75 Use the given tag message (instead of prompting).
76 If multiple `-m` options are given, their values are
builtin-tag.c
+27 -2
@@ -26,6 +26,7 @@ static char signingkey[1000];
26 struct tag_filter {
27 const char *pattern;
28 int lines;
29 + struct commit_list *with_commit;
30 };
31
32 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
@@ -42,6 +43,16 @@ static int show_reference(const char *refname, const unsigned char *sha1,
43 char *buf, *sp, *eol;
44 size_t len;
45
46 + if (filter->with_commit) {
47 + struct commit *commit;
48 +
49 + commit = lookup_commit_reference_gently(sha1, 1);
50 + if (!commit)
51 + return 0;
52 + if (!is_descendant_of(commit, filter->with_commit))
53 + return 0;
54 + }
55 +
56 if (!filter->lines) {
57 printf("%s\n", refname);
58 return 0;
@@ -79,7 +90,8 @@ static int show_reference(const char *refname, const unsigned char *sha1,
90 return 0;
91 }
92
82 -static int list_tags(const char *pattern, int lines)
93 +static int list_tags(const char *pattern, int lines,
94 + struct commit_list *with_commit)
95 {
96 struct tag_filter filter;
97
@@ -88,6 +100,7 @@ static int list_tags(const char *pattern, int lines)
100
101 filter.pattern = pattern;
102 filter.lines = lines;
103 + filter.with_commit = with_commit;
104
105 for_each_tag_ref(show_reference, (void *) &filter);
106
@@ -360,6 +373,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
373 list = 0, delete = 0, verify = 0;
374 const char *msgfile = NULL, *keyid = NULL;
375 struct msg_arg msg = { 0, STRBUF_INIT };
376 + struct commit_list *with_commit = NULL;
377 struct option options[] = {
378 OPT_BOOLEAN('l', NULL, &list, "list tag names"),
379 { OPTION_INTEGER, 'n', NULL, &lines, NULL,
@@ -378,6 +392,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
392 OPT_STRING('u', NULL, &keyid, "key-id",
393 "use another key to sign the tag"),
394 OPT_BOOLEAN('f', NULL, &force, "replace the tag if exists"),
395 +
396 + OPT_GROUP("Tag listing options"),
397 + {
398 + OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
399 + "print only tags that contain the commit",
400 + PARSE_OPT_LASTARG_DEFAULT,
401 + parse_opt_with_commit, (intptr_t)"HEAD",
402 + },
403 OPT_END()
404 };
405
@@ -402,9 +424,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
424 if (list + delete + verify > 1)
425 usage_with_options(git_tag_usage, options);
426 if (list)
405 - return list_tags(argv[0], lines == -1 ? 0 : lines);
427 + return list_tags(argv[0], lines == -1 ? 0 : lines,
428 + with_commit);
429 if (lines != -1)
430 die("-n option is only allowed with -l.");
431 + if (with_commit)
432 + die("--contains option is only allowed with -l.");
433 if (delete)
434 return for_each_tag_name(argv, delete_tag);
435 if (verify)
t/t7004-tag.sh
+115
@@ -1090,6 +1090,121 @@ test_expect_success 'filename for the message is relative to cwd' '
1090 git cat-file tag tag-from-subdir-2 | grep "in sub directory"
1091 '
1092
1093 +# create a few more commits to test --contains
1094 +
1095 +hash1=$(git rev-parse HEAD)
1096 +
1097 +test_expect_success 'creating second commit and tag' '
1098 + echo foo-2.0 >foo &&
1099 + git add foo &&
1100 + git commit -m second
1101 + git tag v2.0
1102 +'
1103 +
1104 +hash2=$(git rev-parse HEAD)
1105 +
1106 +test_expect_success 'creating third commit without tag' '
1107 + echo foo-dev >foo &&
1108 + git add foo &&
1109 + git commit -m third
1110 +'
1111 +
1112 +hash3=$(git rev-parse HEAD)
1113 +
1114 +# simple linear checks of --continue
1115 +
1116 +cat > expected <<EOF
1117 +v0.2.1
1118 +v1.0
1119 +v1.0.1
1120 +v1.1.3
1121 +v2.0
1122 +EOF
1123 +
1124 +test_expect_success 'checking that first commit is in all tags (hash)' "
1125 + git tag -l --contains $hash1 v* >actual
1126 + test_cmp expected actual
1127 +"
1128 +
1129 +# other ways of specifying the commit
1130 +test_expect_success 'checking that first commit is in all tags (tag)' "
1131 + git tag -l --contains v1.0 v* >actual
1132 + test_cmp expected actual
1133 +"
1134 +
1135 +test_expect_success 'checking that first commit is in all tags (relative)' "
1136 + git tag -l --contains HEAD~2 v* >actual
1137 + test_cmp expected actual
1138 +"
1139 +
1140 +cat > expected <<EOF
1141 +v2.0
1142 +EOF
1143 +
1144 +test_expect_success 'checking that second commit only has one tag' "
1145 + git tag -l --contains $hash2 v* >actual
1146 + test_cmp expected actual
1147 +"
1148 +
1149 +
1150 +cat > expected <<EOF
1151 +EOF
1152 +
1153 +test_expect_success 'checking that third commit has no tags' "
1154 + git tag -l --contains $hash3 v* >actual
1155 + test_cmp expected actual
1156 +"
1157 +
1158 +# how about a simple merge?
1159 +
1160 +test_expect_success 'creating simple branch' '
1161 + git branch stable v2.0 &&
1162 + git checkout stable &&
1163 + echo foo-3.0 > foo &&
1164 + git commit foo -m fourth
1165 + git tag v3.0
1166 +'
1167 +
1168 +hash4=$(git rev-parse HEAD)
1169 +
1170 +cat > expected <<EOF
1171 +v3.0
1172 +EOF
1173 +
1174 +test_expect_success 'checking that branch head only has one tag' "
1175 + git tag -l --contains $hash4 v* >actual
1176 + test_cmp expected actual
1177 +"
1178 +
1179 +test_expect_success 'merging original branch into this branch' '
1180 + git merge --strategy=ours master &&
1181 + git tag v4.0
1182 +'
1183 +
1184 +cat > expected <<EOF
1185 +v4.0
1186 +EOF
1187 +
1188 +test_expect_success 'checking that original branch head has one tag now' "
1189 + git tag -l --contains $hash3 v* >actual
1190 + test_cmp expected actual
1191 +"
1192 +
1193 +cat > expected <<EOF
1194 +v0.2.1
1195 +v1.0
1196 +v1.0.1
1197 +v1.1.3
1198 +v2.0
1199 +v3.0
1200 +v4.0
1201 +EOF
1202 +
1203 +test_expect_success 'checking that initial commit is in all tags' "
1204 + git tag -l --contains $hash1 v* >actual
1205 + test_cmp expected actual
1206 +"
1207 +
1208 # mixing modes and options:
1209
1210 test_expect_success 'mixing incompatibles modes and options is forbidden' '