Coverage Report

Created: 2024-09-08 06:23

/src/git/builtin/name-rev.c
Line
Count
Source (jump to first uncovered line)
1
#include "builtin.h"
2
#include "environment.h"
3
#include "gettext.h"
4
#include "hex.h"
5
#include "repository.h"
6
#include "config.h"
7
#include "commit.h"
8
#include "tag.h"
9
#include "refs.h"
10
#include "object-name.h"
11
#include "pager.h"
12
#include "parse-options.h"
13
#include "prio-queue.h"
14
#include "hash-lookup.h"
15
#include "commit-slab.h"
16
#include "commit-graph.h"
17
#include "wildmatch.h"
18
#include "mem-pool.h"
19
20
/*
21
 * One day.  See the 'name a rev shortly after epoch' test in t6120 when
22
 * changing this value
23
 */
24
0
#define CUTOFF_DATE_SLOP 86400
25
26
struct rev_name {
27
  const char *tip_name;
28
  timestamp_t taggerdate;
29
  int generation;
30
  int distance;
31
  int from_tag;
32
};
33
34
define_commit_slab(commit_rev_name, struct rev_name);
35
36
static timestamp_t generation_cutoff = GENERATION_NUMBER_INFINITY;
37
static timestamp_t cutoff = TIME_MAX;
38
static struct commit_rev_name rev_names;
39
40
/* Disable the cutoff checks entirely */
41
static void disable_cutoff(void)
42
0
{
43
0
  generation_cutoff = 0;
44
0
  cutoff = 0;
45
0
}
46
47
/* Cutoff searching any commits older than this one */
48
static void set_commit_cutoff(struct commit *commit)
49
0
{
50
51
0
  if (cutoff > commit->date)
52
0
    cutoff = commit->date;
53
54
0
  if (generation_cutoff) {
55
0
    timestamp_t generation = commit_graph_generation(commit);
56
57
0
    if (generation_cutoff > generation)
58
0
      generation_cutoff = generation;
59
0
  }
60
0
}
61
62
/* adjust the commit date cutoff with a slop to allow for slightly incorrect
63
 * commit timestamps in case of clock skew.
64
 */
65
static void adjust_cutoff_timestamp_for_slop(void)
66
0
{
67
0
  if (cutoff) {
68
    /* check for undeflow */
69
0
    if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
70
0
      cutoff = cutoff - CUTOFF_DATE_SLOP;
71
0
    else
72
0
      cutoff = TIME_MIN;
73
0
  }
74
0
}
75
76
/* Check if a commit is before the cutoff. Prioritize generation numbers
77
 * first, but use the commit timestamp if we lack generation data.
78
 */
79
static int commit_is_before_cutoff(struct commit *commit)
80
0
{
81
0
  if (generation_cutoff < GENERATION_NUMBER_INFINITY)
82
0
    return generation_cutoff &&
83
0
      commit_graph_generation(commit) < generation_cutoff;
84
85
0
  return commit->date < cutoff;
86
0
}
87
88
/* How many generations are maximally preferred over _one_ merge traversal? */
89
0
#define MERGE_TRAVERSAL_WEIGHT 65535
90
91
static int is_valid_rev_name(const struct rev_name *name)
92
0
{
93
0
  return name && name->tip_name;
94
0
}
95
96
static struct rev_name *get_commit_rev_name(const struct commit *commit)
97
0
{
98
0
  struct rev_name *name = commit_rev_name_peek(&rev_names, commit);
99
100
0
  return is_valid_rev_name(name) ? name : NULL;
101
0
}
102
103
static int effective_distance(int distance, int generation)
104
0
{
105
0
  return distance + (generation > 0 ? MERGE_TRAVERSAL_WEIGHT : 0);
106
0
}
107
108
static int is_better_name(struct rev_name *name,
109
        timestamp_t taggerdate,
110
        int generation,
111
        int distance,
112
        int from_tag)
