Coverage Report

Created: 2024-09-08 06:23

/src/git/builtin/rev-list.c
Line
Count
Source (jump to first uncovered line)
1
#include "builtin.h"
2
#include "config.h"
3
#include "commit.h"
4
#include "diff.h"
5
#include "environment.h"
6
#include "gettext.h"
7
#include "hex.h"
8
#include "revision.h"
9
#include "list-objects.h"
10
#include "list-objects-filter-options.h"
11
#include "object.h"
12
#include "object-name.h"
13
#include "object-file.h"
14
#include "object-store-ll.h"
15
#include "pack-bitmap.h"
16
#include "log-tree.h"
17
#include "graph.h"
18
#include "bisect.h"
19
#include "progress.h"
20
#include "reflog-walk.h"
21
#include "oidset.h"
22
#include "packfile.h"
23
24
static const char rev_list_usage[] =
25
"git rev-list [<options>] <commit>... [--] [<path>...]\n"
26
"\n"
27
"  limiting output:\n"
28
"    --max-count=<n>\n"
29
"    --max-age=<epoch>\n"
30
"    --min-age=<epoch>\n"
31
"    --sparse\n"
32
"    --no-merges\n"
33
"    --min-parents=<n>\n"
34
"    --no-min-parents\n"
35
"    --max-parents=<n>\n"
36
"    --no-max-parents\n"
37
"    --remove-empty\n"
38
"    --all\n"
39
"    --branches\n"
40
"    --tags\n"
41
"    --remotes\n"
42
"    --stdin\n"
43
"    --exclude-hidden=[fetch|receive|uploadpack]\n"
44
"    --quiet\n"
45
"  ordering output:\n"
46
"    --topo-order\n"
47
"    --date-order\n"
48
"    --reverse\n"
49
"  formatting output:\n"
50
"    --parents\n"
51
"    --children\n"
52
"    --objects | --objects-edge\n"
53
"    --disk-usage[=human]\n"
54
"    --unpacked\n"
55
"    --header | --pretty\n"
56
"    --[no-]object-names\n"
57
"    --abbrev=<n> | --no-abbrev\n"
58
"    --abbrev-commit\n"
59
"    --left-right\n"
60
"    --count\n"
61
"  special purpose:\n"
62
"    --bisect\n"
63
"    --bisect-vars\n"
64
"    --bisect-all"
65
;
66
67
static struct progress *progress;
68
static unsigned progress_counter;
69
70
static struct oidset omitted_objects;
71
static int arg_print_omitted; /* print objects omitted by filter */
72
73
static struct oidset missing_objects;
74
enum missing_action {
75
  MA_ERROR = 0,    /* fail if any missing objects are encountered */
76
  MA_ALLOW_ANY,    /* silently allow ALL missing objects */
77
  MA_PRINT,        /* print ALL missing objects in special section */
78
  MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
79
};
80
static enum missing_action arg_missing_action;
81
82
/* display only the oid of each object encountered */
83
static int arg_show_object_names = 1;
84
85
0
#define DEFAULT_OIDSET_SIZE     (16*1024)
86
87
static int show_disk_usage;
88
static off_t total_disk_usage;
89
static int human_readable;
90
91
static off_t get_object_disk_usage(struct object *obj)
92
0
{
93
0
  off_t size;
94
0
  struct object_info oi = OBJECT_INFO_INIT;
95
0
  oi.disk_sizep = &size;
96
0
  if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0)
97
0
    die(_("unable to get disk usage of %s"), oid_to_hex(&obj->oid));
98
0
  return size;
99
0
}
100
101
static inline void finish_object__ma(struct object *obj)
102
0
{
103
  /*
104
   * Whether or not we try to dynamically fetch missing objects
105
   * from the server, we currently DO NOT have the object.  We
106
   * can either print, allow (ignore), or conditionally allow
107
   * (ignore) them.
108
   */
109
0
  switch (arg_missing_action) {
110
0
  case MA_ERROR:
111
0
    die("missing %s object '%s'",
112
0
        type_name(obj->type), oid_to_hex(&obj->oid));
113
0
    return;
114
115
0
  case MA_ALLOW_ANY:
116
0
    return;
117
118
0
  case MA_PRINT:
119
0
    oidset_insert(&missing_objects, &obj->oid);
120
0
    return;
121
122
0
  case MA_ALLOW_PROMISOR:
123
0
    if (is_promisor_object(&obj->oid))
124
0
      return;
125
0
    die("unexpected missing %s object '%s'",
126
0
        type_name(obj->type), oid_to_hex(&obj->oid));
127
0
    return;
128
129
0
  default:
130
0
    BUG("unhandled missing_action");
131
0
    return;
132
0
  }
133
0
}
134
135
static void finish_commit(struct commit *commit)
136
0
{
137
0
  free_commit_list(commit->parents);
138
0
  commit->parents = NULL;
139
0
  free_commit_buffer(the_repository->parsed_objects,
140
0
         commit);
141
0
}
142
143
static void show_commit(struct commit *commit, void *data)
144
0
{
145
0
  struct rev_list_info *info = data;
146
0
  struct rev_info *revs = info->revs;
147
148
0
  display_progress(progress, ++progress_counter);
149
150
0
  if (revs->do_not_die_on_missing_objects &&
151
0
      oidset_contains(&revs->missing_commits, &commit->object.oid)) {
152
0
    finish_object__ma(&commit->object);
153
0
    return;
154
0
  }
155
156
0
  if (show_disk_usage)
157
0
    total_disk_usage += get_object_disk_usage(&commit->object);
158
159
0
  if (info->flags & REV_LIST_QUIET) {
160
0
    finish_commit(commit);
161
0
    return;
162
0
  }
163
164
0
  graph_show_commit(revs->graph);
165
166
0
  if (revs->count) {
167
0
    if (commit->object.flags & PATCHSAME)
168
0
      revs->count_same++;
169
0
    else if (commit->object.flags & SYMMETRIC_LEFT)
170
0
      revs->count_left++;
171
0
    else
172
0
      revs->count_right++;
173
0
    finish_commit(commit);
174
0
    return;
175
0
  }
176
177
0
  if (info->show_timestamp)
178
0
    printf("%"PRItime" ", commit->date);
179
0
  if (info->header_prefix)
180
0
    fputs(info->header_prefix, stdout);
181
182
0
  if (revs->include_header) {
183
0
    if (!revs->graph)
184
0
      fputs(get_revision_mark(revs, commit), stdout);
185
0
    if (revs->abbrev_commit && revs->abbrev)
186
0
      fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid, revs->abbrev),
187
0
            stdout);
188
0
    else
189
0
      fputs(oid_to_hex(&commit->object.oid), stdout);
190
0
  }
191
0
  if (revs->print_parents) {
192
0
    struct commit_list *parents = commit->parents;
193
0
    while (parents) {
194
0
      printf(" %s", oid_to_hex(&parents->item->object.oid));
195
0
      parents = parents->next;
196
0
    }
197
0
  }
198
0
  if (revs->children.name) {
199
0
    struct commit_list *children;
200
201
0
    children = lookup_decoration(&revs->children, &commit->object);
202
0
    while (children) {
203
0
      printf(" %s", oid_to_hex(&children->item->object.oid));
204
0
      children = children->next;
205
0
    }
206
0
  }
207
0
  show_decorations(revs, commit);
208
0
  if (revs->commit_format == CMIT_FMT_ONELINE)
209
0
    putchar(' ');
210
0
  else if (revs->include_header)
211
0
    putchar('\n');
212
213
0
  if (revs->verbose_header) {
214
0
    struct strbuf buf = STRBUF_INIT;
215
0
    struct pretty_print_context ctx = {0};
216
0
    ctx.abbrev = revs->abbrev;
217
0
    ctx.date_mode = revs->date_mode;
218
0
    ctx.date_mode_explicit = revs->date_mode_explicit;
219
0
    ctx.fmt = revs->commit_format;
220
0
    ctx.output_encoding = get_log_output_encoding();
221
0
    ctx.color = revs->diffopt.use_color;
222
0
    ctx.rev = revs;
223
0
    pretty_print_commit(&ctx, commit, &buf);
224
0
    if (buf.len) {
225
0
      if (revs->commit_format != CMIT_FMT_ONELINE)
226
0
        graph_show_oneline(revs->graph);
227
228
0
      graph_show_commit_msg(revs->graph, stdout, &buf);
229
230
      /*
231
       * Add a newline after the commit message.
232
       *
233
       * Usually, this newline produces a blank
234
       * padding line between entries, in which case
235
       * we need to add graph padding on this line.
236
       *
237
       * However, the commit message may not end in a
238
       * newline.  In this case the newline simply
239
       * ends the last line of the commit message,
240
       * and we don't need any graph output.  (This
241
       * always happens with CMIT_FMT_ONELINE, and it
242
       * happens with CMIT_FMT_USERFORMAT when the
243
       * format doesn't explicitly end in a newline.)
244
       */
245
0
      if (buf.len && buf.buf[buf.len - 1] == '\n')
246
0
        graph_show_padding(revs->graph);
247
0
      putchar(info->hdr_termination);
248
0
    } else {
249
      /*
250
       * If the message buffer is empty, just show
251
       * the rest of the graph output for this
252
       * commit.
253
       */
254
0
      if (graph_show_remainder(revs->graph))
255
0
        putchar('\n');
256
0
      if (revs->commit_format == CMIT_FMT_ONELINE)
257
0
        putchar('\n');
258
0
    }
259
0
    strbuf_release(&buf);
260
0
  } else {
261
0
    if (graph_show_remainder(revs->graph))
262
0
      putchar('\n');
263
0
  }
264
0
  maybe_flush_or_die(stdout, "stdout");
265
0
  finish_commit(commit);
266
0
}
267
268
static int finish_object(struct object *obj, const char *name UNUSED,
269
       void *cb_data)
270
0
{
271
0
  struct rev_list_info *info = cb_data;
272
0
  if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
273
0
    finish_object__ma(obj);
274
0
    return 1;
275
0
  }
276
0
  if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
277
0
    parse_object(the_repository, &obj->oid);
278
0
  return 0;
279
0
}
280
281
static void show_object(struct object *obj, const char *name, void *cb_data)
282
0
{
283
0
  struct rev_list_info *info = cb_data;
284
0
  struct rev_info *revs = info->revs;
285
286
0
  if (finish_object(obj, name, cb_data))
287
0
    return;
288
0
  display_progress(progress, ++progress_counter);
289
0
  if (show_disk_usage)
290
0
    total_disk_usage += get_object_disk_usage(obj);
291
0
  if (info->flags & REV_LIST_QUIET)
292
0
    return;
293
294
0
  if (revs->count) {
295
    /*
296
     * The object count is always accumulated in the .count_right
297
     * field for traversal that is not a left-right traversal,
298
     * and cmd_rev_list() made sure that a .count request that
299
     * wants to count non-commit objects, which is handled by
300
     * the show_object() callback, does not ask for .left_right.
301
     */
302
0
    revs->count_right++;
303
0
    return;
304
0
  }
305
306
0
  if (arg_show_object_names)
307
0
    show_object_with_name(stdout, obj, name);
308
0
  else
309
0
    printf("%s\n", oid_to_hex(&obj->oid));
310
0
}
311
312
static void show_edge(struct commit *commit)
313
0
{
314
0
  printf("-%s\n", oid_to_hex(&commit->object.oid));
315
0
}
316
317
static void print_var_str(const char *var, const char *val)
318
0
{
319
0
  printf("%s='%s'\n", var, val);
320
0
}
321
322
static void print_var_int(const char *var, int val)
323
0
{
324
0
  printf("%s=%d\n", var, val);
325
0
}
326
327
static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
328
0
{
329
0
  int cnt, flags = info->flags;
330
0
  char hex[GIT_MAX_HEXSZ + 1] = "";
331
0
  struct commit_list *tried;
332
0
  struct rev_info *revs = info->revs;
333
334
0
  if (!revs->commits)
335
0
    return 1;
336
337
0
  revs->commits = filter_skipped(revs->commits, &tried,
338
0
               flags & BISECT_SHOW_ALL,
339
0
               NULL, NULL);
340
341
  /*
342
   * revs->commits can reach "reaches" commits among
343
   * "all" commits.  If it is good, then there are
344
   * (all-reaches) commits left to be bisected.
345
   * On the other hand, if it is bad, then the set
346
   * to bisect is "reaches".
347
   * A bisect set of size N has (N-1) commits further
348
   * to test, as we already know one bad one.
349
   */
350
0
  cnt = all - reaches;
351
0
  if (cnt < reaches)
352
0
    cnt = reaches;
353
354
0
  if (revs->commits)
355
0
    oid_to_hex_r(hex, &revs->commits->item->object.oid);
356
357
0
  if (flags & BISECT_SHOW_ALL) {
358
0
    traverse_commit_list(revs, show_commit, show_object, info);
359
0
    printf("------\n");
360
0
  }
361
362
0
  print_var_str("bisect_rev", hex);
363
0
  print_var_int("bisect_nr", cnt - 1);
364
0
  print_var_int("bisect_good", all - reaches - 1);
365
0
  print_var_int("bisect_bad", reaches - 1);
366
0
  print_var_int("bisect_all", all);
367
0
  print_var_int("bisect_steps", estimate_bisect_steps(all));
368
369
0
  return 0;
370
0
}
371
372
static int show_object_fast(
373
  const struct object_id *oid,
374
  enum object_type type UNUSED,
375
  int exclude UNUSED,
376
  uint32_t name_hash UNUSED,
377
  struct packed_git *found_pack UNUSED,
378
  off_t found_offset UNUSED)
379
0
{
380
0
  fprintf(stdout, "%s\n", oid_to_hex(oid));
381
0
  return 1;
382
0
}
383
384
static void print_disk_usage(off_t size)
385
0
{
386
0
  struct strbuf sb = STRBUF_INIT;
387
0
  if (human_readable)
388
0
    strbuf_humanise_bytes(&sb, size);
389
0
  else
390
0
    strbuf_addf(&sb, "%"PRIuMAX, (uintmax_t)size);
391
0
  puts(sb.buf);
392
0
  strbuf_release(&sb);
393
0
}
394
395
static inline int parse_missing_action_value(const char *value)
396
0
{
397
0
  if (!strcmp(value, "error")) {
398
0
    arg_missing_action = MA_ERROR;
399
0
    return 1;
400
0
  }
401
402
0
  if (!strcmp(value, "allow-any")) {
403
0
    arg_missing_action = MA_ALLOW_ANY;
404
0
    fetch_if_missing = 0;
405
0
    return 1;
406
0
  }
407
408
0
  if (!strcmp(value, "print")) {
409
0
    arg_missing_action = MA_PRINT;
410
0
    fetch_if_missing = 0;
411
0
    return 1;
412
0
  }
413
414
0
  if (!strcmp(value, "allow-promisor")) {
415
0
    arg_missing_action = MA_ALLOW_PROMISOR;
416
0
    fetch_if_missing = 0;
417
0
    return 1;
418
0
  }
419
420
0
  return 0;
421
0
}
422
423
static int try_bitmap_count(struct rev_info *revs,
424
          int filter_provided_objects)
425
0
{
426
0
  uint32_t commit_count = 0,
427
0
     tag_count = 0,
428
0
     tree_count = 0,
429
0
     blob_count = 0;
430
0
  int max_count;
431
0
  struct bitmap_index *bitmap_git;
432
433
  /* This function only handles counting, not general traversal. */
434
0
  if (!revs->count)
435
0
    return -1;
436
437
  /*
438
   * A bitmap result can't know left/right, etc, because we don't
439
   * actually traverse.
440
   */
441
0
  if (revs->left_right || revs->cherry_mark)
442
0
    return -1;
443
444
  /*
445
   * If we're counting reachable objects, we can't handle a max count of
446
   * commits to traverse, since we don't know which objects go with which
447
   * commit.
448
   */
449
0
  if (revs->max_count >= 0 &&
450
0
      (revs->tag_objects || revs->tree_objects || revs->blob_objects))
451
0
    return -1;
452
453
  /*
454
   * This must be saved before doing any walking, since the revision
455
   * machinery will count it down to zero while traversing.
456
   */
457
0
  max_count = revs->max_count;
458
459
0
  bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects);
460
0
  if (!bitmap_git)
461
0
    return -1;
462
463
0
  count_bitmap_commit_list(bitmap_git, &commit_count,
464
0
         revs->tree_objects ? &tree_count : NULL,
465
0
         revs->blob_objects ? &blob_count : NULL,
466
0
         revs->tag_objects ? &tag_count : NULL);
467
0
  if (max_count >= 0 && max_count < commit_count)
468
0
    commit_count = max_count;
469
470
0
  printf("%d\n", commit_count + tree_count + blob_count + tag_count);
471
0
  free_bitmap_index(bitmap_git);
472
0
  return 0;
473
0
}
474
475
static int try_bitmap_traversal(struct rev_info *revs,
476
        int filter_provided_objects)
477
0
{
478
0
  struct bitmap_index *bitmap_git;
479
480
  /*
481
   * We can't use a bitmap result with a traversal limit, since the set
482
   * of commits we'd get would be essentially random.
483
   */
484
0
  if (revs->max_count >= 0)
485
0
    return -1;
486
487
0
  bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects);
488
0
  if (!bitmap_git)
489
0
    return -1;
490
491
0
  traverse_bitmap_commit_list(bitmap_git, revs, &show_object_fast);
492
0
  free_bitmap_index(bitmap_git);
493
0
  return 0;
494
0
}
495
496
static int try_bitmap_disk_usage(struct rev_info *revs,
497
         int filter_provided_objects)
498
0
{
499
0
  struct bitmap_index *bitmap_git;
500
0
  off_t size_from_bitmap;
501
502
0
  if (!show_disk_usage)
503
0
    return -1;
504
505
0
  bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects);
506
0
  if (!bitmap_git)
507
0
    return -1;
508
509
0
  size_from_bitmap = get_disk_usage_from_bitmap(bitmap_git, revs);
510
0
  print_disk_usage(size_from_bitmap);
511
512
0
  free_bitmap_index(bitmap_git);
513
0
  return 0;
