#!/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 . ./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' ' 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 && cp -R -P various $repo && # 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" ' 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 ) ' # 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. test_expect_success '"git checkout ." report should not include failed entries' ' test_config_global filter.delay.process \ "test-tool rot13-filter --always-delay --log=delayed.log clean smudge delay" && 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 ) ' test_done