repack-geometry: prepare for incremental MIDX repacking

Teach `pack_geometry_init()` to optionally restrict the set of repacking candidates to only packs in the tip MIDX layer when a `midx_layer_threshold` is configured. If the tip layer has fewer packs than the threshold, those packs are excluded entirely; otherwise only packs in that layer participate in the geometric repack. Also track whether any tip-layer packs were included in the rollup (`midx_tip_rewritten`), which a subsequent commit will use to decide how to update the MIDX chain after repacking. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed May 19, 2026 at 11:58 UTC d0ac3969f4b8a859d23c9f45cab873cbbf8cdfb8
2 files changed +39
repack-geometry.c
+35
@@ -4,6 +4,7 @@
4 #include "repack.h"
5 #include "repository.h"
6 #include "hex.h"
7 +#include "midx.h"
8 #include "packfile.h"
9
10 static uint32_t pack_geometry_weight(struct packed_git *p)
@@ -31,8 +32,28 @@ void pack_geometry_init(struct pack_geometry *geometry,
32 {
33 struct packed_git *p;
34 struct strbuf buf = STRBUF_INIT;
35 + struct multi_pack_index *m = get_multi_pack_index(existing->source);
36
37 repo_for_each_pack(existing->repo, p) {
38 + if (geometry->midx_layer_threshold_set && m &&
39 + p->multi_pack_index) {
40 + /*
41 + * When writing MIDX layers incrementally,
42 + * ignore packs unless they are in the most
43 + * recent MIDX layer *and* there are at least
44 + * 'midx_layer_threshold' packs in that layer.
45 + *
46 + * Otherwise 'p' is either in an older layer, or
47 + * the youngest layer does not have enough packs
48 + * to consider its packs as candidates for
49 + * repacking. In either of those cases we want
50 + * to ignore the pack.
51 + */
52 + if (m->num_packs < geometry->midx_layer_threshold ||
53 + !midx_layer_contains_pack(m, pack_basename(p)))
54 + continue;
55 + }
56 +
57 if (args->local && !p->pack_local)
58 /*
59 * When asked to only repack local packfiles we skip
@@ -173,6 +194,20 @@ void pack_geometry_split(struct pack_geometry *geometry)
194 geometry->promisor_split = compute_pack_geometry_split(geometry->promisor_pack,
195 geometry->promisor_pack_nr,
196 geometry->split_factor);
197 + for (uint32_t i = 0; i < geometry->split; i++) {
198 + struct packed_git *p = geometry->pack[i];
199 + /*
200 + * During incremental MIDX/bitmap repacking, any packs
201 + * included in the rollup are either (a) not MIDX'd, or
202 + * (b) contained in the tip layer iff it has at least
203 + * the threshold number of packs.
204 + *
205 + * In the latter case, we can safely conclude that the
206 + * tip of the MIDX chain will be rewritten.
207 + */
208 + if (p->multi_pack_index)
209 + geometry->midx_tip_rewritten = true;
210 + }
211 }
212
213 struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
repack.h
+4
@@ -108,6 +108,10 @@ struct pack_geometry {
108 uint32_t promisor_pack_nr, promisor_pack_alloc;
109 uint32_t promisor_split;
110
111 + uint32_t midx_layer_threshold;
112 + bool midx_layer_threshold_set;
113 + bool midx_tip_rewritten;
114 +
115 int split_factor;
116 };
117