514
0
}
515
516
int cmd_rev_list(int argc, const char **argv, const char *prefix)
517
0
{
518
0
  struct rev_info revs;
519
0
  struct rev_list_info info;
520
0
  struct setup_revision_opt s_r_opt = {
521
0
    .allow_exclude_promisor_objects = 1,
522
0
  };
523
0
  int i;
524
0
  int bisect_list = 0;
525
0
  int bisect_show_vars = 0;
526
0
  int bisect_find_all = 0;
527
0
  int use_bitmap_index = 0;
528
0
  int filter_provided_objects = 0;
529
0
  const char *show_progress = NULL;
530
0
  int ret = 0;
531
532
0
  if (argc == 2 && !strcmp(argv[1], "-h"))
533
0
    usage(rev_list_usage);
534
535
0
  git_config(git_default_config, NULL);
536
0
  repo_init_revisions(the_repository, &revs, prefix);
537
0
  revs.abbrev = DEFAULT_ABBREV;
538
0
  revs.commit_format = CMIT_FMT_UNSPECIFIED;
539
0
  revs.include_header = 1;
540
541
  /*
542
   * Scan the argument list before invoking setup_revisions(), so that we
543
   * know if fetch_if_missing needs to be set to 0.
544
   *
545
   * "--exclude-promisor-objects" acts as a pre-filter on missing objects
546
   * by not crossing the boundary from realized objects to promisor
547
   * objects.
548
   *
549
   * Let "--missing" to conditionally set fetch_if_missing.
550
   */
551
  /*
552
   * NEEDSWORK: These loops that attempt to find presence of
553
   * options without understanding that the options they are
554
   * skipping are broken (e.g., it would not know "--grep
555
   * --exclude-promisor-objects" is not triggering
556
   * "--exclude-promisor-objects" option).  We really need
557
   * setup_revisions() to have a mechanism to allow and disallow
558
   * some sets of options for different commands (like rev-list,
559
   * replay, etc). Such a mechanism should do an early parsing
560
   * of options and be able to manage the `--missing=...` and
561
   * `--exclude-promisor-objects` options below.
562
   */
563
0
  for (i = 1; i < argc; i++) {
564
0
    const char *arg = argv[i];
565
0
    if (!strcmp(arg, "--exclude-promisor-objects")) {
566
0
      fetch_if_missing = 0;
567
0
      revs.exclude_promisor_objects = 1;
568
0
      break;
569
0
    }
570
0
  }
571
0
  for (i = 1; i < argc; i++) {
572
0
    const char *arg = argv[i];
573
0
    if (skip_prefix(arg, "--missing=", &arg)) {
574
0
      if (revs.exclude_promisor_objects)
575
0
        die(_("options '%s' and '%s' cannot be used together"), "--exclude-promisor-objects", "--missing");
576
0
      if (parse_missing_action_value(arg))
577
0
        break;
578
0
    }
579
0
  }
580
581
0
  if (arg_missing_action)
582
0
    revs.do_not_die_on_missing_objects = 1;
583
584
0
  argc = setup_revisions(argc, argv, &revs, &s_r_opt);
585
586
0
  memset(&info, 0, sizeof(info));
587
0
  info.revs = &revs;
588
0
  if (revs.bisect)
589
0
    bisect_list = 1;
590
591
0
  if (revs.diffopt.flags.quick)
592
0
    info.flags |= REV_LIST_QUIET;
593
0
  for (i = 1 ; i < argc; i++) {
594
0
    const char *arg = argv[i];
595
596
0
    if (!strcmp(arg, "--header")) {
597
0
      revs.verbose_header = 1;
598
0
      continue;
599
0
    }
600
0
    if (!strcmp(arg, "--timestamp")) {
601
0
      info.show_timestamp = 1;
602
0
      continue;
603
0
    }
604
0
    if (!strcmp(arg, "--bisect")) {
605
0
      bisect_list = 1;
606
0
      continue;
607
0
    }
608
0
    if (!strcmp(arg, "--bisect-all")) {
609
0
      bisect_list = 1;
610
0
      bisect_find_all = 1;
611
0
      info.flags |= BISECT_SHOW_ALL;
612
0
      revs.show_decorations = 1;
613
0
      continue;
614
0
    }
615
0
    if (!strcmp(arg, "--bisect-vars")) {
616
0
      bisect_list = 1;
617
0
      bisect_show_vars = 1;
618
0
      continue;
619
0
    }
620
0
    if (!strcmp(arg, "--use-bitmap-index")) {
621
0
      use_bitmap_index = 1;
622
0
      continue;
623
0
    }
624
0
    if (!strcmp(arg, "--test-bitmap")) {
625
0
      test_bitmap_walk(&revs);
626
0
      goto cleanup;
627
0
    }
628
0
    if (skip_prefix(arg, "--progress=", &arg)) {
629
0
      show_progress = arg;
630
0
      continue;
631
0
    }
632
0
    if (!strcmp(arg, "--filter-provided-objects")) {
633
0
      filter_provided_objects = 1;
634
0
      continue;
635
0
    }
636
0
    if (!strcmp(arg, "--filter-print-omitted")) {
637
0
      arg_print_omitted = 1;
638
0
      continue;
639
0
    }
640
641
0
    if (!strcmp(arg, "--exclude-promisor-objects"))
642
0
      continue; /* already handled above */
643
0
    if (skip_prefix(arg, "--missing=", &arg))
644
0
      continue; /* already handled above */
645
646
0
    if (!strcmp(arg, ("--no-object-names"))) {
647
0
      arg_show_object_names = 0;
648
0
      continue;
649
0
    }
650
651
0
    if (!strcmp(arg, ("--object-names"))) {
652
0
      arg_show_object_names = 1;
653
0
      continue;
654
0
    }
655
656
0
    if (!strcmp(arg, ("--commit-header"))) {
657
0
      revs.include_header = 1;
658
0
      continue;
659
0
    }
660
661
0
    if (!strcmp(arg, ("--no-commit-header"))) {
662
0
      revs.include_header = 0;
663
0
      continue;
664
0
    }
665
666
0
    if (skip_prefix(arg, "--disk-usage", &arg)) {
667
0
      if (*arg == '=') {
668
0
        if (!strcmp(++arg, "human")) {
669
0
          human_readable = 1;
670
0
        } else
671
0
          die(_("invalid value for '%s': '%s', the only allowed format is '%s'"),
672
0
              "--disk-usage=<format>", arg, "human");
673
0
      } else if (*arg) {
674
        /*
675
         * Arguably should goto a label to continue chain of ifs?
676
         * Doesn't matter unless we try to add --disk-usage-foo
677
         * afterwards.
678
         */
679
0
        usage(rev_list_usage);
680
0
      }
681
0
      show_disk_usage = 1;
682
0
      info.flags |= REV_LIST_QUIET;
683
0
      continue;
684
0
    }
685
686
0
    usage(rev_list_usage);
687
688
0
  }
689
0
  if (revs.commit_format != CMIT_FMT_USERFORMAT)
690
0
    revs.include_header = 1;
691
0
  if (revs.commit_format != CMIT_FMT_UNSPECIFIED) {
692
    /* The command line has a --pretty  */
693
0
    info.hdr_termination = '\n';
694
0
    if (revs.commit_format == CMIT_FMT_ONELINE || !revs.include_header)
695
0
      info.header_prefix = "";
696
0
    else
697
0
      info.header_prefix = "commit ";
698
0
  }
699
0
  else if (revs.verbose_header)
700
    /* Only --header was specified */
701
0
    revs.commit_format = CMIT_FMT_RAW;
702
703
0
  if ((!revs.commits && reflog_walk_empty(revs.reflog_info) &&
704
0
       (!(revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
705
0
        !revs.pending.nr) &&
706
0
       !revs.rev_input_given && !revs.read_from_stdin) ||
707
0
      revs.diff)
708
0
    usage(rev_list_usage);
709
710
0
  if (revs.show_notes)
711
0
    die(_("rev-list does not support display of notes"));
712
713
0
  if (revs.count &&
714
0
      (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
715
0
      (revs.left_right || revs.cherry_mark))
716
0
    die(_("marked counting and '%s' cannot be used together"), "--objects");
717
718
0
  save_commit_buffer = (revs.verbose_header ||
719
0
            revs.grep_filter.pattern_list ||
720
0
            revs.grep_filter.header_list);
721
0
  if (bisect_list)
722
0
    revs.limited = 1;
723
724
0
  if (show_progress)
725
0
    progress = start_delayed_progress(show_progress, 0);
726
727
0
  if (use_bitmap_index) {
728
0
    if (!try_bitmap_count(&revs, filter_provided_objects))
729
0
      goto cleanup;
730
0
    if (!try_bitmap_disk_usage(&revs, filter_provided_objects))
731
0
      goto cleanup;
732
0
    if (!try_bitmap_traversal(&revs, filter_provided_objects))
733
0
      goto cleanup;
734
0
  }
735
736
0
  if (prepare_revision_walk(&revs))
737
0
    die("revision walk setup failed");
738
0
  if (revs.tree_objects)
739
0
    mark_edges_uninteresting(&revs, show_edge, 0);
740
741
0
  if (bisect_list) {
742
0
    int reaches, all;
743
0
    unsigned bisect_flags = 0;
744
745
0
    if (bisect_find_all)
746
0
      bisect_flags |= FIND_BISECTION_ALL;
747
748
0
    if (revs.first_parent_only)
749
0
      bisect_flags |= FIND_BISECTION_FIRST_PARENT_ONLY;
750
751
0
    find_bisection(&revs.commits, &reaches, &all, bisect_flags);
752
753
0
    if (bisect_show_vars) {
754
0
      ret = show_bisect_vars(&info, reaches, all);
755
0
      goto cleanup;
756
0
    }
757
0
  }
758
759
0
  if (filter_provided_objects) {
760
0
    struct commit_list *c;
761
0
    for (i = 0; i < revs.pending.nr; i++) {
762
0
      struct object_array_entry *pending = revs.pending.objects + i;
763
0
      pending->item->flags |= NOT_USER_GIVEN;
764
0
    }
765
0
    for (c = revs.commits; c; c = c->next)
766
0
      c->item->object.flags |= NOT_USER_GIVEN;
767
0
  }
768
769
0
  if (arg_print_omitted)
770
0
    oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
771
0
  if (arg_missing_action == MA_PRINT) {
772
0
    oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
773
    /* Add missing tips */
774
0
    oidset_insert_from_set(&missing_objects, &revs.missing_commits);
775
0
    oidset_clear(&revs.missing_commits);
776
0
  }
777
778
0
  traverse_commit_list_filtered(
779
0
    &revs, show_commit, show_object, &info,
780
0
    (arg_print_omitted ? &omitted_objects : NULL));
781
782
0
  if (arg_print_omitted) {
783
0
    struct oidset_iter iter;
784
0
    struct object_id *oid;
785
0
    oidset_iter_init(&omitted_objects, &iter);
786
0
    while ((oid = oidset_iter_next(&iter)))
787
0
      printf("~%s\n", oid_to_hex(oid));
788
0
    oidset_clear(&omitted_objects);
789
0
  }
790
0
  if (arg_missing_action == MA_PRINT) {
791
0
    struct oidset_iter iter;
792
0
    struct object_id *oid;
793
0
    oidset_iter_init(&missing_objects, &iter);
794
0
    while ((oid = oidset_iter_next(&iter)))
795
0
      printf("?%s\n", oid_to_hex(oid));
796
0
    oidset_clear(&missing_objects);
797
0
  }
798
799
0
  stop_progress(&progress);
800
801
0
  if (revs.count) {
802
0
    if (revs.left_right && revs.cherry_mark)
803
0
      printf("%d\t%d\t%d\n", revs.count_left, revs.count_right, revs.count_same);
804
0
    else if (revs.left_right)
805
0
      printf("%d\t%d\n", revs.count_left, revs.count_right);
806
0
    else if (revs.cherry_mark)
807
0
      printf("%d\t%d\n", revs.count_left + revs.count_right, revs.count_same);
808
0
    else
809
0
      printf("%d\n", revs.count_left + revs.count_right);
810
0
  }
811
812
0
  if (show_disk_usage)
813
0
    print_disk_usage(total_disk_usage);
814
815
0
cleanup:
816
0
  release_revisions(&revs);
817
0
  return ret;
818
0
}