Skip to content

Commit 212945d

Browse files
spearcegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6d21667 commit 212945d

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

builtin-describe.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ static int max_candidates = 10;
2222
const char *pattern = NULL;
2323

2424
struct commit_name {
25+
struct tag *tag;
2526
int prio; /* annotated tag = 2, tag = 1, head = 0 */
27+
unsigned char sha1[20];
2628
char path[FLEX_ARRAY]; /* more */
2729
};
2830
static const char *prio_names[] = {
@@ -31,14 +33,17 @@ static const char *prio_names[] = {
3133

3234
static void add_to_known_names(const char *path,
3335
struct commit *commit,
34-
int prio)
36+
int prio,
37+
const unsigned char *sha1)
3538
{
3639
struct commit_name *e = commit->util;
3740
if (!e || e->prio < prio) {
3841
size_t len = strlen(path)+1;
3942
free(e);
4043
e = xmalloc(sizeof(struct commit_name) + len);
44+
e->tag = NULL;
4145
e->prio = prio;
46+
hashcpy(e->sha1, sha1);
4247
memcpy(e->path, path, len);
4348
commit->util = e;
4449
}
@@ -89,7 +94,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
8994
if (!tags && prio < 2)
9095
return 0;
9196
}
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);
9398
return 0;
9499
}
95100

@@ -146,6 +151,22 @@ static unsigned long finish_depth_computation(
146151
return seen_commits;
147152
}
148153

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+
149170
static void describe(const char *arg, int last_one)
150171
{
151172
unsigned char sha1[20];
@@ -170,7 +191,8 @@ static void describe(const char *arg, int last_one)
170191

171192
n = cmit->util;
172193
if (n) {
173-
printf("%s\n", n->path);
194+
display_name(n);
195+
printf("\n");
174196
return;
175197
}
176198

@@ -252,12 +274,12 @@ static void describe(const char *arg, int last_one)
252274
sha1_to_hex(gave_up_on->object.sha1));
253275
}
254276
}
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,
260281
find_unique_abbrev(cmit->object.sha1, abbrev));
282+
printf("\n");
261283

262284
if (!last_one)
263285
clear_commit_marks(cmit, -1);

0 commit comments

Comments
 (0)