@matheusbsbs / matheus-bagliano / commits / 212945d4a8
Fork 0

Teach git-describe to verify annotated tag names before output

If an annotated tag describes a commit we want to favor the name listed in the body of the tag, rather than whatever name it has been stored under locally. By doing so it is easier to converse about tags with others, even if the tags happen to be fetched to a different name than it was given by its creator. To avoid confusion when a tag is stored under a different name (and thus is not readable via git-rev-parse --verify, etc.) we show a warning message if the name of the tag does not match the ref we found it under and if that tag was also selected for output. For example: $ git tag -a -m "i am a test" testtag $ mv .git/refs/tags/testtag .git/refs/tags/bobbytag $ ./git-describe HEAD warning: tag 'testtag' is really 'bobbytag' here testtag $ git tag -d testtag error: tag 'testtag' not found. $ git tag -d bobbytag Deleted tag 'bobbytag' Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Shawn O. Pearce committed Feb 28, 2008 at 01:22 UTC 212945d4a85dfa172ea55ec73b1d830ef2d8582f
1 file changed +30 -8
builtin-describe.c
+30 -8
@@ -22,7 +22,9 @@ static int max_candidates = 10;
22 const char *pattern = NULL;
23
24 struct commit_name {
25 + struct tag *tag;
26 int prio; /* annotated tag = 2, tag = 1, head = 0 */
27 + unsigned char sha1[20];
28 char path[FLEX_ARRAY]; /* more */
29 };
30 static const char *prio_names[] = {
@@ -31,14 +33,17 @@ static const char *prio_names[] = {
33
34 static void add_to_known_names(const char *path,
35 struct commit *commit,
34 - int prio)
36 + int prio,
37 + const unsigned char *sha1)
38 {
39 struct commit_name *e = commit->util;
40 if (!e || e->prio < prio) {
41 size_t len = strlen(path)+1;
42 free(e);
43 e = xmalloc(sizeof(struct commit_name) + len);
44 + e->tag = NULL;
45 e->prio = prio;
46 + hashcpy(e->sha1, sha1);
47 memcpy(e->path, path, len);
48 commit->util = e;
49 }
@@ -89,7 +94,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
94 if (!tags && prio < 2)
95 return 0;
96 }
92 - add_to_known_names(all ? path + 5 : path + 10, commit, prio);
97 + add_to_known_names(all ? path + 5 : path + 10, commit, prio, sha1);
98 return 0;
99 }
100
@@ -146,6 +151,22 @@ static unsigned long finish_depth_computation(
151 return seen_commits;
152 }
153
154 +static void display_name(struct commit_name *n)
155 +{
156 + if (n->prio == 2 && !n->tag) {
157 + n->tag = lookup_tag(n->sha1);
158 + if (!n->tag || !n->tag->tag)
159 + die("annotated tag %s not available", n->path);
160 + if (strcmp(n->tag->tag, n->path))
161 + warning("tag '%s' is really '%s' here", n->tag->tag, n->path);
162 + }
163 +
164 + if (n->tag)
165 + printf("%s", n->tag->tag);
166 + else
167 + printf("%s", n->path);
168 +}
169 +
170 static void describe(const char *arg, int last_one)
171 {
172 unsigned char sha1[20];
@@ -170,7 +191,8 @@ static void describe(const char *arg, int last_one)
191
192 n = cmit->util;
193 if (n) {
173 - printf("%s\n", n->path);
194 + display_name(n);
195 + printf("\n");
196 return;
197 }
198
@@ -252,12 +274,12 @@ static void describe(const char *arg, int last_one)
274 sha1_to_hex(gave_up_on->object.sha1));
275 }
276 }
255 - if (abbrev == 0)
256 - printf("%s\n", all_matches[0].name->path );
257 - else
258 - printf("%s-%d-g%s\n", all_matches[0].name->path,
259 - all_matches[0].depth,
277 +
278 + display_name(all_matches[0].name);
279 + if (abbrev)
280 + printf("-%d-g%s", all_matches[0].depth,
281 find_unique_abbrev(cmit->object.sha1, abbrev));
282 + printf("\n");
283
284 if (!last_one)
285 clear_commit_marks(cmit, -1);