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>main
parent
938af89260
commit
06733a50ee
|
|
@ -263,14 +263,19 @@ linkgit:git-multi-pack-index[1]).
|
|||
|
||||
`incremental`;;
|
||||
Write an incremental MIDX chain instead of a single
|
||||
flat MIDX. This mode requires `--geometric`.
|
||||
flat MIDX.
|
||||
+
|
||||
The incremental mode maintains a chain of MIDX layers that is compacted
|
||||
over time using a geometric merging strategy. Each repack creates a new
|
||||
tip layer containing the newly written pack(s). Adjacent layers are then
|
||||
merged whenever the newer layer's object count exceeds
|
||||
`1/repack.midxSplitFactor` of the next deeper layer's count. Layers
|
||||
that do not meet this condition are retained as-is.
|
||||
Without `--geometric`, a new MIDX layer is appended to the existing
|
||||
chain (or a new chain is started) containing whatever packs were written
|
||||
by the repack. Existing layers are preserved as-is.
|
||||
+
|
||||
When combined with `--geometric`, the incremental mode maintains a chain
|
||||
of MIDX layers that is compacted over time using a geometric merging
|
||||
strategy. Each repack creates a new tip layer containing the newly
|
||||
written pack(s). Adjacent layers are then merged whenever the newer
|
||||
layer's object count exceeds `1/repack.midxSplitFactor` of the next
|
||||
deeper layer's count. Layers that do not meet this condition are
|
||||
retained as-is.
|
||||
+
|
||||
The result is that newer (tip) layers tend to contain many small packs
|
||||
with relatively few objects, while older (deeper) layers contain fewer,
|
||||
|
|
|
|||
|
|
@ -263,9 +263,6 @@ int cmd_repack(int argc,
|
|||
if (pack_everything & PACK_CRUFT)
|
||||
pack_everything |= ALL_INTO_ONE;
|
||||
|
||||
if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL && !geometry.split_factor)
|
||||
die(_("--write-midx=incremental requires --geometric"));
|
||||
|
||||
if (write_bitmaps < 0) {
|
||||
if (write_midx == REPACK_WRITE_MIDX_NONE &&
|
||||
(!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))
|
||||
|
|
|
|||
|
|
@ -548,6 +548,60 @@ static void midx_compaction_step_release(struct midx_compaction_step *step)
|
|||
free(step->csum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build an append-only MIDX plan: a single WRITE step for the freshly
|
||||
* written packs, plus COPY steps for every existing layer. No
|
||||
* compaction or merging is performed.
|
||||
*/
|
||||
static void repack_make_midx_append_plan(struct repack_write_midx_opts *opts,
|
||||
struct midx_compaction_step **steps_p,
|
||||
size_t *steps_nr_p)
|
||||
{
|
||||
struct multi_pack_index *m;
|
||||
struct midx_compaction_step *steps = NULL;
|
||||
struct midx_compaction_step *step;
|
||||
size_t steps_nr = 0, steps_alloc = 0;
|
||||
|
||||
odb_reprepare(opts->existing->repo->objects);
|
||||
m = get_multi_pack_index(opts->existing->source);
|
||||
|
||||
if (opts->names->nr) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
uint32_t i;
|
||||
|
||||
ALLOC_GROW(steps, st_add(steps_nr, 1), steps_alloc);
|
||||
|
||||
step = &steps[steps_nr++];
|
||||
memset(step, 0, sizeof(*step));
|
||||
|
||||
step->type = MIDX_COMPACTION_STEP_WRITE;
|
||||
string_list_init_dup(&step->u.write);
|
||||
|
||||
for (i = 0; i < opts->names->nr; i++) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "pack-%s.idx",
|
||||
opts->names->items[i].string);
|
||||
string_list_append(&step->u.write, buf.buf);
|
||||
}
|
||||
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
for (; m; m = m->base_midx) {
|
||||
ALLOC_GROW(steps, st_add(steps_nr, 1), steps_alloc);
|
||||
|
||||
step = &steps[steps_nr++];
|
||||
memset(step, 0, sizeof(*step));
|
||||
|
||||
step->type = MIDX_COMPACTION_STEP_COPY;
|
||||
step->u.copy = m;
|
||||
step->objects_nr = m->num_objects;
|
||||
}
|
||||
|
||||
*steps_p = steps;
|
||||
*steps_nr_p = steps_nr;
|
||||
}
|
||||
|
||||
static int repack_make_midx_compaction_plan(struct repack_write_midx_opts *opts,
|
||||
struct midx_compaction_step **steps_p,
|
||||
size_t *steps_nr_p)
|
||||
|
|
@ -904,9 +958,13 @@ static int write_midx_incremental(struct repack_write_midx_opts *opts)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (repack_make_midx_compaction_plan(opts, &steps, &steps_nr) < 0) {
|
||||
ret = error(_("unable to generate compaction plan"));
|
||||
goto done;
|
||||
if (opts->geometry->split_factor) {
|
||||
if (repack_make_midx_compaction_plan(opts, &steps, &steps_nr) < 0) {
|
||||
ret = error(_("unable to generate compaction plan"));
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
repack_make_midx_append_plan(opts, &steps, &steps_nr);
|
||||
}
|
||||
|
||||
for (i = 0; i < steps_nr; i++) {
|
||||
|
|
|
|||
|
|
@ -63,10 +63,36 @@ create_layers () {
|
|||
done
|
||||
}
|
||||
|
||||
test_expect_success '--write-midx=incremental requires --geometric' '
|
||||
test_must_fail git repack --write-midx=incremental 2>err &&
|
||||
test_expect_success '--write-midx=incremental without --geometric' '
|
||||
git init incremental-without-geometric &&
|
||||
(
|
||||
cd incremental-without-geometric &&
|
||||
|
||||
test_grep -- "--write-midx=incremental requires --geometric" err
|
||||
git config maintenance.auto false &&
|
||||
|
||||
test_commit first &&
|
||||
git repack -d &&
|
||||
|
||||
test_commit second &&
|
||||
git repack --write-midx=incremental &&
|
||||
|
||||
git multi-pack-index verify &&
|
||||
test_line_count = 1 $midx_chain &&
|
||||
cp $midx_chain $midx_chain.before &&
|
||||
|
||||
# A second repack appends a new layer without
|
||||
# disturbing the existing one.
|
||||
test_commit third &&
|
||||
git repack --write-midx=incremental &&
|
||||
|
||||
git multi-pack-index verify &&
|
||||
test_line_count = 2 $midx_chain &&
|
||||
head -n 1 $midx_chain.before >expect &&
|
||||
head -n 1 $midx_chain >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
git fsck
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'below layer threshold, tip packs excluded' '
|
||||
|
|
@ -334,8 +360,7 @@ test_expect_success 'kept packs are excluded from repack' '
|
|||
# entirely, so no rollup occurs as there is only one
|
||||
# non-kept pack. A new MIDX layer is written containing
|
||||
# that pack.
|
||||
git repack --geometric=2 -d --write-midx=incremental \
|
||||
--write-bitmap-index &&
|
||||
git repack --geometric=2 -d --write-midx=incremental &&
|
||||
|
||||
test-tool read-midx $objdir >actual &&
|
||||
grep "^pack-.*\.idx$" actual >actual.packs &&
|
||||
|
|
@ -433,6 +458,36 @@ test_expect_success 'repack -ad removes stale incremental chain' '
|
|||
)
|
||||
'
|
||||
|
||||
test_expect_success 'repack -ad --write-midx=incremental is safe' '
|
||||
git init ad-incremental-midx &&
|
||||
(
|
||||
cd ad-incremental-midx &&
|
||||
|
||||
git config maintenance.auto false &&
|
||||
|
||||
# Build a MIDX chain with multiple layers referencing
|
||||
# distinct packs.
|
||||
test_commit first &&
|
||||
git repack -d &&
|
||||
|
||||
test_commit second &&
|
||||
git repack -d --write-midx=incremental &&
|
||||
|
||||
git multi-pack-index verify &&
|
||||
test_line_count = 1 $midx_chain &&
|
||||
|
||||
# Now do a full -ad repack. The new pack contains all
|
||||
# objects, but any retained MIDX layers still reference
|
||||
# the now-deleted packs.
|
||||
test_commit third &&
|
||||
git repack -ad --write-midx=incremental &&
|
||||
|
||||
git multi-pack-index verify &&
|
||||
git fsck &&
|
||||
git rev-list --all --objects >/dev/null
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'repack rejects invalid midxSplitFactor' '
|
||||
test_when_finished "rm -fr bad-split-factor" &&
|
||||
git init bad-split-factor &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue