Skip to content

Commit 12ebd5c

Browse files
committed
maintenance(geometric): do release the .idx files before repacking
As is done for all the other maintenance tasks, let's release the ODB also before starting the geometric repacking. That way, the `.idx` files won't be `mmap()`ed when they are to be deleted (which does not work on Windows because you cannot delete files on that platform as long as they are kept open by a process). This regression was introduced by 9bc1518 (builtin/maintenance: introduce "geometric-repack" task, 2025-10-24), but was only noticed once geometric repacking was made the default in 452b12c (builtin/ maintenance: use "geometric" strategy by default, 2026-02-24). The fix recapitulates my work from df76ee7 (run-command: offer to close the object store before running, 2021-09-09) & friends. To guard against future regressions of this kind, add a check to `run_and_verify_geometric_pack()` in `t7900` that detects orphaned `.idx` files left behind after repacking. Contrary to interactive calls, the `git maintenance` call in that test case would _not_ block on Windows, asking whether to retry deleting that file, which is the reason why this bug was not caught earlier. Furthermore, since the default behavior of `DeleteFileW()` was changed at some point between Windows 10 Build 17134.1304 and Build 18363.657 to use POSIX semantics (see https://stackoverflow.com/a/60512798), the added orphaned-`.idx` check would be insufficient to catch this regression on modern Windows without emulating legacy delete semantics via `GIT_TEST_LEGACY_DELETE=1`. This fixes git-for-windows#6210. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 97508e9 commit 12ebd5c

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

builtin/gc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,7 @@ static int maintenance_task_geometric_repack(struct maintenance_run_opts *opts,
15901590
pack_geometry_split(&geometry);
15911591

15921592
child.git_cmd = 1;
1593+
child.odb_to_close = the_repository->objects;
15931594

15941595
strvec_pushl(&child.args, "repack", "-d", "-l", NULL);
15951596
if (geometry.split < geometry.pack_nr)

t/t7900-maintenance.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,16 @@ run_and_verify_geometric_pack () {
532532

533533
# And verify that there are no loose objects anymore.
534534
git count-objects -v >count &&
535-
test_grep '^count: 0$' count
535+
test_grep '^count: 0$' count &&
536+
537+
# Verify that no orphaned .idx files were left behind. On
538+
# Windows, a missing odb_to_close causes the parent to hold
539+
# mmap handles on .idx files, silently preventing their
540+
# deletion by the child git-repack process.
541+
ls .git/objects/pack/pack-*.idx .git/objects/pack/pack-*.pack |
542+
sed "s/\.pack$/.idx/" |
543+
sort | uniq -u >orphaned-idx &&
544+
test_must_be_empty orphaned-idx
536545
}
537546

538547
test_expect_success 'geometric repacking task' '
@@ -580,8 +589,19 @@ test_expect_success 'geometric repacking task' '
580589
581590
# And these two small packs should now be merged via the
582591
# geometric repack. The large packfile should remain intact.
592+
cp -R .git/objects .git/objects.save &&
583593
run_and_verify_geometric_pack 2 &&
584594
595+
# On Windows, verify the same with legacy delete semantics
596+
# that reject deletion of mmap-held .idx files.
597+
if test_have_prereq MINGW
598+
then
599+
rm -rf .git/objects &&
600+
mv .git/objects.save .git/objects &&
601+
test_env GIT_TEST_LEGACY_DELETE=1 \
602+
run_and_verify_geometric_pack 2
603+
fi &&
604+
585605
# If we now add two more objects and repack twice we should
586606
# then see another all-into-one repack. This time around
587607
# though, as we have unreachable objects, we should also see a

0 commit comments

Comments
 (0)