247
struct tip_table_entry {
248
struct object_id oid;
249
const char *refname;
250
+ struct commit *commit;
251
+ timestamp_t taggerdate;
252
+ unsigned int from_tag:1;
253
+ unsigned int deref:1;
254
} *table;
255
int nr;
256
int alloc;
258
} tip_table;
259
260
static void add_to_tip_table(const struct object_id *oid, const char *refname,
257
- int shorten_unambiguous)
261
+ int shorten_unambiguous, struct commit *commit,
262
+ timestamp_t taggerdate, int from_tag, int deref)
263
{
264
refname = name_ref_abbrev(refname, shorten_unambiguous);
265
266
ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
267
oidcpy(&tip_table.table[tip_table.nr].oid, oid);
268
tip_table.table[tip_table.nr].refname = xstrdup(refname);
269
+ tip_table.table[tip_table.nr].commit = commit;
270
+ tip_table.table[tip_table.nr].taggerdate = taggerdate;
271
+ tip_table.table[tip_table.nr].from_tag = from_tag;
272
+ tip_table.table[tip_table.nr].deref = deref;
273
tip_table.nr++;
274
tip_table.sorted = 0;
275
}
280
return oidcmp(&a->oid, &b->oid);
281
}
282
283
+static int cmp_by_tag_and_age(const void *a_, const void *b_)
284
+{
285
+ const struct tip_table_entry *a = a_, *b = b_;
286
+ int cmp;
287
+
288
+ /* Prefer tags. */
289
+ cmp = b->from_tag - a->from_tag;
290
+ if (cmp)
291
+ return cmp;
292
+
293
+ /* Older is better. */
294
+ if (a->taggerdate < b->taggerdate)
295
+ return -1;
296
+ return a->taggerdate != b->taggerdate;
297
+}
298
+
299
static int name_ref(const char *path, const struct object_id *oid, int flags, void *cb_data)
300
{
301
struct object *o = parse_object(the_repository, oid);
302
struct name_ref_data *data = cb_data;
303
int can_abbreviate_output = data->tags_only && data->name_only;
304
int deref = 0;
305
+ int from_tag = 0;
306
+ struct commit *commit = NULL;
307
timestamp_t taggerdate = TIME_MAX;
308
309
if (data->tags_only && !starts_with(path, "refs/tags/"))
352
return 0;
353
}
354
328
- add_to_tip_table(oid, path, can_abbreviate_output);
329
-
355
while (o && o->type == OBJ_TAG) {
356
struct tag *t = (struct tag *) o;
357
if (!t->tagged)
361
taggerdate = t->date;
362
}
363
if (o && o->type == OBJ_COMMIT) {
339
- struct commit *commit = (struct commit *)o;
340
- int from_tag = starts_with(path, "refs/tags/");
341
-
364
+ commit = (struct commit *)o;
365
+ from_tag = starts_with(path, "refs/tags/");
366
if (taggerdate == TIME_MAX)
367
taggerdate = commit->date;
344
- path = name_ref_abbrev(path, can_abbreviate_output);
345
- name_rev(commit, path, taggerdate, from_tag, deref);
368
}
369
+
370
+ add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
371
+ from_tag, deref);
372
return 0;
373
}
374
375
+static void name_tips(void)
376
+{
377
+ int i;
378
+
379
+ /*
380
+ * Try to set better names first, so that worse ones spread
381
+ * less.
382
+ */
383
+ QSORT(tip_table.table, tip_table.nr, cmp_by_tag_and_age);
384
+ for (i = 0; i < tip_table.nr; i++) {
385
+ struct tip_table_entry *e = &tip_table.table[i];
386
+ if (e->commit) {
387
+ name_rev(e->commit, e->refname, e->taggerdate,
388
+ e->from_tag, e->deref);
389
+ }
390
+ }
391
+}
392
+
393
static const unsigned char *nth_tip_table_ent(size_t ix, void *table_)
394
{
395
struct tip_table_entry *table = table_;
602
cutoff = TIME_MIN;
603
}
604
for_each_ref(name_ref, &data);
605
+ name_tips();
606
607
if (transform_stdin) {
608
char buffer[2048];