2021-05-04 16:27:31 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='parallel-checkout basics
|
|
|
|
|
|
|
|
Ensure that parallel-checkout basically works on clone and checkout, spawning
|
|
|
|
the required number of workers and correctly populating both the index and the
|
|
|
|
working tree.
|
|
|
|
'
|
|
|
|
|
|
|
|
TEST_NO_CREATE_REPO=1
|
2024-08-01 10:41:06 +00:00
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
2021-05-04 16:27:31 +00:00
|
|
|
. ./test-lib.sh
|
|
|
|
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"
|
|
|
|
|
|
|
|
# Test parallel-checkout with a branch switch containing a variety of file
|
|
|
|
# creations, deletions, and modifications, involving different entry types.
|
|
|
|
# The branches B1 and B2 have the following paths:
|
|
|
|
#
|
|
|
|
# B1 B2
|
|
|
|
# a/a (file) a (file)
|
|
|
|
# b (file) b/b (file)
|
|
|
|
#
|
|
|
|
# c/c (file) c (symlink)
|
|
|
|
# d (symlink) d/d (file)
|
|
|
|
#
|
|
|
|
# e/e (file) e (submodule)
|
|
|
|
# f (submodule) f/f (file)
|
|
|
|
#
|
|
|
|
# g (submodule) g (symlink)
|
|
|
|
# h (symlink) h (submodule)
|
|
|
|
#
|
|
|
|
# Additionally, the following paths are present on both branches, but with
|
|
|
|
# different contents:
|
|
|
|
#
|
|
|
|
# i (file) i (file)
|
|
|
|
# j (symlink) j (symlink)
|
|
|
|
# k (submodule) k (submodule)
|
|
|
|
#
|
|
|
|
# And the following paths are only present in one of the branches:
|
|
|
|
#
|
|
|
|
# l/l (file) -
|
|
|
|
# - m/m (file)
|
|
|
|
#
|
|
|
|
test_expect_success 'setup repo for checkout with various types of changes' '
|
2022-09-30 20:48:56 +00:00
|
|
|
test_config_global protocol.file.allow always &&
|
|
|
|
|
2021-05-04 16:27:31 +00:00
|
|
|
git init sub &&
|
|
|
|
(
|
|
|
|
cd sub &&
|
|
|
|
git checkout -b B2 &&
|
|
|
|
echo B2 >file &&
|
|
|
|
git add file &&
|
|
|
|
git commit -m file &&
|
|
|
|
|
|
|
|
git checkout -b B1 &&
|
|
|
|
echo B1 >file &&
|
|
|
|
git add file &&
|
|
|
|
git commit -m file
|
|
|
|
) &&
|
|
|
|
|
|
|
|
git init various &&
|
|
|
|
(
|
|
|
|
cd various &&
|
|
|
|
|
|
|
|
git checkout -b B1 &&
|
|
|
|
mkdir a c e &&
|
|
|
|
echo a/a >a/a &&
|
|
|
|
echo b >b &&
|
|
|
|
echo c/c >c/c &&
|
|
|
|
test_ln_s_add c d &&
|
|
|
|
echo e/e >e/e &&
|
|
|
|
git submodule add ../sub f &&
|
|
|
|
git submodule add ../sub g &&
|
|
|
|
test_ln_s_add c h &&
|
|
|
|
|
|
|
|
echo "B1 i" >i &&
|
|
|
|
test_ln_s_add c j &&
|
|
|
|
git submodule add -b B1 ../sub k &&
|
|
|
|
mkdir l &&
|
|
|
|
echo l/l >l/l &&
|
|
|
|
|
|
|
|
git add . &&
|
|
|
|
git commit -m B1 &&
|
|
|
|
|
|
|
|
git checkout -b B2 &&
|
|
|
|
git rm -rf :^.gitmodules :^k &&
|
|
|
|
mkdir b d f &&
|
|
|
|
echo a >a &&
|
|
|
|
echo b/b >b/b &&
|
|
|
|
test_ln_s_add b c &&
|
|
|
|
echo d/d >d/d &&
|
|
|
|
git submodule add ../sub e &&
|
|
|
|
echo f/f >f/f &&
|
|
|
|
test_ln_s_add b g &&
|
|
|
|
git submodule add ../sub h &&
|
|
|
|
|
|
|
|
echo "B2 i" >i &&
|
|
|
|
test_ln_s_add b j &&
|
|
|
|
git -C k checkout B2 &&
|
|
|
|
mkdir m &&
|
|
|
|
echo m/m >m/m &&
|
|
|
|
|
|
|
|
git add . &&
|
|
|
|
git commit -m B2 &&
|
|
|
|
|
|
|
|
git checkout --recurse-submodules B1
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
for mode in sequential parallel sequential-fallback
|
|
|
|
do
|
|
|
|
case $mode in
|
|
|
|
sequential) workers=1 threshold=0 expected_workers=0 ;;
|
|
|
|
parallel) workers=2 threshold=0 expected_workers=2 ;;
|
|
|
|
sequential-fallback) workers=2 threshold=100 expected_workers=0 ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
test_expect_success "$mode checkout" '
|
|
|
|
repo=various_$mode &&
|
2021-05-26 23:58:56 +00:00
|
|
|
cp -R -P various $repo &&
|
2021-05-04 16:27:31 +00:00
|
|
|
|
|
|
|
# The just copied files have more recent timestamps than their
|
|
|
|
# associated index entries. So refresh the cached timestamps
|
|
|
|
# to avoid an "entry not up-to-date" error from `git checkout`.
|
|
|
|
# We only have to do this for the submodules as `git checkout`
|
|
|
|
# will already refresh the superproject index before performing
|
|
|
|
# the up-to-date check.
|
|
|
|
#
|
|
|
|
git -C $repo submodule foreach "git update-index --refresh" &&
|
|
|
|
|
|
|
|
set_checkout_config $workers $threshold &&
|
|
|
|
test_checkout_workers $expected_workers \
|
|
|
|
git -C $repo checkout --recurse-submodules B2 &&
|
|
|
|
verify_checkout $repo
|
|
|
|
'
|
|
|
|
done
|
|
|
|
|
|
|
|
for mode in parallel sequential-fallback
|
|
|
|
do
|
|
|
|
case $mode in
|
|
|
|
parallel) workers=2 threshold=0 expected_workers=2 ;;
|
|
|
|
sequential-fallback) workers=2 threshold=100 expected_workers=0 ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
test_expect_success "$mode checkout on clone" '
|
2022-09-30 20:48:56 +00:00
|
|
|
test_config_global protocol.file.allow always &&
|
2021-05-04 16:27:31 +00:00
|
|
|
repo=various_${mode}_clone &&
|
|
|
|
set_checkout_config $workers $threshold &&
|
|
|
|
test_checkout_workers $expected_workers \
|
|
|
|
git clone --recurse-submodules --branch B2 various $repo &&
|
|
|
|
verify_checkout $repo
|
|
|
|
'
|
|
|
|
done
|
|
|
|
|
|
|
|
# Just to be paranoid, actually compare the working trees' contents directly.
|
|
|
|
test_expect_success 'compare the working trees' '
|
|
|
|
rm -rf various_*/.git &&
|
|
|
|
rm -rf various_*/*/.git &&
|
|
|
|
|
|
|
|
# We use `git diff` instead of `diff -r` because the latter would
|
|
|
|
# follow symlinks, and not all `diff` implementations support the
|
|
|
|
# `--no-dereference` option.
|
|
|
|
#
|
|
|
|
git diff --no-index various_sequential various_parallel &&
|
|
|
|
git diff --no-index various_sequential various_parallel_clone &&
|
|
|
|
git diff --no-index various_sequential various_sequential-fallback &&
|
|
|
|
git diff --no-index various_sequential various_sequential-fallback_clone
|
|
|
|
'
|
|
|
|
|
|
|
|
# Currently, each submodule is checked out in a separated child process, but
|
|
|
|
# these subprocesses must also be able to use parallel checkout workers to
|
|
|
|
# write the submodules' entries.
|
|
|
|
test_expect_success 'submodules can use parallel checkout' '
|
|
|
|
set_checkout_config 2 0 &&
|
|
|
|
git init super &&
|
|
|
|
(
|
|
|
|
cd super &&
|
|
|
|
git init sub &&
|
|
|
|
test_commit -C sub A &&
|
|
|
|
test_commit -C sub B &&
|
|
|
|
git submodule add ./sub &&
|
|
|
|
git commit -m sub &&
|
|
|
|
rm sub/* &&
|
|
|
|
test_checkout_workers 2 git checkout --recurse-submodules .
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'parallel checkout respects --[no]-force' '
|
|
|
|
set_checkout_config 2 0 &&
|
|
|
|
git init dirty &&
|
|
|
|
(
|
|
|
|
cd dirty &&
|
|
|
|
mkdir D &&
|
|
|
|
test_commit D/F &&
|
|
|
|
test_commit F &&
|
|
|
|
|
|
|
|
rm -rf D &&
|
|
|
|
echo changed >D &&
|
|
|
|
echo changed >F.t &&
|
|
|
|
|
|
|
|
# We expect 0 workers because there is nothing to be done
|
|
|
|
test_checkout_workers 0 git checkout HEAD &&
|
|
|
|
test_path_is_file D &&
|
|
|
|
grep changed D &&
|
|
|
|
grep changed F.t &&
|
|
|
|
|
|
|
|
test_checkout_workers 2 git checkout --force HEAD &&
|
|
|
|
test_path_is_dir D &&
|
|
|
|
grep D/F D/F.t &&
|
|
|
|
grep F F.t
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success SYMLINKS 'parallel checkout checks for symlinks in leading dirs' '
|
|
|
|
set_checkout_config 2 0 &&
|
|
|
|
git init symlinks &&
|
|
|
|
(
|
|
|
|
cd symlinks &&
|
|
|
|
mkdir D untracked &&
|
|
|
|
# Commit 2 files to have enough work for 2 parallel workers
|
|
|
|
test_commit D/A &&
|
|
|
|
test_commit D/B &&
|
|
|
|
rm -rf D &&
|
|
|
|
ln -s untracked D &&
|
|
|
|
|
|
|
|
test_checkout_workers 2 git checkout --force HEAD &&
|
|
|
|
! test -h D &&
|
|
|
|
grep D/A D/A.t &&
|
|
|
|
grep D/B D/B.t
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2022-07-14 11:49:11 +00:00
|
|
|
# This test is here (and not in e.g. t2022-checkout-paths.sh), because we
|
|
|
|
# check the final report including sequential, parallel, and delayed entries
|
|
|
|
# all at the same time. So we must have finer control of the parallel checkout
|
|
|
|
# variables.
|
2022-08-15 01:06:38 +00:00
|
|
|
test_expect_success '"git checkout ." report should not include failed entries' '
|
2022-07-14 11:49:11 +00:00
|
|
|
test_config_global filter.delay.process \
|
2022-08-15 01:06:38 +00:00
|
|
|
"test-tool rot13-filter --always-delay --log=delayed.log clean smudge delay" &&
|
2022-07-14 11:49:11 +00:00
|
|
|
test_config_global filter.delay.required true &&
|
|
|
|
test_config_global filter.cat.clean cat &&
|
|
|
|
test_config_global filter.cat.smudge cat &&
|
|
|
|
test_config_global filter.cat.required true &&
|
|
|
|
|
|
|
|
set_checkout_config 2 0 &&
|
|
|
|
git init failed_entries &&
|
|
|
|
(
|
|
|
|
cd failed_entries &&
|
|
|
|
cat >.gitattributes <<-EOF &&
|
|
|
|
*delay* filter=delay
|
|
|
|
parallel-ineligible* filter=cat
|
|
|
|
EOF
|
|
|
|
echo a >missing-delay.a &&
|
|
|
|
echo a >parallel-ineligible.a &&
|
|
|
|
echo a >parallel-eligible.a &&
|
|
|
|
echo b >success-delay.b &&
|
|
|
|
echo b >parallel-ineligible.b &&
|
|
|
|
echo b >parallel-eligible.b &&
|
|
|
|
git add -A &&
|
|
|
|
git commit -m files &&
|
|
|
|
|
|
|
|
a_blob="$(git rev-parse :parallel-ineligible.a)" &&
|
|
|
|
rm .git/objects/$(test_oid_to_path $a_blob) &&
|
|
|
|
rm *.a *.b &&
|
|
|
|
|
|
|
|
test_checkout_workers 2 test_must_fail git checkout . 2>err &&
|
|
|
|
|
|
|
|
# All *.b entries should succeed and all *.a entries should fail:
|
|
|
|
# - missing-delay.a: the delay filter will drop this path
|
|
|
|
# - parallel-*.a: the blob will be missing
|
|
|
|
#
|
|
|
|
grep "Updated 3 paths from the index" err &&
|
|
|
|
test_stdout_line_count = 3 ls *.b &&
|
|
|
|
! ls *.a
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2021-05-04 16:27:31 +00:00
|
|
|
test_done
|