midx: pass custom '--base' through incremental writes

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). 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. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Jun 12, 2026 at 16:07 UTC 8e519b87565a8689d509693a049bc6dad632dbb3
5 files changed +25 -8
builtin/multi-pack-index.c
+2 -1
@@ -224,7 +224,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
224 }
225
226 ret = write_midx_file(source, opts.preferred_pack,
227 - opts.refs_snapshot, opts.flags);
227 + opts.refs_snapshot, opts.incremental_base,
228 + opts.flags);
229
230 free(opts.refs_snapshot);
231 return ret;
builtin/repack.c
+1 -1
@@ -629,7 +629,7 @@ int cmd_repack(int argc,
629 unsigned flags = 0;
630 if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))
631 flags |= MIDX_WRITE_INCREMENTAL;
632 - write_midx_file(existing.source, NULL, NULL, flags);
632 + write_midx_file(existing.source, NULL, NULL, NULL, flags);
633 }
634
635 cleanup:
midx-write.c
+2
@@ -1850,12 +1850,14 @@ cleanup:
1850 int write_midx_file(struct odb_source *source,
1851 const char *preferred_pack_name,
1852 const char *refs_snapshot,
1853 + const char *incremental_base,
1854 unsigned flags)
1855 {
1856 struct write_midx_opts opts = {
1857 .source = source,
1858 .preferred_pack_name = preferred_pack_name,
1859 .refs_snapshot = refs_snapshot,
1860 + .incremental_base = incremental_base,
1861 .flags = flags,
1862 };
1863
midx.h
+1 -1
@@ -131,7 +131,7 @@ int prepare_multi_pack_index_one(struct odb_source *source);
131 */
132 int write_midx_file(struct odb_source *source,
133 const char *preferred_pack_name, const char *refs_snapshot,
134 - unsigned flags);
134 + const char *incremental_base, unsigned flags);
135 int write_midx_file_only(struct odb_source *source,
136 struct string_list *packs_to_include,
137 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'
119 test_grep "cannot use --base without --no-write-chain-file" err
120 '
121
122 -test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file' '
122 +test_expect_failure 'write MIDX layer with --base=none and --no-write-chain-file' '
123 test_commit base-none &&
124 git repack -d &&
125
@@ -128,19 +128,33 @@ test_expect_success 'write MIDX layer with --base=none and --no-write-chain-file
128 --no-write-chain-file --base=none)" &&
129
130 test_cmp "$midx_chain.bak" "$midx_chain" &&
131 - test_path_is_file "$midxdir/multi-pack-index-$layer.midx"
131 + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" &&
132 +
133 + echo "$layer" >"$midx_chain" &&
134 + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects &&
135 + test_grep "^$(git rev-parse 2.2) " midx.objects &&
136 + cp "$midx_chain.bak" "$midx_chain"
137 '
138
134 -test_expect_success 'write MIDX layer with --base=<hash> and --no-write-chain-file' '
139 +test_expect_failure 'write MIDX layer with --base=<hash> and --no-write-chain-file' '
140 test_commit base-hash &&
141 git repack -d &&
142
143 cp "$midx_chain" "$midx_chain.bak" &&
144 + base="$(nth_line 1 "$midx_chain")" &&
145 layer="$(git multi-pack-index write --bitmap --incremental \
140 - --no-write-chain-file --base="$(nth_line 1 "$midx_chain")")" &&
146 + --no-write-chain-file --base="$base")" &&
147
148 test_cmp "$midx_chain.bak" "$midx_chain" &&
143 - test_path_is_file "$midxdir/multi-pack-index-$layer.midx"
149 + test_path_is_file "$midxdir/multi-pack-index-$layer.midx" &&
150 +
151 + {
152 + echo "$base" &&
153 + echo "$layer"
154 + } >"$midx_chain" &&
155 + test-tool read-midx --show-objects "$objdir" "$layer" >midx.objects &&
156 + test_grep "^$(git rev-parse 2.2) " midx.objects &&
157 + cp "$midx_chain.bak" "$midx_chain"
158 '
159
160 for reuse in false single multi