278 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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' '
 | |
| 	test_config_global protocol.file.allow always &&
 | |
| 
 | |
| 	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" '
 | |
| 		test_config_global protocol.file.allow always &&
 | |
| 		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
 | 