113
0
{
114
0
  int name_distance = effective_distance(name->distance, name->generation);
115
0
  int new_distance = effective_distance(distance, generation);
116
117
  /* If both are tags, we prefer the nearer one. */
118
0
  if (from_tag && name->from_tag)
119
0
    return name_distance > new_distance;
120
121
  /* Favor a tag over a non-tag. */
122
0
  if (name->from_tag != from_tag)
123
0
    return from_tag;
124
125
  /*
126
   * We are now looking at two non-tags.  Tiebreak to favor
127
   * shorter hops.
128
   */
129
0
  if (name_distance != new_distance)
130
0
    return name_distance > new_distance;
131
132
  /* ... or tiebreak to favor older date */
133
0
  if (name->taggerdate != taggerdate)
134
0
    return name->taggerdate > taggerdate;
135
136
  /* keep the current one if we cannot decide */
137
0
  return 0;
138
0
}
139
140
static struct rev_name *create_or_update_name(struct commit *commit,
141
                timestamp_t taggerdate,
142
                int generation, int distance,
143
                int from_tag)
144
0
{
145
0
  struct rev_name *name = commit_rev_name_at(&rev_names, commit);
146
147
0
  if (is_valid_rev_name(name) &&
148
0
      !is_better_name(name, taggerdate, generation, distance, from_tag))
149
0
    return NULL;
150
151
0
  name->taggerdate = taggerdate;
152
0
  name->generation = generation;
153
0
  name->distance = distance;
154
0
  name->from_tag = from_tag;
155
156
0
  return name;
157
0
}
158
159
static char *get_parent_name(const struct rev_name *name, int parent_number,
160
           struct mem_pool *string_pool)
161
0
{
162
0
  size_t len;
163
164
0
  strip_suffix(name->tip_name, "^0", &len);
165
0
  if (name->generation > 0) {
166
0
    return mem_pool_strfmt(string_pool, "%.*s~%d^%d",
167
0
               (int)len, name->tip_name,
168
0
               name->generation, parent_number);
169
0
  } else {
170
0
    return mem_pool_strfmt(string_pool, "%.*s^%d",
171
0
               (int)len, name->tip_name, parent_number);
172
0
  }
173
0
}
174
175
static void name_rev(struct commit *start_commit,
176
    const char *tip_name, timestamp_t taggerdate,
177
    int from_tag, int deref, struct mem_pool *string_pool)
178
0
{
179
0
  struct prio_queue queue;
180
0
  struct commit *commit;
181
0
  struct commit **parents_to_queue = NULL;
182
0
  size_t parents_to_queue_nr, parents_to_queue_alloc = 0;
183
0
  struct rev_name *start_name;
184
185
0
  repo_parse_commit(the_repository, start_commit);
186
0
  if (commit_is_before_cutoff(start_commit))
187
0
    return;
188
189
0
  start_name = create_or_update_name(start_commit, taggerdate, 0, 0,
190
0
             from_tag);
191
0
  if (!start_name)
192
0
    return;
193
0
  if (deref)
194
0
    start_name->tip_name = mem_pool_strfmt(string_pool, "%s^0",
195
0
                   tip_name);
196
0
  else
197
0
    start_name->tip_name = mem_pool_strdup(string_pool, tip_name);
198
199
0
  memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */
200
0
  prio_queue_put(&queue, start_commit);
201
202
0
  while ((commit = prio_queue_get(&queue))) {
203
0
    struct rev_name *name = get_commit_rev_name(commit);
204
0
    struct commit_list *parents;
205
0
    int parent_number = 1;
206
207
0
    parents_to_queue_nr = 0;
208
209
0
    for (parents = commit->parents;
210
0
        parents;
211
0
        parents = parents->next, parent_number++) {
212
0
      struct commit *parent = parents->item;
213
0
      struct rev_name *parent_name;
214
0
      int generation, distance;
215
216
0
      repo_parse_commit(the_repository, parent);
217
0
      if (commit_is_before_cutoff(parent))
218
0
        continue;
219
220
0
      if (parent_number > 1) {
221
0
        generation = 0;
222
0
        distance = name->distance + MERGE_TRAVERSAL_WEIGHT;
223
0
      } else {
224
0
        generation = name->generation + 1;
225
0
        distance = name->distance + 1;
226
0
      }
227
228
0
      parent_name = create_or_update_name(parent, taggerdate,
229
0
                  generation,
230
0
                  distance, from_tag);
231
0
      if (parent_name) {
232
0
        if (parent_number > 1)
233
0
          parent_name->tip_name =
234
0
            get_parent_name(name,
235
0
                parent_number,
236
0
                string_pool);
237
0
        else
238
0
          parent_name->tip_name = name->tip_name;
239
0
        ALLOC_GROW(parents_to_queue,
240
0
             parents_to_queue_nr + 1,
241
0
             parents_to_queue_alloc);
242
0
        parents_to_queue[parents_to_queue_nr] = parent;
243
0
        parents_to_queue_nr++;
244
0
      }
245
0
    }
246
247
    /* The first parent must come out first from the prio_queue */
248
0
    while (parents_to_queue_nr)
249
0
      prio_queue_put(&queue,
250
0
               parents_to_queue[--parents_to_queue_nr]);
251
0
  }
252
253
0
  clear_prio_queue(&queue);
254
0
  free(parents_to_queue);
255
0
}
256
257
static int subpath_matches(const char *path, const char *filter)
258
0
{
259
0
  const char *subpath = path;
260
261
0
  while (subpath) {
262
0
    if (!wildmatch(filter, subpath, 0))
263
0
      return subpath - path;
264
0
    subpath = strchr(subpath, '/');
265
0
    if (subpath)
266
0
      subpath++;
267
0
  }
268
0
  return -1;
269
0
}
270
271
struct name_ref_data {
272
  int tags_only;
273
  int name_only;
274
  struct string_list ref_filters;
275
  struct string_list exclude_filters;
276
};
277
278
static struct tip_table {
279
  struct tip_table_entry {
280
    struct object_id oid;
281
    const char *refname;
282
    struct commit *commit;
283
    timestamp_t taggerdate;
284
    unsigned int from_tag:1;
285
    unsigned int deref:1;
286
  } *table;
287
  int nr;
288
  int alloc;
289
  int sorted;
290
} tip_table;
291
292
static void add_to_tip_table(const struct object_id *oid, const char *refname,
293
           int shorten_unambiguous, struct commit *commit,
294
           timestamp_t taggerdate, int from_tag, int deref)
