builtin/gc: extract object database optimizations into separate function

Extract the object database optimization logic from `cmd_gc()` into a new `maintenance_task_odb()` helper function. This is a pure refactoring with no intended functional change. Note that the message that notifies the user about too many loose objects is moved into the new function, as well. It is inherently an implementation detail of how the "files" source works, and as a consequence we'll move it around in a later commit, as well. This reordering means that the warning may now be printed at a different point in time, but it's not expected that this will have any practical implications. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 13, 2026 at 07:52 UTC e86fe6fe62d0fb5b54a1afed6166d3e27d28f081
1 file changed +49 -30
builtin/gc.c
+49 -30
@@ -839,6 +839,53 @@ static int gc_foreground_tasks(struct maintenance_run_opts *opts,
839 return 0;
840 }
841
842 +static int maintenance_task_odb(struct maintenance_run_opts *opts,
843 + struct gc_config *cfg,
844 + struct strvec *repack_args)
845 +{
846 + struct child_process repack_cmd = CHILD_PROCESS_INIT;
847 + int ret;
848 +
849 + if (the_repository->repository_format_precious_objects)
850 + return 0;
851 +
852 + repack_cmd.git_cmd = 1;
853 + repack_cmd.odb_to_close = the_repository->objects;
854 + strvec_pushv(&repack_cmd.args, repack_args->v);
855 + if (run_command(&repack_cmd)) {
856 + ret = error(FAILED_RUN, repack_args->v[0]);
857 + goto out;
858 + }
859 +
860 + if (cfg->prune_expire) {
861 + struct child_process prune_cmd = CHILD_PROCESS_INIT;
862 +
863 + strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL);
864 + /* run `git prune` even if using cruft packs */
865 + strvec_push(&prune_cmd.args, cfg->prune_expire);
866 + if (opts->quiet)
867 + strvec_push(&prune_cmd.args, "--no-progress");
868 + if (repo_has_promisor_remote(the_repository))
869 + strvec_push(&prune_cmd.args,
870 + "--exclude-promisor-objects");
871 + prune_cmd.git_cmd = 1;
872 +
873 + if (run_command(&prune_cmd)) {
874 + ret = error(FAILED_RUN, prune_cmd.args.v[0]);
875 + goto out;
876 + }
877 + }
878 +
879 + if (opts->auto_flag && too_many_loose_objects(cfg->gc_auto_threshold))
880 + warning(_("There are too many unreachable loose objects; "
881 + "run 'git prune' to remove them."));
882 +
883 + ret = 0;
884 +
885 +out:
886 + return ret;
887 +}
888 +
889 int cmd_gc(int argc,
890 const char **argv,
891 const char *prefix,
@@ -1018,32 +1065,8 @@ int cmd_gc(int argc,
1065 if (maintenance_task_rerere_gc(&opts, &cfg))
1066 die(FAILED_RUN, "rerere");
1067
1021 - if (!the_repository->repository_format_precious_objects) {
1022 - struct child_process repack_cmd = CHILD_PROCESS_INIT;
1023 -
1024 - repack_cmd.git_cmd = 1;
1025 - repack_cmd.odb_to_close = the_repository->objects;
1026 - strvec_pushv(&repack_cmd.args, repack_args.v);
1027 - if (run_command(&repack_cmd))
1028 - die(FAILED_RUN, repack_args.v[0]);
1029 -
1030 - if (cfg.prune_expire) {
1031 - struct child_process prune_cmd = CHILD_PROCESS_INIT;
1032 -
1033 - strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL);
1034 - /* run `git prune` even if using cruft packs */
1035 - strvec_push(&prune_cmd.args, cfg.prune_expire);
1036 - if (opts.quiet)
1037 - strvec_push(&prune_cmd.args, "--no-progress");
1038 - if (repo_has_promisor_remote(the_repository))
1039 - strvec_push(&prune_cmd.args,
1040 - "--exclude-promisor-objects");
1041 - prune_cmd.git_cmd = 1;
1042 -
1043 - if (run_command(&prune_cmd))
1044 - die(FAILED_RUN, prune_cmd.args.v[0]);
1045 - }
1046 - }
1068 + if (maintenance_task_odb(&opts, &cfg, &repack_args))
1069 + die(NULL);
1070
1071 report_garbage = report_pack_garbage;
1072 odb_reprepare(the_repository->objects);
@@ -1057,10 +1080,6 @@ int cmd_gc(int argc,
1080 !opts.quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
1081 NULL);
1082
1060 - if (opts.auto_flag && too_many_loose_objects(cfg.gc_auto_threshold))
1061 - warning(_("There are too many unreachable loose objects; "
1062 - "run 'git prune' to remove them."));
1063 -
1083 if (!daemonized) {
1084 char *path = repo_git_path(the_repository, "gc.log");
1085 unlink(path);