Merge branch 'ps/packfile-stale-delta-base-cache-fix' into jch
Closing a packfile did not evict the entries belonging to it from the delta base cache, which could lead to data corruption when a newly allocated packfile happened to reuse the same memory address. The cache eviction logic has been updated to remove these stale entries upon closing a pack * ps/packfile-stale-delta-base-cache-fix: packfile: fix corruption due to stale delta base cache entries packfile: move around `close_pack()`jch
commit
b59d45a334
33
packfile.c
33
packfile.c
|
|
@ -355,16 +355,6 @@ static void close_pack_mtimes(struct packed_git *p)
|
|||
p->mtimes_map = NULL;
|
||||
}
|
||||
|
||||
void close_pack(struct packed_git *p)
|
||||
{
|
||||
close_pack_windows(p);
|
||||
close_pack_fd(p);
|
||||
close_pack_index(p);
|
||||
close_pack_revindex(p);
|
||||
close_pack_mtimes(p);
|
||||
oidset_clear(&p->bad_objects);
|
||||
}
|
||||
|
||||
void unlink_pack_path(const char *pack_name, int force_delete)
|
||||
{
|
||||
static const char *exts[] = {".idx", ".pack", ".rev", ".keep", ".bitmap", ".promisor", ".mtimes"};
|
||||
|
|
@ -1263,6 +1253,29 @@ 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);
|
||||
close_pack_fd(p);
|
||||
close_pack_index(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,
|
||||
void *base, size_t base_size,
|
||||
size_t delta_base_cache_limit,
|
||||
|
|
|
|||
|
|
@ -553,4 +553,51 @@ test_expect_success 'merge does not mix up superproject and submodule commit-gra
|
|||
test_cmp expect actual)
|
||||
'
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue