builtin/gc: forward git-gc(1)'s `--auto` flag when packing refs

Forward the `--auto` flag to git-pack-refs(1) when it has been invoked with this flag itself. This does not change anything for the "files" backend, which will continue to eagerly pack refs. But it does ensure that the "reftable" backend only compacts refs as required. This change does not impact git-maintenance(1) because this command will in fact never run the pack-refs task when run with `--auto`. This issue will be addressed in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 25, 2024 at 11:03 UTC bfc2f9eb8e83f394cc397f978c833edced507923
2 files changed +28 -12
builtin/gc.c
+12 -9
@@ -212,6 +212,9 @@ static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *
212
213 cmd.git_cmd = 1;
214 strvec_pushl(&cmd.args, "pack-refs", "--all", "--prune", NULL);
215 + if (opts->auto_flag)
216 + strvec_push(&cmd.args, "--auto");
217 +
218 return run_command(&cmd);
219 }
220
@@ -572,7 +575,7 @@ done:
575 return ret;
576 }
577
575 -static void gc_before_repack(void)
578 +static void gc_before_repack(struct maintenance_run_opts *opts)
579 {
580 /*
581 * We may be called twice, as both the pre- and
@@ -583,7 +586,7 @@ static void gc_before_repack(void)
586 if (done++)
587 return;
588
586 - if (pack_refs && maintenance_task_pack_refs(NULL))
589 + if (pack_refs && maintenance_task_pack_refs(opts))
590 die(FAILED_RUN, "pack-refs");
591
592 if (prune_reflogs) {
@@ -599,7 +602,6 @@ static void gc_before_repack(void)
602 int cmd_gc(int argc, const char **argv, const char *prefix)
603 {
604 int aggressive = 0;
602 - int auto_gc = 0;
605 int quiet = 0;
606 int force = 0;
607 const char *name;
@@ -608,6 +610,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
610 int keep_largest_pack = -1;
611 timestamp_t dummy;
612 struct child_process rerere_cmd = CHILD_PROCESS_INIT;
613 + struct maintenance_run_opts opts = {0};
614
615 struct option builtin_gc_options[] = {
616 OPT__QUIET(&quiet, N_("suppress progress reporting")),
@@ -618,7 +621,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
621 OPT_MAGNITUDE(0, "max-cruft-size", &max_cruft_size,
622 N_("with --cruft, limit the size of new cruft packs")),
623 OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
621 - OPT_BOOL_F(0, "auto", &auto_gc, N_("enable auto-gc mode"),
624 + OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"),
625 PARSE_OPT_NOCOMPLETE),
626 OPT_BOOL_F(0, "force", &force,
627 N_("force running gc even if there may be another gc running"),
@@ -663,7 +666,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
666 if (quiet)
667 strvec_push(&repack, "-q");
668
666 - if (auto_gc) {
669 + if (opts.auto_flag) {
670 /*
671 * Auto-gc should be least intrusive as possible.
672 */
@@ -688,7 +691,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
691
692 if (lock_repo_for_gc(force, &pid))
693 return 0;
691 - gc_before_repack(); /* dies on failure */
694 + gc_before_repack(&opts); /* dies on failure */
695 delete_tempfile(&pidfile);
696
697 /*
@@ -713,7 +716,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
716
717 name = lock_repo_for_gc(force, &pid);
718 if (name) {
716 - if (auto_gc)
719 + if (opts.auto_flag)
720 return 0; /* be quiet on --auto */
721 die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"),
722 name, (uintmax_t)pid);
@@ -728,7 +731,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
731 atexit(process_log_file_at_exit);
732 }
733
731 - gc_before_repack();
734 + gc_before_repack(&opts);
735
736 if (!repository_format_precious_objects) {
737 struct child_process repack_cmd = CHILD_PROCESS_INIT;
@@ -783,7 +786,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
786 !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
787 NULL);
788
786 - if (auto_gc && too_many_loose_objects())
789 + if (opts.auto_flag && too_many_loose_objects())
790 warning(_("There are too many unreachable loose objects; "
791 "run 'git prune' to remove them."));
792
t/t0610-reftable-basics.sh
+16 -3
@@ -387,7 +387,9 @@ test_expect_success 'pack-refs: compaction raises locking errors' '
387 test_cmp expect err
388 '
389
390 -test_expect_success 'pack-refs: auto compaction' '
390 +for command in pack-refs gc
391 +do
392 +test_expect_success "$command: auto compaction" '
393 test_when_finished "rm -rf repo" &&
394 git init repo &&
395 (
@@ -395,14 +397,24 @@ test_expect_success 'pack-refs: auto compaction' '
397
398 test_commit A &&
399
400 + # We need a bit of setup to ensure that git-gc(1) actually
401 + # triggers, and that it does not write anything to the refdb.
402 + git config gc.auto 1 &&
403 + git config gc.autoDetach 0 &&
404 + git config gc.reflogExpire never &&
405 + git config gc.reflogExpireUnreachable never &&
406 + test_oid blob17_1 | git hash-object -w --stdin &&
407 +
408 # The tables should have been auto-compacted, and thus auto
409 # compaction should not have to do anything.
410 ls -1 .git/reftable >tables-expect &&
411 test_line_count = 4 tables-expect &&
402 - git pack-refs --auto &&
412 + git $command --auto &&
413 ls -1 .git/reftable >tables-actual &&
414 test_cmp tables-expect tables-actual &&
415
416 + test_oid blob17_2 | git hash-object -w --stdin &&
417 +
418 # Lock all tables write some refs. Auto-compaction will be
419 # unable to compact tables and thus fails gracefully, leaving
420 # the stack in a sub-optimal state.
@@ -416,10 +428,11 @@ test_expect_success 'pack-refs: auto compaction' '
428 rm .git/reftable/*.lock &&
429 test_line_count = 5 .git/reftable/tables.list &&
430
419 - git pack-refs --auto &&
431 + git $command --auto &&
432 test_line_count = 1 .git/reftable/tables.list
433 )
434 '
435 +done
436
437 test_expect_success 'pack-refs: prunes stale tables' '
438 test_when_finished "rm -rf repo" &&