builtin/gc: inline config values specific to the "files" backend

The `struct gc_config` contains a set of values that we read via the Git repository's configuration. Several of those values that are consumed by the object database optimization logic are inherently specific to the "files" config. In a later commit we'll make the logic to optimize object databases pluggable. So by carrying these "files"-backend specific values in the generic config struct means that other backends would have to worry about these values, too. This feels somewhat dirty, as implementation- specific details should live with the backends themselves. Inline these values directly at the call sites that need them instead. 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 57ca517baca6c28ed11e923ed7f25bb5c7af8909
1 file changed +53 -62
builtin/gc.c
+53 -62
@@ -130,22 +130,11 @@ struct gc_config {
130 unsigned long max_cruft_size;
131 int aggressive_depth;
132 int aggressive_window;
133 - int gc_auto_threshold;
134 - int gc_auto_pack_limit;
133 int detach_auto;
134 char *gc_log_expire;
135 char *prune_expire;
136 char *prune_worktrees_expire;
139 - char *repack_filter;
140 - char *repack_filter_to;
137 char *repack_expire_to;
142 - unsigned long big_pack_threshold;
143 - unsigned long max_delta_cache_size;
144 - /*
145 - * Remove this member from gc_config once repo_settings is passed
146 - * through the callchain.
147 - */
148 - size_t delta_base_cache_limit;
138 };
139
140 #define GC_CONFIG_INIT { \
@@ -154,14 +143,10 @@ struct gc_config {
143 .cruft_packs = 1, \
144 .aggressive_depth = 50, \
145 .aggressive_window = 250, \
157 - .gc_auto_threshold = 6700, \
158 - .gc_auto_pack_limit = 50, \
146 .detach_auto = 1, \
147 .gc_log_expire = xstrdup("1.day.ago"), \
148 .prune_expire = xstrdup("2.weeks.ago"), \
149 .prune_worktrees_expire = xstrdup("3.months.ago"), \
163 - .max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE, \
164 - .delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT, \
150 }
151
152 static void gc_config_release(struct gc_config *cfg)
@@ -169,15 +154,12 @@ static void gc_config_release(struct gc_config *cfg)
154 free(cfg->gc_log_expire);
155 free(cfg->prune_expire);
156 free(cfg->prune_worktrees_expire);
172 - free(cfg->repack_filter);
173 - free(cfg->repack_filter_to);
157 }
158
159 static void gc_config(struct gc_config *cfg)
160 {
161 const char *value;
162 char *owned = NULL;
180 - unsigned long ulongval;
163
164 if (!repo_config_get_value(the_repository, "gc.packrefs", &value)) {
165 if (value && !strcmp(value, "notbare"))
@@ -192,8 +174,6 @@ static void gc_config(struct gc_config *cfg)
174
175 repo_config_get_int(the_repository, "gc.aggressivewindow", &cfg->aggressive_window);
176 repo_config_get_int(the_repository, "gc.aggressivedepth", &cfg->aggressive_depth);
195 - repo_config_get_int(the_repository, "gc.auto", &cfg->gc_auto_threshold);
196 - repo_config_get_int(the_repository, "gc.autopacklimit", &cfg->gc_auto_pack_limit);
177 repo_config_get_bool(the_repository, "gc.autodetach", &cfg->detach_auto);
178 repo_config_get_bool(the_repository, "gc.cruftpacks", &cfg->cruft_packs);
179 repo_config_get_ulong(the_repository, "gc.maxcruftsize", &cfg->max_cruft_size);
@@ -213,22 +193,6 @@ static void gc_config(struct gc_config *cfg)
193 cfg->gc_log_expire = owned;
194 }
195
216 - repo_config_get_ulong(the_repository, "gc.bigpackthreshold", &cfg->big_pack_threshold);
217 - repo_config_get_ulong(the_repository, "pack.deltacachesize", &cfg->max_delta_cache_size);
218 -
219 - if (!repo_config_get_ulong(the_repository, "core.deltabasecachelimit", &ulongval))
220 - cfg->delta_base_cache_limit = ulongval;
221 -
222 - if (!repo_config_get_string(the_repository, "gc.repackfilter", &owned)) {
223 - free(cfg->repack_filter);
224 - cfg->repack_filter = owned;
225 - }
226 -
227 - if (!repo_config_get_string(the_repository, "gc.repackfilterto", &owned)) {
228 - free(cfg->repack_filter_to);
229 - cfg->repack_filter_to = owned;
230 - }
231 -
196 repo_config(the_repository, git_default_config, NULL);
197 }
198
@@ -504,12 +468,12 @@ static struct packed_git *find_base_packs(struct string_list *packs,
468 return base;
469 }
470
507 -static int too_many_packs(struct gc_config *cfg)
471 +static int too_many_packs(int gc_auto_pack_limit)
472 {
473 struct packed_git *p;
474 int cnt = 0;
475
512 - if (cfg->gc_auto_pack_limit <= 0)
476 + if (gc_auto_pack_limit <= 0)
477 return 0;
478
479 repo_for_each_pack(the_repository, p) {
@@ -523,7 +487,7 @@ static int too_many_packs(struct gc_config *cfg)
487 */
488 cnt++;
489 }
526 - return cfg->gc_auto_pack_limit < cnt;
490 + return gc_auto_pack_limit < cnt;
491 }
492
493 static uint64_t total_ram(void)
@@ -571,9 +535,10 @@ static uint64_t total_ram(void)
535 return 0;
536 }
537
574 -static uint64_t estimate_repack_memory(struct gc_config *cfg,
575 - struct packed_git *pack)
538 +static uint64_t estimate_repack_memory(struct packed_git *pack)
539 {
540 + unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
541 + unsigned long delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT;
542 unsigned long nr_objects;
543 size_t os_cache, heap;
544
@@ -584,6 +549,9 @@ static uint64_t estimate_repack_memory(struct gc_config *cfg,
549 if (!pack || !nr_objects)
550 return 0;
551
552 + repo_config_get_ulong(the_repository, "pack.deltacachesize", &max_delta_cache_size);
553 + repo_config_get_ulong(the_repository, "core.deltabasecachelimit", &delta_base_cache_limit);
554 +
555 /*
556 * First we have to scan through at least one pack.
557 * Assume enough room in OS file cache to keep the entire pack
@@ -611,9 +579,9 @@ static uint64_t estimate_repack_memory(struct gc_config *cfg,
579 * read_sha1_file() (either at delta calculation phase, or
580 * writing phase) also fills up the delta base cache
581 */
614 - heap += cfg->delta_base_cache_limit;
582 + heap += delta_base_cache_limit;
583 /* and of course pack-objects has its own delta cache */
616 - heap += cfg->max_delta_cache_size;
584 + heap += max_delta_cache_size;
585
586 return os_cache + heap;
587 }
@@ -629,6 +597,12 @@ static void add_repack_all_option(struct gc_config *cfg,
597 struct string_list *keep_pack,
598 struct strvec *args)
599 {
600 + char *repack_filter = NULL;
601 + char *repack_filter_to = NULL;
602 +
603 + repo_config_get_string(the_repository, "gc.repackfilter", &repack_filter);
604 + repo_config_get_string(the_repository, "gc.repackfilterto", &repack_filter_to);
605 +
606 if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")
607 && !(cfg->cruft_packs && cfg->repack_expire_to))
608 strvec_push(args, "-a");
@@ -650,10 +624,13 @@ static void add_repack_all_option(struct gc_config *cfg,
624 if (keep_pack)
625 for_each_string_list(keep_pack, keep_one_pack, args);
626
653 - if (cfg->repack_filter && *cfg->repack_filter)
654 - strvec_pushf(args, "--filter=%s", cfg->repack_filter);
655 - if (cfg->repack_filter_to && *cfg->repack_filter_to)
656 - strvec_pushf(args, "--filter-to=%s", cfg->repack_filter_to);
627 + if (repack_filter && *repack_filter)
628 + strvec_pushf(args, "--filter=%s", repack_filter);
629 + if (repack_filter_to && *repack_filter_to)
630 + strvec_pushf(args, "--filter-to=%s", repack_filter_to);
631 +
632 + free(repack_filter);
633 + free(repack_filter_to);
634 }
635
636 static void add_repack_incremental_option(struct strvec *args)
@@ -661,16 +638,24 @@ static void add_repack_incremental_option(struct strvec *args)
638 strvec_push(args, "--no-write-bitmap-index");
639 }
640
664 -static int need_to_gc(struct gc_config *cfg)
641 +static int need_to_gc(struct repository *repo)
642 {
643 + int gc_auto_threshold = 6700;
644 + int gc_auto_pack_limit = 50;
645 +
646 + repo_config_get_int(repo, "gc.auto", &gc_auto_threshold);
647 + repo_config_get_int(repo, "gc.autopacklimit", &gc_auto_pack_limit);
648 +
649 /*
650 * Setting gc.auto to 0 or negative can disable the
651 * automatic gc.
652 */
670 - if (cfg->gc_auto_threshold <= 0)
653 + if (gc_auto_threshold <= 0)
654 return 0;
672 - if (!too_many_packs(cfg) && !too_many_loose_objects(cfg->gc_auto_threshold))
655 + if (!too_many_packs(gc_auto_pack_limit) &&
656 + !too_many_loose_objects(gc_auto_threshold))
657 return 0;
658 +
659 return 1;
660 }
661
@@ -807,8 +792,15 @@ static int maintenance_task_odb(struct maintenance_run_opts *opts,
792 int aggressive)
793 {
794 struct child_process repack_cmd = CHILD_PROCESS_INIT;
795 + unsigned long big_pack_threshold = 0;
796 + int gc_auto_threshold = 6700;
797 + int gc_auto_pack_limit = 50;
798 int ret;
799
800 + repo_config_get_int(the_repository, "gc.auto", &gc_auto_threshold);
801 + repo_config_get_int(the_repository, "gc.autopacklimit", &gc_auto_pack_limit);
802 + repo_config_get_ulong(the_repository, "gc.bigpackthreshold", &big_pack_threshold);
803 +
804 if (the_repository->repository_format_precious_objects)
805 return 0;
806
@@ -843,19 +835,18 @@ static int maintenance_task_odb(struct maintenance_run_opts *opts,
835 if (keep_largest_pack != -1) {
836 if (keep_largest_pack)
837 find_base_packs(&keep_pack, 0);
846 - } else if (cfg->big_pack_threshold) {
847 - find_base_packs(&keep_pack, cfg->big_pack_threshold);
838 + } else if (big_pack_threshold) {
839 + find_base_packs(&keep_pack, big_pack_threshold);
840 }
841
842 add_repack_all_option(cfg, &keep_pack, &repack_cmd.args);
843 string_list_clear(&keep_pack, 0);
852 - } else if (too_many_packs(cfg)) {
844 + } else if (too_many_packs(gc_auto_pack_limit)) {
845 struct string_list keep_pack = STRING_LIST_INIT_NODUP;
846
855 - if (cfg->big_pack_threshold) {
856 - find_base_packs(&keep_pack, cfg->big_pack_threshold);
857 - if (keep_pack.nr >= cfg->gc_auto_pack_limit) {
858 - cfg->big_pack_threshold = 0;
847 + if (big_pack_threshold) {
848 + find_base_packs(&keep_pack, big_pack_threshold);
849 + if (keep_pack.nr >= gc_auto_pack_limit) {
850 string_list_clear(&keep_pack, 0);
851 find_base_packs(&keep_pack, 0);
852 }
@@ -864,7 +855,7 @@ static int maintenance_task_odb(struct maintenance_run_opts *opts,
855 uint64_t mem_have, mem_want;
856
857 mem_have = total_ram();
867 - mem_want = estimate_repack_memory(cfg, p);
858 + mem_want = estimate_repack_memory(p);
859
860 /*
861 * Only allow 1/2 of memory for pack-objects, leave
@@ -905,7 +896,7 @@ static int maintenance_task_odb(struct maintenance_run_opts *opts,
896 }
897 }
898
908 - if (opts->auto_flag && too_many_loose_objects(cfg->gc_auto_threshold))
899 + if (opts->auto_flag && too_many_loose_objects(gc_auto_threshold))
900 warning(_("There are too many unreachable loose objects; "
901 "run 'git prune' to remove them."));
902
@@ -994,7 +985,7 @@ int cmd_gc(int argc,
985 /*
986 * Auto-gc should be least intrusive as possible.
987 */
997 - if (!need_to_gc(&cfg) || run_hooks(the_repository, "pre-auto-gc")) {
988 + if (!need_to_gc(the_repository) || run_hooks(the_repository, "pre-auto-gc")) {
989 ret = 0;
990 goto out;
991 }
@@ -1291,9 +1282,9 @@ static int maintenance_task_gc_background(struct maintenance_run_opts *opts,
1282 return run_command(&child);
1283 }
1284
1294 -static int gc_condition(struct gc_config *cfg)
1285 +static int gc_condition(struct gc_config *cfg UNUSED)
1286 {
1296 - return need_to_gc(cfg);
1287 + return need_to_gc(the_repository);
1288 }
1289
1290 static int prune_packed(struct maintenance_run_opts *opts)