gc: add gc.bigPackThreshold config

The --keep-largest-pack option is not very convenient to use because you need to tell gc to do this explicitly (and probably on just a few large repos). Add a config key that enables this mode when packs larger than a limit are found. Note that there's a slight behavior difference compared to --keep-largest-pack: all packs larger than the threshold are kept, not just the largest one. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Apr 15, 2018 at 17:36 UTC 55dfe13df9bb38809bc45b8d6d5c7f5bf0470c11
3 files changed +31 -8
Documentation/config.txt
+7
@@ -1558,6 +1558,13 @@ gc.autoDetach::
1558 Make `git gc --auto` return immediately and run in background
1559 if the system supports it. Default is true.
1560
1561 +gc.bigPackThreshold::
1562 + If non-zero, all packs larger than this limit are kept when
1563 + `git gc` is run. This is very similar to `--keep-base-pack`
1564 + except that all packs that meet the threshold are kept, not
1565 + just the base pack. Defaults to zero. Common unit suffixes of
1566 + 'k', 'm', or 'g' are supported.
1567 +
1568 gc.logExpiry::
1569 If the file gc.log exists, then `git gc --auto` won't run
1570 unless that file is more than 'gc.logExpiry' old. Default is
Documentation/git-gc.txt
+4 -2
@@ -56,7 +56,8 @@ single pack using `git repack -d -l`. Setting the value of `gc.auto`
56 to 0 disables automatic packing of loose objects.
57 +
58 If the number of packs exceeds the value of `gc.autoPackLimit`,
59 -then existing packs (except those marked with a `.keep` file)
59 +then existing packs (except those marked with a `.keep` file
60 +or over `gc.bigPackThreshold` limit)
61 are consolidated into a single pack by using the `-A` option of
62 'git repack'. Setting `gc.autoPackLimit` to 0 disables
63 automatic consolidation of packs.
@@ -86,7 +87,8 @@ be performed as well.
87
88 --keep-largest-pack::
89 All packs except the largest pack and those marked with a
89 - `.keep` files are consolidated into a single pack.
90 + `.keep` files are consolidated into a single pack. When this
91 + option is used, `gc.bigPackThreshold` is ignored.
92
93 Configuration
94 -------------
builtin/gc.c
+20 -6
@@ -41,6 +41,7 @@ static timestamp_t gc_log_expire_time;
41 static const char *gc_log_expire = "1.day.ago";
42 static const char *prune_expire = "2.weeks.ago";
43 static const char *prune_worktrees_expire = "3.months.ago";
44 +static unsigned long big_pack_threshold;
45
46 static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
47 static struct argv_array reflog = ARGV_ARRAY_INIT;
@@ -128,6 +129,8 @@ static void gc_config(void)
129 git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
130 git_config_get_expiry("gc.logexpiry", &gc_log_expire);
131
132 + git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold);
133 +
134 git_config(git_default_config, NULL);
135 }
136
@@ -166,14 +169,17 @@ static int too_many_loose_objects(void)
169 return needed;
170 }
171
169 -static void find_base_packs(struct string_list *packs)
172 +static void find_base_packs(struct string_list *packs, unsigned long limit)
173 {
174 struct packed_git *p, *base = NULL;
175
176 for (p = get_packed_git(the_repository); p; p = p->next) {
177 if (!p->pack_local)
178 continue;
176 - if (!base || base->pack_size < p->pack_size) {
179 + if (limit) {
180 + if (p->pack_size >= limit)
181 + string_list_append(packs, p->pack_name);
182 + } else if (!base || base->pack_size < p->pack_size) {
183 base = p;
184 }
185 }
@@ -244,9 +250,15 @@ static int need_to_gc(void)
250 * we run "repack -A -d -l". Otherwise we tell the caller
251 * there is no need.
252 */
247 - if (too_many_packs())
248 - add_repack_all_option(NULL);
249 - else if (too_many_loose_objects())
253 + if (too_many_packs()) {
254 + struct string_list keep_pack = STRING_LIST_INIT_NODUP;
255 +
256 + if (big_pack_threshold)
257 + find_base_packs(&keep_pack, big_pack_threshold);
258 +
259 + add_repack_all_option(&keep_pack);
260 + string_list_clear(&keep_pack, 0);
261 + } else if (too_many_loose_objects())
262 add_repack_incremental_option();
263 else
264 return 0;
@@ -464,7 +476,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
476
477 if (keep_base_pack != -1) {
478 if (keep_base_pack)
467 - find_base_packs(&keep_pack);
479 + find_base_packs(&keep_pack, 0);
480 + } else if (big_pack_threshold) {
481 + find_base_packs(&keep_pack, big_pack_threshold);
482 }
483
484 add_repack_all_option(&keep_pack);