midx: honor custom bases for incremental writes
cover midx: honor custom bases for incremental writes
SZEDER noticed[1] that t5334 was trying to call nth_line(), despite that helper living only in t5335.
Fixing that should have made the test exercise git multi-pack-index write --incremental --base=.... Instead, it uncovered another wrinkle, which is that the normal MIDX write path parsed "--bases" without actually passing it down to the MIDX writer.
This short series fixes both issues. It is structured as follows:
* The first patch moves nth_line() to lib-midx.sh so that t5334 and t5335 use the same helper.
* The second patch threads the parsed --base value through write_midx_file(), and consequently marks two t5334 cases as known breakages.
* The final patch fixes the pack inclusion check and marks the tests successful again.
The result is that --base=none and --base=<hash> now correctly produce detached incremental layers that include any packs above the selected base, preserving reachability closure for bitmaps.
Thanks in advance for your review!
[1]: https://lore.kernel.org/git/[email protected]/
Taylor Blau (3):
t5334: expose shared nth_line() helper
midx: pass custom '--base' through incremental writes
midx-write: include packs above custom incremental base
builtin/multi-pack-index.c | 3 ++- builtin/repack.c | 2 +- midx-write.c | 18 +++++++++++++----- midx.h | 2 +- t/lib-midx.sh | 6 ++++++ t/t5334-incremental-multi-pack-index.sh | 20 +++++++++++++++++--- t/t5335-compact-multi-pack-index.sh | 7 +------ 7 files changed, 41 insertions(+), 17 deletions(-)
base-commit: 3e65291872de10c3f0bf05ea8c24187e7a71ebf0
Signature · 1 line
2.55.0.rc0.3.g7bf7c87b605
PATCH 1/3 t5334: expose shared `nth_line()` helper
Since commit 0cd2255e64b (midx: support custom --base for incremental MIDX writes, 2026-05-19), t5334 has referred to a non-existent helper function 'nth_line', which is defined in t5335, but not here.
Move the helper to lib-midx.sh so that both tests can use the same implementation. Ensure likewise that nth_line() remains visible from within t5335 by sourcing lib-midx.sh there appropriately.
Curiously, t5334 passes both before and after this change. Before this change, the failed command substitution leaves '--base' with an empty value, and after this change, the custom base value is still ignored by the normal incremental write path. The following commits will explain and address that behavior.
--- t/lib-midx.sh | 6 ++++++ t/t5335-compact-multi-pack-index.sh | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-)
t/lib-midx.sh +6 -0
@@ -34,3 +34,9 @@ compare_results_with_midx () { midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted ' } + +nth_line() { + local n="$1" + shift + awk "NR==$n" "$@" +}
t/t5335-compact-multi-pack-index.sh +1 -6
@@ -3,6 +3,7 @@ test_description='multi-pack-index compaction' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-midx.sh GIT_TEST_MULTI_PACK_INDEX=0 GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
@@ -13,12 +14,6 @@ packdir=$objdir/pack midxdir=$packdir/multi-pack-index.d midx_chain=$midxdir/multi-pack-index-chain -nth_line() { - local n="$1" - shift - awk "NR==$n" "$@" -} - write_packs () { for c in "$@" do
Signature · 1 line
2.55.0.rc0.3.g7bf7c87b605
Re: [PATCH 1/3] t5334: expose shared `nth_line()` helper
Quoted 5 lines · Taylor Blau
t/lib-midx.sh +0
-0
t/lib-midx.sh compare_results_with_midx () { · line 42
Quoted 9 lines
t/lib-midx.sh +6
-0@@ -34,3 +34,9 @@ compare_results_with_midx () { midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted ' } + +nth_line() { + local n="$1" + shift + awk "NR==$n" "$@" +}
It feels a bit weird to have such a general function in "lib-midx.sh", but so be it.
Patrick
Re: [PATCH 1/3] t5334: expose shared `nth_line()` helper
Quoted 10 lines · Patrick Steinhardt
Quoted 9 lines · Taylor Blau
t/lib-midx.sh +1
-0@@ -34,3 +34,9 @@ compare_results_with_midx () { midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted ' } +
Quoted 8 lines
t/lib-midx.sh compare_results_with_midx () { · line 42
Quoted 5 lines
t/lib-midx.sh +5
-0+nth_line() { + local n="$1" + shift + awk "NR==$n" "$@" +}It feels a bit weird to have such a general function in "
lib-midx.sh", but so be it.
Yeah, I agree. It mostly just felt weird to write '| awk "NR==$n"' a bunch of times.
Thanks,
Taylor
PATCH 2/3 midx: pass custom '--base' through incremental writes
In reply to Taylor BlauThe 'multi-pack-index' builtin parses '--base' for incremental writes, but the normal write path does not pass that value through to write_midx_file().
As a result, something like:
$ git multi-pack-index write --incremental --base=<base>
behaves as if no custom base had been given (unless the caller used the '--stdin-packs' path).
Thread the parsed base through write_midx_file(), and update the repack caller to pass NULL for the new argument where no custom base selection is needed.
This exposes a pre-existing problem in incremental writes with custom
bases: the writer skips packs from the full existing MIDX chain, even when the caller selected an older base or no base at all.
The affected t5334 cases fail while trying to write MIDX bitmaps. The detached layer omits packs above the selected base, and thus the resulting MIDX does not have a reachability closure, making it impossible to generate reachability bitmaps.
Mark those tests as expected failures accordingly. The following commit will fix the broken behavior and restore these tests.
--- builtin/multi-pack-index.c | 3 ++- builtin/repack.c | 2 +- midx-write.c | 2 ++ midx.h | 2 +- t/t5334-incremental-multi-pack-index.sh | 24 +++++++++++++++++++----- 5 files changed, 25 insertions(+), 8 deletions(-)
builtin/multi-pack-index.c +2 -1
@@ -224,7 +224,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, } ret =write_midx_file (source, opts.preferred_pack, - opts.refs_snapshot, opts.flags); + opts.refs_snapshot, opts.incremental_base, + opts.flags);free (opts.refs_snapshot);return ret;
builtin/repack.c +1 -1
@@ -629,7 +629,7 @@ int cmd_repack(int argc,unsigned flags =0 ;if (git_env_bool (GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL ,0 )) flags |=MIDX_WRITE_INCREMENTAL ; -write_midx_file (existing.source,NULL ,NULL , flags); +write_midx_file (existing.source,NULL ,NULL ,NULL , flags); } cleanup:
midx-write.c +2 -0
@@ -1850,12 +1850,14 @@ static int write_midx_internal(struct write_midx_opts *opts)int write_midx_file (struct odb_source *source,const char *preferred_pack_name,const char *refs_snapshot, +const char *incremental_base,unsigned flags) {struct write_midx_opts opts = { .source = source, .preferred_pack_name = preferred_pack_name, .refs_snapshot = refs_snapshot, + .incremental_base = incremental_base, .flags = flags, };
midx.h +1 -1
@@ -131,7 +131,7 @@ int prepare_multi_pack_index_one(struct odb_source *source);*/ int write_midx_file (struct odb_source *source,const char *preferred_pack_name,const char *refs_snapshot, -unsigned flags); +const char *incremental_base,unsigned flags); int write_midx_file_only(struct odb_source *source, struct string_list *packs_to_include, const char *preferred_pack_name,
t/t5334-incremental-multi-pack-index.sh +19 -5
@@ -119,7 +119,7 @@ test_expect_success 'write MIDX layer with --base without --no-write-chain-file' test_grep "cannot use --base without --no-write-chain-file" err ' -test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file' ' +test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file' ' test_commit base-none && git repack -d &&
@@ -128,19 +128,33 @@ test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file --no-write-chain-file --base=none)" && test_cmp "$midx_chain.bak" "$midx_chain" && - test_path_is_file "$midxdir/multi-pack-index-$layer.midx" + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" && + + echo "$layer" >"$midx_chain" && + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects && + test_grep "^$(git rev-parse 2.2) " midx.objects && + cp "$midx_chain.bak" "$midx_chain" ' -test_expect_success 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' +test_expect_failure 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' test_commit base-hash && git repack -d && cp "$midx_chain" "$midx_chain.bak" && + base="$(nth_line 1 "$midx_chain")" && layer="$(git multi-pack-index write --bitmap --incremental \ - --no-write-chain-file --base="$(nth_line 1 "$midx_chain")")" && + --no-write-chain-file --base="$base")" && test_cmp "$midx_chain.bak" "$midx_chain" && - test_path_is_file "$midxdir/multi-pack-index-$layer.midx" + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" && + + { + echo "$base" && + echo "$layer" + } >"$midx_chain" && + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects && + test_grep "^$(git rev-parse 2.2) " midx.objects && + cp "$midx_chain.bak" "$midx_chain" ' for reuse in false single multi
Signature · 1 line
2.55.0.rc0.3.g7bf7c87b605
Re: [PATCH 2/3] midx: pass custom '--base' through incremental writes
Quoted 10 lines · Taylor Blau
The 'multi-pack-index' builtin parses '--base' for incremental writes, but the normal write path does not pass that value through to
write_midx_file().As a result, something like:
$ git multi-pack-index write --incremental --base=<base>behaves as if no custom base had been given (unless the caller used the '--stdin-packs' path).
I'm a bit confused. Is the "normal" write path the one that generates a completely new, full MIDX? I assume not, and that you use "normal" to discern between whether or not we pass "--stdin-packs"? I think that could be made a bit more explicit.
*goes looking into the code* Yeah, seems like the distinction indeed is whether "--stdin-packs" was passed in the first place.
Quoted 7 lines
Thread the parsed base through
write_midx_file(), and update the repack caller to pass NULL for the new argument where no custom base selection is needed.This exposes a pre-existing problem in incremental writes with custom
bases: the writer skips packs from the full existing MIDX chain, even when the caller selected an older base or no base at all.
So as the "normal" write path didn't honor this option at all, I assume this bug here then refers to "--stdin-packs" being broken?
Quoted 7 lines
The affected t5334 cases fail while trying to write MIDX bitmaps. The detached layer omits packs above the selected base, and thus the resulting MIDX does not have a reachability closure, making it impossible to generate reachability bitmaps.
Mark those tests as expected failures accordingly. The following commit will fix the broken behavior and restore these tests.
Okay.
Quoted 5 lines
builtin/multi-pack-index.c +0
-0
builtin/multi-pack-index.c static int cmd_multi_pack_index_write(int argc, const char **argv, · line 231
Quoted 9 lines
builtin/multi-pack-index.c +2
-1@@ -224,7 +224,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, } ret =write_midx_file (source, opts.preferred_pack, - opts.refs_snapshot, opts.flags); + opts.refs_snapshot, opts.incremental_base, + opts.flags);free (opts.refs_snapshot);return ret;
Previously we only passed the base to write_midx_file_only(), which is what we use with "--stdin-packs". Here we now update the normal write path to use the incremental base, too.
Quoted 8 lines
midx-write.c +0
-0@@ -1850,12 +1850,14 @@ static int write_midx_internal(struct write_midx_opts *opts) int write_midx_file(struct odb_source *source, const char *preferred_pack_name, const char *refs_snapshot,
midx-write.c static int write_midx_internal(struct write_midx_opts *opts) · line 1862
Quoted 10 lines
midx-write.c +2
-0+ const char *incremental_base, unsigned flags) {struct write_midx_opts opts = { .source = source, .preferred_pack_name = preferred_pack_name, .refs_snapshot = refs_snapshot, + .incremental_base = incremental_base, .flags = flags, };
I was wondering whether there needs to be error checking somewhere so that we only accept an incremental base in case MIDX_WRITE_INCREMENTAL is set. I couldn't find any.
t/t5334-incremental-multi-pack-index.sh test_expect_success 'write MIDX layer with --base without --no-write-chain-file' · line 125
Quoted 13 lines
t/t5334-incremental-multi-pack-index.sh +1
-1@@ -119,7 +119,7 @@ test_expect_success 'write MIDX layer with --base without --no-write-chain-file' test_grep "cannot use --base without --no-write-chain-file" err ' -test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file' ' +test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file' ' test_commit base-none && git repack -d &&
Okay. If I understand correctly, the expectation here would be that we generate a complete MIDX as we don't select any base at all. But we don't, and instead we base our incremental MIDX on top of the newest layer by accident.
t/t5334-incremental-multi-pack-index.sh test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file · line 137
Quoted 12 lines
t/t5334-incremental-multi-pack-index.sh +6
-1@@ -128,19 +128,33 @@ test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file --no-write-chain-file --base=none)" && test_cmp "$midx_chain.bak" "$midx_chain" && - test_path_is_file "$midxdir/multi-pack-index-$layer.midx" + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" && + + echo "$layer" >"$midx_chain" && + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects && + test_grep "^$(git rev-parse 2.2) " midx.objects && + cp "$midx_chain.bak" "$midx_chain" '
Would it make sense to also test for an object from the first MIDX layer to be included? Otherwise we don't really assert that all layers are included in the new MIDX.
Patrick
Re: [PATCH 2/3] midx: pass custom '--base' through incremental writes
Quoted 10 lines · Patrick Steinhardt
Quoted 7 lines
Thread the parsed base through
write_midx_file(), and update the repack caller to pass NULL for the new argument where no custom base selection is needed.This exposes a pre-existing problem in incremental writes with custom
bases: the writer skips packs from the full existing MIDX chain, even when the caller selected an older base or no base at all.So as the "normal" write path didn't honor this option at all, I assume this bug here then refers to "--stdin-packs" being broken?
Yeah, that's right.
Quoted 16 lines
t/t5334-incremental-multi-pack-index.sh test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file · line 137
Quoted 12 lines
t/t5334-incremental-multi-pack-index.sh +6
-1@@ -128,19 +128,33 @@ test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file --no-write-chain-file --base=none)" && test_cmp "$midx_chain.bak" "$midx_chain" && - test_path_is_file "$midxdir/multi-pack-index-$layer.midx" + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" && + + echo "$layer" >"$midx_chain" && + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects && + test_grep "^$(git rev-parse 2.2) " midx.objects && + cp "$midx_chain.bak" "$midx_chain" 'Would it make sense to also test for an object from the first MIDX layer to be included? Otherwise we don't really assert that all layers are included in the new MIDX.
I don't think that is necessary in this case, but let me know if I am missing something below.
The new layer is written with '--bitmap', and '--base=none' means that there is no base layer from which the bitmap can inherit objects. Since 1.2 is an ancestor of 2.2, writing a bitmap for the new layer already requires that it contain 1.2 and the rest of its reachable history. Otherwise bitmap generation would fail with the missing-closure error before we reached the assertion.
Checking 2.2 confirms that an object from the old tip was pulled into the new layer; the successful bitmap write already establishes that its objects from the earlier layer were pulled in, too.
Thanks,
Taylor
Re: [PATCH 2/3] midx: pass custom '--base' through incremental writes
Quoted 28 lines · Taylor Blau
Quoted 16 lines · Patrick Steinhardt
t/t5334-incremental-multi-pack-index.sh test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file · line 137
Quoted 12 lines
t/t5334-incremental-multi-pack-index.sh +6
-1@@ -128,19 +128,33 @@ test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file --no-write-chain-file --base=none)" && test_cmp "$midx_chain.bak" "$midx_chain" && - test_path_is_file "$midxdir/multi-pack-index-$layer.midx" + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" && + + echo "$layer" >"$midx_chain" && + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects && + test_grep "^$(git rev-parse 2.2) " midx.objects && + cp "$midx_chain.bak" "$midx_chain" 'Would it make sense to also test for an object from the first MIDX layer to be included? Otherwise we don't really assert that all layers are included in the new MIDX.
I don't think that is necessary in this case, but let me know if I am missing something below.
The new layer is written with '--bitmap', and '--base=none' means that there is no base layer from which the bitmap can inherit objects. Since 1.2 is an ancestor of 2.2, writing a bitmap for the new layer already requires that it contain 1.2 and the rest of its reachable history. Otherwise bitmap generation would fail with the missing-closure error before we reached the assertion.
Quoted 3 lines
Checking 2.2 confirms that an object from the old tip was pulled into the new layer; the successful bitmap write already establishes that its objects from the earlier layer were pulled in, too.
I think that's a bit roundabout, as it simply tells us that the bitmap was generated correctly, but not that the MIDX contains the objects. It of course should if the bitmap was generated properly, but I would have preferred if we verified the property directly.
Anyway, this is not a huge concern, more of a nitpick. Thanks!
Patrick
PATCH 3/3 midx-write: include packs above custom incremental base
In reply to Taylor BlauThe previous commit made '--base' take effect on the normal incremental write path, which exposed an existing assumption in our helper function should_include_pack(), which is that any pack already present in ctx->m was skipped.
That is only correct for non-incremental writes. For incremental writes, ctx->base_midx is the boundary that should be excluded from the new layer. If the caller selects an older base, or no base at all, then packs from layers above that base have to be included in the detached layer so that its bitmap has reachability closure.
Teach should_include_pack() to choose the MIDX used for pack exclusion based on whether or not we are performing an incremental write. When doing so, use ctx->base_midx, and use ctx->m otherwise.
The t5334 cases from the previous commit can now be marked as successful.
--- midx-write.c | 16 +++++++++++----- t/t5334-incremental-multi-pack-index.sh | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-)
midx-write.c +11 -5
@@ -133,8 +133,17 @@ static uint32_t midx_pack_perm(struct write_midx_context *ctx,static int should_include_pack (const struct write_midx_context *ctx,const char *file_name) { +struct multi_pack_index *m = ctx->m;/* -* Note that at most one of ctx->m and ctx->to_include are set, +* When writing incrementally, ctx->m may contain layers above +* the selected base MIDX, which must be included in the new +* layer. +*/ +if (ctx->incremental) + m = ctx->base_midx; + +/* +* Note that at most one of m and ctx->to_include are set, * so we are testing midx_contains_pack() and * string_list_has_string() independently (guarded by the * appropriate NULL checks).
@@ -148,10 +157,7 @@ static int should_include_pack(const struct write_midx_context *ctx,* should be performed independently (likely checking * to_include before the existing MIDX). */ -if (ctx->m &&midx_contains_pack (ctx->m, file_name)) -return 0 ; -else if (ctx->base_midx &&midx_contains_pack (ctx->base_midx, - file_name)) +if (m &&midx_contains_pack (m, file_name))return 0 ;else if (ctx->to_include && !string_list_has_string (ctx->to_include, file_name))
t/t5334-incremental-multi-pack-index.sh +2 -2
@@ -119,7 +119,7 @@ test_expect_success 'write MIDX layer with --base without --no-write-chain-file' test_grep "cannot use --base without --no-write-chain-file" err ' -test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file' ' +test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file' ' test_commit base-none && git repack -d &&
@@ -136,7 +136,7 @@ test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file cp "$midx_chain.bak" "$midx_chain" ' -test_expect_failure 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' +test_expect_success 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' test_commit base-hash && git repack -d &&
Signature · 1 line
2.55.0.rc0.3.g7bf7c87b605
Re: [PATCH 3/3] midx-write: include packs above custom incremental base
Quoted 9 lines · Taylor Blau
midx-write.c +1
-0@@ -133,8 +133,17 @@ static uint32_t midx_pack_perm(struct write_midx_context *ctx,static int should_include_pack (const struct write_midx_context *ctx,const char *file_name) { +struct multi_pack_index *m = ctx->m;
midx-write.c static uint32_t midx_pack_perm(struct write_midx_context *ctx, · line 145
Quoted 10 lines
midx-write.c +8
-1/* -* Note that at most one of ctx->m and ctx->to_include are set, +* When writing incrementally, ctx->m may contain layers above +* the selected base MIDX, which must be included in the new +* layer. +*/ +if (ctx->incremental) + m = ctx->base_midx; +/* +* Note that at most one of m and ctx->to_include are set,
Is that true? With "--stdin-packs --incremental --base=<foo>" I'd expect that we have both set now.
midx-write.c static int should_include_pack(const struct write_midx_context *ctx, · line 161
Quoted 10 lines
midx-write.c +1
-4@@ -148,10 +157,7 @@ static int should_include_pack(const struct write_midx_context *ctx,* should be performed independently (likely checking * to_include before the existing MIDX). */ -if (ctx->m &&midx_contains_pack (ctx->m, file_name)) -return 0 ; -else if (ctx->base_midx &&midx_contains_pack (ctx->base_midx, - file_name)) +if (m &&midx_contains_pack (m, file_name))return 0 ;
Okay, previously we were always checking against ctx->m, so we would exclude packs that are contained in the current MIDX. And that includes the case where parts of the current MIDX are supposed to be thrown away because we want to write a new layer that excludes all layers starting at the base.
This is fixed by instead always comparing against the base MIDX in case "--incremental" was passed. When the user passes "--base=none" we don't have any base, and consequently we'd include all packs. Otherwise, we'll exclude all packs that are already covered by our base, but include all the other ones.
That feels sensible to me.
Quoted 16 lines
midx-write.c +0
-0else if (ctx->to_include && !string_list_has_string (ctx->to_include, file_name))t/t5334-incremental-multi-pack-index.sh +1
-1@@ -119,7 +119,7 @@ test_expect_success 'write MIDX layer with --base without --no-write-chain-file' test_grep "cannot use --base without --no-write-chain-file" err ' -test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file' ' +test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file' ' test_commit base-none && git repack -d &&
t/t5334-incremental-multi-pack-index.sh test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file · line 141
Quoted 7 lines
t/t5334-incremental-multi-pack-index.sh +1
-1@@ -136,7 +136,7 @@ test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file cp "$midx_chain.bak" "$midx_chain" ' -test_expect_failure 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' +test_expect_success 'write MIDX layer with --base=<hash> and --no-write-chain-file' ' test_commit base-hash && git repack -d &&
And those two tests pass now.
Thanks!
Patrick
Re: [PATCH 3/3] midx-write: include packs above custom incremental base
Quoted 15 lines · Patrick Steinhardt
Quoted 14 lines · Taylor Blau
midx-write.c +4
-1@@ -133,8 +133,17 @@ static uint32_t midx_pack_perm(struct write_midx_context *ctx,static int should_include_pack (const struct write_midx_context *ctx,const char *file_name) { +struct multi_pack_index *m = ctx->m;/* -* Note that at most one of ctx->m and ctx->to_include are set, +* When writing incrementally, ctx->m may contain layers above +* the selected base MIDX, which must be included in the new +* layer.
Quoted 8 lines
midx-write.c static uint32_t midx_pack_perm(struct write_midx_context *ctx, · line 146
Quoted 5 lines
midx-write.c +5
-0+*/ +if (ctx->incremental) + m = ctx->base_midx; +/* +* Note that at most one of m and ctx->to_include are set, Is that true? With "--stdin-packs --incremental --base=<foo>" I'd expect that we have both set now.
That invariant holds for ctx->mj, but not for the local m after the assignment above. With '--stdin-packs', write_midx_internal() leaves ctx->m unset, but can still set ctx->base_midx for an incremental write. Once we assign m = ctx->base_midx, both m and ctx->to_include can indeed be non-NULL.
The filtering still does the right thing: packs covered by the selected base are excluded, and the remaining packs are checked against the stdin list. But the comment is wrong, so I'll fix it.
Quoted 5 lines
Okay, previously we were always checking against
ctx->m, so we would exclude packs that are contained in the current MIDX. And that includes the case where parts of the current MIDX are supposed to be thrown away because we want to write a new layer that excludes all layers starting at the base.
On the non- '--stdin-packs' path, yes. With '--stdin-packs', ctx->m is NULL and the old code already checks ctx->base_midx. The problem appears when the previous patch starts honoring '--base' on the ordinary write path. Since ctx->m still refers to the entire existing chain, it excludes packs from layers above the selected base.
Quoted 7 lines
This is fixed by instead always comparing against the base MIDX in case "--incremental" was passed. When the user passes "--base=none" we don't have any base, and consequently we'd include all packs. Otherwise, we'll exclude all packs that are already covered by our base, but include all the other ones.
That feels sensible to me.
Exactly.
Thanks,
Taylor
Re: [PATCH 3/3] midx-write: include packs above custom incremental base
Quoted 5 lines · Taylor Blau
ctx->to_includecan indeed be non-NULL.
...
The filtering still does the right thing: packs covered by the selected base are excluded, and the remaining packs are checked against the stdin list. But the comment is wrong, so I'll fix it.
Has anything happened since we saw this comment on Aug 13th?
Thanks.
Re: [PATCH 3/3] midx-write: include packs above custom incremental base
Quoted 9 lines · Junio C Hamano
Quoted 5 lines · Taylor Blau
ctx->to_includecan indeed be non-NULL.
...
The filtering still does the right thing: packs covered by the selected base are excluded, and the remaining packs are checked against the stdin list. But the comment is wrong, so I'll fix it.Has anything happened since we saw this comment on Aug 13th?
Not until you sent this message ;-).
I had a small reroll prepped that I had meant to send a couple of weeks ago but never got around to doing so. When I looked at it just now, I found that I wasn't quite satisfied with the range-diff in that the resulting block comment was somewhat confusing.
Instead of sending a new round immediately, let me instead share the comment that I wrote instead. Patrick (or others): does this comment seem clear, or do you think there are ways to tighten it up further?
--- 8< ---
midx-write.c +25 -9
@@ -143,15 +143,31 @@ static int should_include_pack(const struct write_midx_context *ctx, m = ctx->base_midx;/* -* Note that m and ctx->to_include may both be set, -* so we are testing midx_contains_pack() and -* string_list_has_string() independently (guarded by the -* appropriate NULL checks). -* -* We could support passing to_include while reusing an existing -* MIDX, but don't currently since the reuse process drags -* forward all packs from an existing MIDX (without checking -* whether or not they appear in the to_include list). +* Note that it is OK for both ctx->base_midx and +* ctx->to_include may both be non-NULL, but at most one of +* ctx->m and ctx->to_include may be non-NULL. +* +* When ctx->m is NULL we are writing a new MIDX without reusing +* any packs from the previous layer(s). In that case, we care +* that both: +* +* - the new layer's base MIDX (ctx->base_midx) does not +* already contain the pack we are considering, or the new +* layer has no base (i.e., it is a non-incremental MIDX) +* +* - the pack appears in ctx->to_include, or ctx->to_include +* is NULL, meaning that we can include any pack provided +* the above condition is met. +* +* When ctx->m is non-NULL, we are writing a new MIDX that will +* subsume ctx->m and thus includes its packs. In this case, we +* could support respecting ctx->to_include, but currently +* don't. +* +* The only caller of this function which permits +* ctx->to_include being non-NULL restricts setting ctx->m when +* this is the case. So in this setting it is impossible that +* both will be non-NULL. * * If we added support for that, these next two conditional * should be performed independently (likely checking
--- >8 ---
Thanks,
Taylor
Re: [PATCH 3/3] midx-write: include packs above custom incremental base
Quoted 33 lines · Taylor Blau
Quoted 9 lines · Junio C Hamano
Quoted 5 lines · Taylor Blau
ctx->to_includecan indeed be non-NULL.
...
The filtering still does the right thing: packs covered by the selected base are excluded, and the remaining packs are checked against the stdin list. But the comment is wrong, so I'll fix it.Has anything happened since we saw this comment on Aug 13th?
Not until you sent this message ;-).
I had a small reroll prepped that I had meant to send a couple of weeks ago but never got around to doing so. When I looked at it just now, I found that I wasn't quite satisfied with the range-diff in that the resulting block comment was somewhat confusing.
Instead of sending a new round immediately, let me instead share the comment that I wrote instead. Patrick (or others): does this comment seem clear, or do you think there are ways to tighten it up further?
--- 8< ---
midx-write.c +0
-2@@ -143,15 +143,31 @@ static int should_include_pack(const struct write_midx_context *ctx, m = ctx->base_midx;/* -* Note that m and ctx->to_include may both be set, -* so we are testing midx_contains_pack() and
midx-write.c static int should_include_pack(const struct write_midx_context *ctx, · line 148
Quoted 10 lines
midx-write.c +3
-7-* string_list_has_string() independently (guarded by the -* appropriate NULL checks). -* -* We could support passing to_include while reusing an existing -* MIDX, but don't currently since the reuse process drags -* forward all packs from an existing MIDX (without checking -* whether or not they appear in the to_include list). +* Note that it is OK for both ctx->base_midx and +* ctx->to_include may both be non-NULL, but at most one of +* ctx->m and ctx->to_include may be non-NULL.
That reads a bit off. Should that be "Note that it is OK for both ... to be non-NULL" instead?
Quoted 11 lines
midx-write.c +11
-0+* When ctx->m is NULL we are writing a new MIDX without reusing +* any packs from the previous layer(s). In that case, we care +* that both: +* +* - the new layer's base MIDX (ctx->base_midx) does not +* already contain the pack we are considering, or the new +* layer has no base (i.e., it is a non-incremental MIDX) +* +* - the pack appears in ctx->to_include, or ctx->to_include +* is NULL, meaning that we can include any pack provided +* the above condition is met.
midx-write.c static int should_include_pack(const struct write_midx_context *ctx, · line 170
Quoted 10 lines
midx-write.c +10
-0+* +* When ctx->m is non-NULL, we are writing a new MIDX that will +* subsume ctx->m and thus includes its packs. In this case, we +* could support respecting ctx->to_include, but currently +* don't. +* +* The only caller of this function which permits +* ctx->to_include being non-NULL restricts setting ctx->m when +* this is the case. So in this setting it is impossible that +* both will be non-NULL.
I feel like this last paragraph could be dropped -- it's something that we could mention as part of the commit message, but in this function here I think it's very likely to go stale fast.
Other than that I think this is good. It's quite long, but I don't have any good ideas for how to tighten this up significantly.
Thanks!
Patrick