295
0
{
296
0
  char *short_refname = NULL;
297
298
0
  if (shorten_unambiguous)
299
0
    short_refname = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
300
0
                   refname, 0);
301
0
  else if (skip_prefix(refname, "refs/heads/", &refname))
302
0
    ; /* refname already advanced */
303
0
  else
304
0
    skip_prefix(refname, "refs/", &refname);
305
306
0
  ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
307
0
  oidcpy(&tip_table.table[tip_table.nr].oid, oid);
308
0
  tip_table.table[tip_table.nr].refname = short_refname ?
309
0
    short_refname : xstrdup(refname);
310
0
  tip_table.table[tip_table.nr].commit = commit;
311
0
  tip_table.table[tip_table.nr].taggerdate = taggerdate;
312
0
  tip_table.table[tip_table.nr].from_tag = from_tag;
313
0
  tip_table.table[tip_table.nr].deref = deref;
314
0
  tip_table.nr++;
315
0
  tip_table.sorted = 0;
316
0
}
317
318
static int tipcmp(const void *a_, const void *b_)
319
0
{
320
0
  const struct tip_table_entry *a = a_, *b = b_;
321
0
  return oidcmp(&a->oid, &b->oid);
322
0
}
323
324
static int cmp_by_tag_and_age(const void *a_, const void *b_)
325
0
{
326
0
  const struct tip_table_entry *a = a_, *b = b_;
327
0
  int cmp;
328
329
  /* Prefer tags. */
330
0
  cmp = b->from_tag - a->from_tag;
331
0
  if (cmp)
332
0
    return cmp;
333
334
  /* Older is better. */
335
0
  if (a->taggerdate < b->taggerdate)
336
0
    return -1;
337
0
  return a->taggerdate != b->taggerdate;
338
0
}
339
340
static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
341
        int flags UNUSED, void *cb_data)
342
0
{
343
0
  struct object *o = parse_object(the_repository, oid);
344
0
  struct name_ref_data *data = cb_data;
345
0
  int can_abbreviate_output = data->tags_only && data->name_only;
346
0
  int deref = 0;
347
0
  int from_tag = 0;
348
0
  struct commit *commit = NULL;
349
0
  timestamp_t taggerdate = TIME_MAX;
350
351
0
  if (data->tags_only && !starts_with(path, "refs/tags/"))
352
0
    return 0;
353
354
0
  if (data->exclude_filters.nr) {
355
0
    struct string_list_item *item;
356
357
0
    for_each_string_list_item(item, &data->exclude_filters) {
358
0
      if (subpath_matches(path, item->string) >= 0)
359
0
        return 0;
360
0
    }
361
0
  }
362
363
0
  if (data->ref_filters.nr) {
364
0
    struct string_list_item *item;
365
0
    int matched = 0;
366
367
    /* See if any of the patterns match. */
368
0
    for_each_string_list_item(item, &data->ref_filters) {
369
      /*
370
       * Check all patterns even after finding a match, so
371
       * that we can see if a match with a subpath exists.
372
       * When a user asked for 'refs/tags/v*' and 'v1.*',
373
       * both of which match, the user is showing her
374
       * willingness to accept a shortened output by having
375
       * the 'v1.*' in the acceptable refnames, so we
376
       * shouldn't stop when seeing 'refs/tags/v1.4' matches
377
       * 'refs/tags/v*'.  We should show it as 'v1.4'.
378
       */
379
0
      switch (subpath_matches(path, item->string)) {
380
0
      case -1: /* did not match */
381
0
        break;
382
0
      case 0: /* matched fully */
383
0
        matched = 1;
384
0
        break;
385
0
      default: /* matched subpath */
386
0
        matched = 1;
387
0
        can_abbreviate_output = 1;
388
0
        break;
389
0
      }
390
0
    }
391
392
    /* If none of the patterns matched, stop now */
393
0
    if (!matched)
394
0
      return 0;
395
0
  }
396
397
0
  while (o && o->type == OBJ_TAG) {
398
0
    struct tag *t = (struct tag *) o;
399
0
    if (!t->tagged)
400
0
      break; /* broken repository */
401
0
    o = parse_object(the_repository, &t->tagged->oid);
402
0
    deref = 1;
403
0
    taggerdate = t->date;
404
0
  }
405
0
  if (o && o->type == OBJ_COMMIT) {
406
0
    commit = (struct commit *)o;
407
0
    from_tag = starts_with(path, "refs/tags/");
408
0
    if (taggerdate == TIME_MAX)
409
0
      taggerdate = commit->date;
410
0
  }
411
412
0
  add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
413
0
       from_tag, deref);
414
0
  return 0;
415
0
}
416
417
static void name_tips(struct mem_pool *string_pool)
418
0
{
419
0
  int i;
420
421
  /*
422
   * Try to set better names first, so that worse ones spread
423
   * less.
424
   */
425
0
  QSORT(tip_table.table, tip_table.nr, cmp_by_tag_and_age);
426
0
  for (i = 0; i < tip_table.nr; i++) {
427
0
    struct tip_table_entry *e = &tip_table.table[i];
428
0
    if (e->commit) {
429
0
      name_rev(e->commit, e->refname, e->taggerdate,
430
0
         e->from_tag, e->deref, string_pool);
431
0
    }
432
0
  }
433
0
}
434
435
static const struct object_id *nth_tip_table_ent(size_t ix, const void *table_)
436
0
{
437
0
  const struct tip_table_entry *table = table_;
438
0
  return &table[ix].oid;
439
0
}
440
441
static const char *get_exact_ref_match(const struct object *o)
442
0
{
443
0
  int found;
444
445
0
  if (!tip_table.table || !tip_table.nr)
446
0
    return NULL;
447
448
0
  if (!tip_table.sorted) {
449
0
    QSORT(tip_table.table, tip_table.nr, tipcmp);
450
0
    tip_table.sorted = 1;
451
0
  }
452
453
0
  found = oid_pos(&o->oid, tip_table.table, tip_table.nr,
454
0
      nth_tip_table_ent);
455
0
  if (0 <= found)
456
0
    return tip_table.table[found].refname;
457
0
  return NULL;
458
0
}
459
460
/* may return a constant string or use "buf" as scratch space */
461
static const char *get_rev_name(const struct object *o, struct strbuf *buf)
462
0
{
463
0
  struct rev_name *n;
464
0
  const struct commit *c;
465
466
0
  if (o->type != OBJ_COMMIT)
467
0
    return get_exact_ref_match(o);
468
0
  c = (const struct commit *) o;
469
0
  n = get_commit_rev_name(c);
470
0
  if (!n)
471
0
    return NULL;
472
473
0
  if (!n->generation)
474
0
    return n->tip_name;
475
0
  else {
476
0
    strbuf_reset(buf);
477
0
    strbuf_addstr(buf, n->tip_name);
478
0
    strbuf_strip_suffix(buf, "^0");
479
0
    strbuf_addf(buf, "~%d", n->generation);
480
0
    return buf->buf;
481
0
  }
482
0
}
483
484
static void show_name(const struct object *obj,
485
          const char *caller_name,
486
          int always, int allow_undefined, int name_only)
