Skip to content

Commit 1b17f64

Browse files
ttaylorrgitster
authored andcommitted
repack: allow --write-midx=incremental without --geometric
Previously, `--write-midx=incremental` required `--geometric` and would die() without it. Relax this restriction so that incremental MIDX repacking can be used independently. Without `--geometric`, the behavior is append-only: a single new MIDX layer is created containing whatever packs were written by the repack and appended to the existing chain (or a new chain is started). Existing layers are preserved as-is with no compaction or merging. Implement this via a new repack_make_midx_append_plan() that builds a plan consisting of a WRITE step for the freshly written packs followed by COPY steps for every existing MIDX layer. The existing compaction plan (repack_make_midx_compaction_plan) is used only when `--geometric` is active. Update the documentation to describe the behavior with and without `--geometric`, and replace the test that enforced the old restriction with one exercising append-only incremental MIDX repacking. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a00b0db commit 1b17f64

4 files changed

Lines changed: 103 additions & 18 deletions

File tree

Documentation/git-repack.adoc

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,14 +263,19 @@ linkgit:git-multi-pack-index[1]).
263263

264264
`incremental`;;
265265
Write an incremental MIDX chain instead of a single
266-
flat MIDX. This mode requires `--geometric`.
266+
flat MIDX.
267267
+
268-
The incremental mode maintains a chain of MIDX layers that is compacted
269-
over time using a geometric merging strategy. Each repack creates a new
270-
tip layer containing the newly written pack(s). Adjacent layers are then
271-
merged whenever the newer layer's object count exceeds
272-
`1/repack.midxSplitFactor` of the next deeper layer's count. Layers
273-
that do not meet this condition are retained as-is.
268+
Without `--geometric`, a new MIDX layer is appended to the existing
269+
chain (or a new chain is started) containing whatever packs were written
270+
by the repack. Existing layers are preserved as-is.
271+
+
272+
When combined with `--geometric`, the incremental mode maintains a chain
273+
of MIDX layers that is compacted over time using a geometric merging
274+
strategy. Each repack creates a new tip layer containing the newly
275+
written pack(s). Adjacent layers are then merged whenever the newer
276+
layer's object count exceeds `1/repack.midxSplitFactor` of the next
277+
deeper layer's count. Layers that do not meet this condition are
278+
retained as-is.
274279
+
275280
The result is that newer (tip) layers tend to contain many small packs
276281
with relatively few objects, while older (deeper) layers contain fewer,

builtin/repack.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,6 @@ int cmd_repack(int argc,
263263
if (pack_everything & PACK_CRUFT)
264264
pack_everything |= ALL_INTO_ONE;
265265

266-
if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL && !geometry.split_factor)
267-
die(_("--write-midx=incremental requires --geometric"));
268-
269266
if (write_bitmaps < 0) {
270267
if (write_midx == REPACK_WRITE_MIDX_NONE &&
271268
(!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))

repack-midx.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,60 @@ static void midx_compaction_step_release(struct midx_compaction_step *step)
555555
free(step->csum);
556556
}
557557

