rev-list: factor out bitmap-optimized routines
There are a few operations in rev-list that are optimized for bitmaps. Rather than having the code inline in cmd_rev_list(), let's move them into helpers. This not only makes the flow of the main function simpler, but it lets us replace the complex "can we do the optimization?" conditionals with a series of early returns from the functions. That also makes it easy to add comments explaining those conditions. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Feb 14, 2020 at 13:22 UTC
792f8119986bd354eb4ea0858dfd45904120c257
1 file changed
+67
-21
builtin/rev-list.c
+67
-21
@@ -364,6 +364,69 @@ static inline int parse_missing_action_value(const char *value)
364
return 0;
365
}
366
367
+static int try_bitmap_count(struct rev_info *revs)
368
+{
369
+ uint32_t commit_count;
370
+ int max_count;
371
+ struct bitmap_index *bitmap_git;
372
+
373
+ /* This function only handles counting, not general traversal. */
374
+ if (!revs->count)
375
+ return -1;
376
+
377
+ /*
378
+ * A bitmap result can't know left/right, etc, because we don't
379
+ * actually traverse.
380
+ */
381
+ if (revs->left_right || revs->cherry_mark)
382
+ return -1;
383
+
384
+ /*
385
+ * This must be saved before doing any walking, since the revision
386
+ * machinery will count it down to zero while traversing.
387
+ */
388
+ max_count = revs->max_count;
389
+
390
+ bitmap_git = prepare_bitmap_walk(revs);
391
+ if (!bitmap_git)
392
+ return -1;
393
+
394
+ count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
395
+ if (max_count >= 0 && max_count < commit_count)
396
+ commit_count = max_count;
397
+
398
+ printf("%d\n", commit_count);
399
+ free_bitmap_index(bitmap_git);
400
+ return 0;
401
+}
402
+
403
+static int try_bitmap_traversal(struct rev_info *revs)
404
+{
405
+ struct bitmap_index *bitmap_git;
406
+
407
+ /*
408
+ * We can't use a bitmap result with a traversal limit, since the set
409
+ * of commits we'd get would be essentially random.
410
+ */
411
+ if (revs->max_count >= 0)
412
+ return -1;
413
+
414
+ /*
415
+ * Our bitmap result will return all objects, and we're not
416
+ * yet prepared to show only particular types.
417
+ */
418
+ if (!revs->tag_objects || !revs->tree_objects || !revs->blob_objects)
419
+ return -1;
420
+
421
+ bitmap_git = prepare_bitmap_walk(revs);
422
+ if (!bitmap_git)
423
+ return -1;
424
+
425
+ traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
426
+ free_bitmap_index(bitmap_git);
427
+ return 0;
428
+}
429
+
430
int cmd_rev_list(int argc, const char **argv, const char *prefix)
431
{
432
struct rev_info revs;
@@ -534,27 +597,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
597
progress = start_delayed_progress(show_progress, 0);
598
599
if (use_bitmap_index) {
537
- if (revs.count && !revs.left_right && !revs.cherry_mark) {
538
- uint32_t commit_count;
539
- int max_count = revs.max_count;
540
- struct bitmap_index *bitmap_git;
541
- if ((bitmap_git = prepare_bitmap_walk(&revs))) {
542
- count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
543
- if (max_count >= 0 && max_count < commit_count)
544
- commit_count = max_count;
545
- printf("%d\n", commit_count);
546
- free_bitmap_index(bitmap_git);
547
- return 0;
548
- }
549
- } else if (revs.max_count < 0 &&
550
- revs.tag_objects && revs.tree_objects && revs.blob_objects) {
551
- struct bitmap_index *bitmap_git;
552
- if ((bitmap_git = prepare_bitmap_walk(&revs))) {
553
- traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
554
- free_bitmap_index(bitmap_git);
555
- return 0;
556
- }
557
- }
600
+ if (!try_bitmap_count(&revs))
601
+ return 0;
602
+ if (!try_bitmap_traversal(&revs))
603
+ return 0;
604
}
605
606
if (prepare_revision_walk(&revs))