diff --git a/packfile.c b/packfile.c index af1b837974..365c54c7dc 100644 --- a/packfile.c +++ b/packfile.c @@ -1253,6 +1253,18 @@ void clear_delta_base_cache(void) } } +static void delta_base_cache_evict_entry(struct packed_git *p) +{ + struct list_head *lru, *tmp; + + list_for_each_safe(lru, tmp, &delta_base_cache_lru) { + struct delta_base_cache_entry *entry = + list_entry(lru, struct delta_base_cache_entry, lru); + if (entry->key.p == p) + release_delta_base_cache(entry); + } +} + void close_pack(struct packed_git *p) { close_pack_windows(p); @@ -1261,6 +1273,7 @@ void close_pack(struct packed_git *p) close_pack_revindex(p); close_pack_mtimes(p); oidset_clear(&p->bad_objects); + delta_base_cache_evict_entry(p); } static void add_delta_base_cache(struct packed_git *p, off_t base_offset, diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index 1546d5f773..0ee3684206 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -514,4 +514,51 @@ test_expect_success 'merging should fail with no merge base' ' ) ' +test_expect_success 'merge with many packed submodules reports conflicts' ' + test_config_global protocol.file.allow always && + + # Create 16 submodules with two divergent branches each. + submodules="A B C D E F G H I J K L M N O P" && + for name in $submodules + do + git init source-$name && + test_commit -C source-$name $name-main && + git -C source-$name switch --create branch-a main && + git -C source-$name commit --allow-empty --message $name-branch-a && + git -C source-$name switch --create branch-b main && + git -C source-$name commit --allow-empty --message $name-branch-b || return 1 + done && + + # Create the superproject and add all submodules. + git init many-packed && + for name in $submodules + do + git -C many-packed submodule add --branch main "file://$PWD/source-$name" $name || return 1 + done && + git -C many-packed commit --message main && + + # Create two divergent commits in the superproject that update all + # submodules to the divergent branches. + for branch in branch-a branch-b + do + git -C many-packed switch -c $branch main && + for name in $submodules + do + git -C many-packed/$name switch $branch || return 1 + done && + git -C many-packed add $submodules && + git -C many-packed commit --message $branch || return 1 + done && + + # Clone the superproject to ensure that everything is well-packed and + # then merge the two branches, creating conflicts for every submodule. + git clone many-packed many-packed-clone && + git -C many-packed-clone submodule update --init && + git -C many-packed-clone switch branch-a && + test_expect_code 1 git -C many-packed-clone -c advice.submoduleMergeConflict=false merge branch-b >out 2>err && + grep "^CONFLICT (submodule)" out >conflicts && + test_line_count = 16 conflicts && + test_must_be_empty err +' + test_done