558+
/*
559+
* Build an append-only MIDX plan: a single WRITE step for the freshly
560+
* written packs, plus COPY steps for every existing layer. No
561+
* compaction or merging is performed.
562+
*/
563+
static void repack_make_midx_append_plan(struct repack_write_midx_opts *opts,
564+
struct midx_compaction_step **steps_p,
565+
size_t *steps_nr_p)
566+
{
567+
struct multi_pack_index *m;
568+
struct midx_compaction_step *steps = NULL;
569+
struct midx_compaction_step *step;
570+
size_t steps_nr = 0, steps_alloc = 0;
571+
572+
odb_reprepare(opts->existing->repo->objects);
573+
m = get_multi_pack_index(opts->existing->source);
574+
575+
if (opts->names->nr) {
576+
struct strbuf buf = STRBUF_INIT;
577+
uint32_t i;
578+
579+
ALLOC_GROW(steps, st_add(steps_nr, 1), steps_alloc);
580+
581+
step = &steps[steps_nr++];
582+
memset(step, 0, sizeof(*step));
583+
584+
step->type = MIDX_COMPACTION_STEP_WRITE;
585+
string_list_init_dup(&step->u.write);
586+
587+
for (i = 0; i < opts->names->nr; i++) {
588+
strbuf_reset(&buf);
589+
strbuf_addf(&buf, "pack-%s.idx",
590+
opts->names->items[i].string);
591+
string_list_append(&step->u.write, buf.buf);
592+
}
593+
594+
strbuf_release(&buf);
595+
}
596+
597+
for (; m; m = m->base_midx) {
598+
ALLOC_GROW(steps, st_add(steps_nr, 1), steps_alloc);
599+
600+
step = &steps[steps_nr++];
601+
memset(step, 0, sizeof(*step));
602+
603+
step->type = MIDX_COMPACTION_STEP_COPY;
604+
step->u.copy = m;
605+
step->objects_nr = m->num_objects;
606+
}
607+
608+
*steps_p = steps;
609+
*steps_nr_p = steps_nr;
610+
}
611+
558612
static int repack_make_midx_compaction_plan(struct repack_write_midx_opts *opts,
559613
struct midx_compaction_step **steps_p,
560614
size_t *steps_nr_p)
@@ -911,9 +965,13 @@ static int write_midx_incremental(struct repack_write_midx_opts *opts)
911965
goto done;
912966
}
913967

914-
if (repack_make_midx_compaction_plan(opts, &steps, &steps_nr) < 0) {
915-
ret = error(_("unable to generate compaction plan"));
916-
goto done;
968+
if (opts->geometry->split_factor) {
969+
if (repack_make_midx_compaction_plan(opts, &steps, &steps_nr) < 0) {
970+
ret = error(_("unable to generate compaction plan"));
971+
goto done;
972+
}
973+
} else {
974+
repack_make_midx_append_plan(opts, &steps, &steps_nr);
917975
}
918976

919977
for (i = 0; i < steps_nr; i++) {

t/t7705-repack-incremental-midx.sh

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,36 @@ create_layers () {
6363
done
6464
}
6565

66-
test_expect_success '--write-midx=incremental requires --geometric' '
67-
test_must_fail git repack --write-midx=incremental 2>err &&
66+
test_expect_success '--write-midx=incremental without --geometric' '
67+
git init incremental-without-geometric &&
68+
(
69+
cd incremental-without-geometric &&
70+
71+
git config maintenance.auto false &&
72+
73+
test_commit first &&
74+
git repack -d &&
75+
76+
test_commit second &&
77+
git repack --write-midx=incremental &&
78+
79+
git multi-pack-index verify &&
80+
test_line_count = 1 $midx_chain &&
81+
cp $midx_chain $midx_chain.before &&
6882
69-
test_grep -- "--write-midx=incremental requires --geometric" err
83+
# A second repack appends a new layer without
84+
# disturbing the existing one.
85+
test_commit third &&
86+
git repack --write-midx=incremental &&
87+
88+
git multi-pack-index verify &&
89+
test_line_count = 2 $midx_chain &&
90+
head -n 1 $midx_chain.before >expect &&
91+
head -n 1 $midx_chain >actual &&
92+
test_cmp expect actual &&
93+
94+
git fsck
95+
)
7096
'
7197

7298
test_expect_success 'below layer threshold, tip packs excluded' '
@@ -334,8 +360,7 @@ test_expect_success 'kept packs are excluded from repack' '
334360
# entirely, so no rollup occurs as there is only one
335361
# non-kept pack. A new MIDX layer is written containing
336362
# that pack.
337-
git repack --geometric=2 -d --write-midx=incremental \
338-
--write-bitmap-index &&
363+
git repack --geometric=2 -d --write-midx=incremental &&
339364
340365
test-tool read-midx $objdir >actual &&
341366
grep "^pack-.*\.idx$" actual >actual.packs &&

0 commit comments

Comments
 (0)