487
0
{
488
0
  const char *name;
489
0
  const struct object_id *oid = &obj->oid;
490
0
  struct strbuf buf = STRBUF_INIT;
491
492
0
  if (!name_only)
493
0
    printf("%s ", caller_name ? caller_name : oid_to_hex(oid));
494
0
  name = get_rev_name(obj, &buf);
495
0
  if (name)
496
0
    printf("%s\n", name);
497
0
  else if (allow_undefined)
498
0
    printf("undefined\n");
499
0
  else if (always)
500
0
    printf("%s\n",
501
0
           repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
502
0
  else
503
0
    die("cannot describe '%s'", oid_to_hex(oid));
504
0
  strbuf_release(&buf);
505
0
}
506
507
static char const * const name_rev_usage[] = {
508
  N_("git name-rev [<options>] <commit>..."),
509
  N_("git name-rev [<options>] --all"),
510
  N_("git name-rev [<options>] --annotate-stdin"),
511
  NULL
512
};
513
514
static void name_rev_line(char *p, struct name_ref_data *data)
515
0
{
516
0
  struct strbuf buf = STRBUF_INIT;
517
0
  int counter = 0;
518
0
  char *p_start;
519
0
  const unsigned hexsz = the_hash_algo->hexsz;
520
521
0
  for (p_start = p; *p; p++) {
522
0
#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f'))
523
0
    if (!ishex(*p))
524
0
      counter = 0;
525
0
    else if (++counter == hexsz &&
526
0
       !ishex(*(p+1))) {
527
0
      struct object_id oid;
528
0
      const char *name = NULL;
529
0
      char c = *(p+1);
530
0
      int p_len = p - p_start + 1;
531
532
0
      counter = 0;
533
534
0
      *(p+1) = 0;
535
0
      if (!repo_get_oid(the_repository, p - (hexsz - 1), &oid)) {
536
0
        struct object *o =
537
0
          lookup_object(the_repository, &oid);
538
0
        if (o)
539
0
          name = get_rev_name(o, &buf);
540
0
      }
541
0
      *(p+1) = c;
542
543
0
      if (!name)
544
0
        continue;
545
546
0
      if (data->name_only)
547
0
        printf("%.*s%s", p_len - hexsz, p_start, name);
548
0
      else
549
0
        printf("%.*s (%s)", p_len, p_start, name);
550
0
      p_start = p + 1;
551
0
    }
552
0
  }
553
554
  /* flush */
555
0
  if (p_start != p)
556
0
    fwrite(p_start, p - p_start, 1, stdout);
557
558
0
  strbuf_release(&buf);
559
0
}
560
561
int cmd_name_rev(int argc, const char **argv, const char *prefix)
562
0
{
563
0
  struct mem_pool string_pool;
564
0
  struct object_array revs = OBJECT_ARRAY_INIT;
565
0
  int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
566
0
  struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
567
0
  struct option opts[] = {
568
0
    OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
569
0
    OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
570
0
    OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
571
0
           N_("only use refs matching <pattern>")),
572
0
    OPT_STRING_LIST(0, "exclude", &data.exclude_filters, N_("pattern"),
573
0
           N_("ignore refs matching <pattern>")),
574
0
    OPT_GROUP(""),
575
0
    OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
576
0
    OPT_BOOL_F(0,
577
0
         "stdin",
578
0
         &transform_stdin,
579
0
         N_("deprecated: use --annotate-stdin instead"),
580
0
         PARSE_OPT_HIDDEN),
581
0
    OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
582
0
    OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
583
0
    OPT_BOOL(0, "always",     &always,
584
0
         N_("show abbreviated commit object as fallback")),
585
0
    OPT_HIDDEN_BOOL(0, "peel-tag", &peel_tag,
586
0
         N_("dereference tags in the input (internal use)")),
587
0
    OPT_END(),
588
0
  };
589
590
0
  mem_pool_init(&string_pool, 0);
591
0
  init_commit_rev_name(&rev_names);
592
0
  git_config(git_default_config, NULL);
593
0
  argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
594
595
0
  if (transform_stdin) {
596
0
    warning("--stdin is deprecated. Please use --annotate-stdin instead, "
597
0
          "which is functionally equivalent.\n"
598
0
          "This option will be removed in a future release.");
599
0
    annotate_stdin = 1;
600
0
  }
601
602
0
  if (all + annotate_stdin + !!argc > 1) {
603
0
    error("Specify either a list, or --all, not both!");
604
0
    usage_with_options(name_rev_usage, opts);
605
0
  }
606
0
  if (all || annotate_stdin)
607
0
    disable_cutoff();
608
609
0
  for (; argc; argc--, argv++) {
610
0
    struct object_id oid;
611
0
    struct object *object;
612
0
    struct commit *commit;
613
614
0
    if (repo_get_oid(the_repository, *argv, &oid)) {
615
0
      fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
616
0
          *argv);
617
0
      continue;
618
0
    }
619
620
0
    commit = NULL;
621
0
    object = parse_object(the_repository, &oid);
622
0
    if (object) {
623
0
      struct object *peeled = deref_tag(the_repository,
624
0
                object, *argv, 0);
625
0
      if (peeled && peeled->type == OBJ_COMMIT)
626
0
        commit = (struct commit *)peeled;
627
0
    }
628
629
0
    if (!object) {
630
0
      fprintf(stderr, "Could not get object for %s. Skipping.\n",
631
0
          *argv);
632
0
      continue;
633
0
    }
634
635
0
    if (commit)
636
0
      set_commit_cutoff(commit);
637
638
0
    if (peel_tag) {
639
0
      if (!commit) {
640
0
        fprintf(stderr, "Could not get commit for %s. Skipping.\n",
641
0
          *argv);
642
0
        continue;
643
0
      }
644
0
      object = (struct object *)commit;
645
0
    }
646
0
    add_object_array(object, *argv, &revs);
647
0
  }
