builtin/gc: avoid global state in `gc_before_repack()`

The `gc_before_repack()` should only ever run once in git-gc(1), but we may end up calling it twice when the "--detach" flag is passed. The duplicated call is avoided though via a static flag in this function. This pattern is somewhat unintuitive though. Refactor it to drop the static flag and instead guard the second call of `gc_before_repack()` via `opts.detach`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jun 3, 2025 at 16:01 UTC d2b084c66037f1a77b3e061ae7e4d96cbdbf6c05
1 file changed +9 -15
builtin/gc.c
+9 -15
@@ -816,22 +816,14 @@ done:
816 return ret;
817 }
818
819 -static void gc_before_repack(struct maintenance_run_opts *opts,
820 - struct gc_config *cfg)
819 +static int gc_before_repack(struct maintenance_run_opts *opts,
820 + struct gc_config *cfg)
821 {
822 - /*
823 - * We may be called twice, as both the pre- and
824 - * post-daemonized phases will call us, but running these
825 - * commands more than once is pointless and wasteful.
826 - */
827 - static int done = 0;
828 - if (done++)
829 - return;
830 -
822 if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg))
832 - die(FAILED_RUN, "pack-refs");
823 + return error(FAILED_RUN, "pack-refs");
824 if (cfg->prune_reflogs && maintenance_task_reflog_expire(opts, cfg))
834 - die(FAILED_RUN, "reflog");
825 + return error(FAILED_RUN, "reflog");
826 + return 0;
827 }
828
829 int cmd_gc(int argc,
@@ -965,7 +957,8 @@ int cmd_gc(int argc,
957 goto out;
958 }
959
968 - gc_before_repack(&opts, &cfg); /* dies on failure */
960 + if (gc_before_repack(&opts, &cfg) < 0)
961 + die(NULL);
962 delete_tempfile(&pidfile);
963
964 /*
@@ -995,7 +988,8 @@ int cmd_gc(int argc,
988 free(path);
989 }
990
998 - gc_before_repack(&opts, &cfg);
991 + if (opts.detach <= 0)
992 + gc_before_repack(&opts, &cfg);
993
994 if (!repository_format_precious_objects) {
995 struct child_process repack_cmd = CHILD_PROCESS_INIT;