Always perfer annotated tags in git-describe.
[git/git.git] / builtin-describe.c
CommitLineData
908e5310
LT
1#include "cache.h"
2#include "commit.h"
635d4134 3#include "tag.h"
908e5310 4#include "refs.h"
80dbae03
SP
5#include "diff.h"
6#include "diffcore.h"
7#include "revision.h"
9a0eaf83 8#include "builtin.h"
908e5310 9
2d9e7c9f
JH
10static const char describe_usage[] =
11"git-describe [--all] [--tags] [--abbrev=<n>] <committish>*";
908e5310 12
96f1e58f
DR
13static int all; /* Default to annotated tags only */
14static int tags; /* But allow any tags if --tags is specified */
2d9e7c9f 15
2d9e7c9f 16static int abbrev = DEFAULT_ABBREV;
908e5310 17
96f1e58f 18static int names, allocs;
908e5310 19static struct commit_name {
80dbae03 20 struct commit *commit;
64deb858 21 int prio; /* annotated tag = 2, tag = 1, head = 0 */
5a2282de 22 char path[FLEX_ARRAY]; /* more */
908e5310
LT
23} **name_array = NULL;
24
25static struct commit_name *match(struct commit *cmit)
26{
27 int i = names;
28 struct commit_name **p = name_array;
29
30 while (i-- > 0) {
31 struct commit_name *n = *p++;
32 if (n->commit == cmit)
33 return n;
34 }
35 return NULL;
36}
37
64deb858 38static void add_to_known_names(const char *path,
80dbae03 39 struct commit *commit,
64deb858 40 int prio)
908e5310
LT
41{
42 int idx;
43 int len = strlen(path)+1;
44 struct commit_name *name = xmalloc(sizeof(struct commit_name) + len);
45
46 name->commit = commit;
f7122265 47 name->prio = prio;
908e5310
LT
48 memcpy(name->path, path, len);
49 idx = names;
50 if (idx >= allocs) {
51 allocs = (idx + 50) * 3 / 2;
52 name_array = xrealloc(name_array, allocs*sizeof(*name_array));
53 }
54 name_array[idx] = name;
55 names = ++idx;
56}
57
8da19775 58static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
908e5310
LT
59{
60 struct commit *commit = lookup_commit_reference_gently(sha1, 1);
64deb858
JH
61 struct object *object;
62 int prio;
63
908e5310
LT
64 if (!commit)
65 return 0;
64deb858 66 object = parse_object(sha1);
2d9e7c9f
JH
67 /* If --all, then any refs are used.
68 * If --tags, then any tags are used.
69 * Otherwise only annotated tags are used.
70 */
64deb858 71 if (!strncmp(path, "refs/tags/", 10)) {
1974632c 72 if (object->type == OBJ_TAG)
64deb858
JH
73 prio = 2;
74 else
75 prio = 1;
76 }
77 else
78 prio = 0;
79
635d4134 80 if (!all) {
64deb858
JH
81 if (!prio)
82 return 0;
83 if (!tags && prio < 2)
635d4134 84 return 0;
635d4134 85 }
64deb858 86 add_to_known_names(all ? path + 5 : path + 10, commit, prio);
908e5310
LT
87 return 0;
88}
89
90static int compare_names(const void *_a, const void *_b)
91{
92 struct commit_name *a = *(struct commit_name **)_a;
93 struct commit_name *b = *(struct commit_name **)_b;
94 unsigned long a_date = a->commit->date;
95 unsigned long b_date = b->commit->date;
64deb858
JH
96
97 if (a->prio != b->prio)
98 return b->prio - a->prio;
908e5310
LT
99 return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
100}
101
80dbae03
SP
102struct possible_tag {
103 struct possible_tag *next;
104 struct commit_name *name;
105 unsigned long depth;
106};
107
554fe20d 108static void describe(const char *arg, int last_one)
908e5310 109{
4c34a2c5
JH
110 unsigned char sha1[20];
111 struct commit *cmit;
908e5310
LT
112 struct commit_list *list;
113 static int initialized = 0;
114 struct commit_name *n;
80dbae03 115 struct possible_tag *all_matches, *min_match, *cur_match;
908e5310 116
31fff305
DL
117 if (get_sha1(arg, sha1))
118 die("Not a valid object name %s", arg);
4c34a2c5
JH
119 cmit = lookup_commit_reference(sha1);
120 if (!cmit)
31fff305 121 die("%s is not a valid '%s' object", arg, commit_type);
4c34a2c5 122
908e5310
LT
123 if (!initialized) {
124 initialized = 1;
cb5d709f 125 for_each_ref(get_name, NULL);
908e5310
LT
126 qsort(name_array, names, sizeof(*name_array), compare_names);
127 }
128
129 n = match(cmit);
130 if (n) {
131 printf("%s\n", n->path);
132 return;
133 }
134
135 list = NULL;
80dbae03
SP
136 all_matches = NULL;
137 cur_match = NULL;
908e5310
LT
138 commit_list_insert(cmit, &list);
139 while (list) {
80dbae03 140 struct commit *c = pop_commit(&list);
dccd0c2a 141 struct commit_list *parents = c->parents;
908e5310
LT
142 n = match(c);
143 if (n) {
80dbae03
SP
144 struct possible_tag *p = xmalloc(sizeof(*p));
145 p->name = n;
146 p->next = NULL;
147 if (cur_match)
148 cur_match->next = p;
149 else
150 all_matches = p;
151 cur_match = p;
dccd0c2a
SP
152 if (n->prio == 2)
153 continue;
154 }
155 while (parents) {
156 struct commit *p = parents->item;
157 parse_commit(p);
158 if (!(p->object.flags & SEEN)) {
159 p->object.flags |= SEEN;
160 insert_by_date(p, &list);
80dbae03 161 }
dccd0c2a 162 parents = parents->next;
80dbae03
SP
163 }
164 }
165
166 if (!all_matches)
167 die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1));
168
169 min_match = NULL;
170 for (cur_match = all_matches; cur_match; cur_match = cur_match->next) {
171 struct rev_info revs;
172 struct commit *tagged = cur_match->name->commit;
173
174 clear_commit_marks(cmit, -1);
175 init_revisions(&revs, NULL);
176 tagged->object.flags |= UNINTERESTING;
177 add_pending_object(&revs, &tagged->object, NULL);
178 add_pending_object(&revs, &cmit->object, NULL);
179
180 prepare_revision_walk(&revs);
181 cur_match->depth = 0;
182 while ((!min_match || cur_match->depth < min_match->depth)
183 && get_revision(&revs))
184 cur_match->depth++;
dccd0c2a
SP
185 if (!min_match || (cur_match->depth < min_match->depth
186 && cur_match->name->prio >= min_match->name->prio))
80dbae03 187 min_match = cur_match;
94d23673 188 free_commit_list(revs.commits);
80dbae03
SP
189 }
190 printf("%s-g%s\n", min_match->name->path,
191 find_unique_abbrev(cmit->object.sha1, abbrev));
192
193 if (!last_one) {
194 for (cur_match = all_matches; cur_match; cur_match = min_match) {
195 min_match = cur_match->next;
196 free(cur_match);
908e5310 197 }
80dbae03 198 clear_commit_marks(cmit, SEEN);
908e5310
LT
199 }
200}
201
9a0eaf83 202int cmd_describe(int argc, const char **argv, const char *prefix)
908e5310
LT
203{
204 int i;
205
206 for (i = 1; i < argc; i++) {
207 const char *arg = argv[i];
908e5310 208
4c34a2c5
JH
209 if (*arg != '-')
210 break;
211 else if (!strcmp(arg, "--all"))
908e5310 212 all = 1;
4c34a2c5 213 else if (!strcmp(arg, "--tags"))
2d9e7c9f 214 tags = 1;
4c34a2c5 215 else if (!strncmp(arg, "--abbrev=", 9)) {
2d9e7c9f 216 abbrev = strtoul(arg + 9, NULL, 10);
f7122265 217 if (abbrev < MINIMUM_ABBREV || 40 < abbrev)
2d9e7c9f 218 abbrev = DEFAULT_ABBREV;
2d9e7c9f 219 }
4c34a2c5 220 else
908e5310 221 usage(describe_usage);
908e5310 222 }
4c34a2c5 223
8c599c74 224 save_commit_buffer = 0;
8112894d 225
5b6df8e4 226 if (argc <= i)
fec9ebf1 227 describe("HEAD", 1);
4c34a2c5 228 else
fec9ebf1
JH
229 while (i < argc) {
230 describe(argv[i], (i == argc - 1));
231 i++;
232 }
4c34a2c5 233
908e5310
LT
234 return 0;
235}