648
649
0
  adjust_cutoff_timestamp_for_slop();
650
651
0
  refs_for_each_ref(get_main_ref_store(the_repository), name_ref, &data);
652
0
  name_tips(&string_pool);
653
654
0
  if (annotate_stdin) {
655
0
    struct strbuf sb = STRBUF_INIT;
656
657
0
    while (strbuf_getline(&sb, stdin) != EOF) {
658
0
      strbuf_addch(&sb, '\n');
659
0
      name_rev_line(sb.buf, &data);
660
0
    }
661
0
    strbuf_release(&sb);
662
0
  } else if (all) {
663
0
    int i, max;
664
665
0
    max = get_max_object_index();
666
0
    for (i = 0; i < max; i++) {
667
0
      struct object *obj = get_indexed_object(i);
668
0
      if (!obj || obj->type != OBJ_COMMIT)
669
0
        continue;
670
0
      show_name(obj, NULL,
671
0
          always, allow_undefined, data.name_only);
672
0
    }
673
0
  } else {
674
0
    int i;
675
0
    for (i = 0; i < revs.nr; i++)
676
0
      show_name(revs.objects[i].item, revs.objects[i].name,
677
0
          always, allow_undefined, data.name_only);
678
0
  }
679
680
0
  string_list_clear(&data.ref_filters, 0);
681
0
  string_list_clear(&data.exclude_filters, 0);
682
0
  mem_pool_discard(&string_pool, 0);
683
0
  object_array_clear(&revs);
684
0
  return 0;
685
0
}