305 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			305 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
| #!/bin/sh
 | |
| 
 | |
| test_description='git fetch output format'
 | |
| 
 | |
| GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 | |
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 | |
| 
 | |
| . ./test-lib.sh
 | |
| 
 | |
| test_expect_success 'fetch with invalid output format configuration' '
 | |
| 	test_when_finished "rm -rf clone" &&
 | |
| 	git clone . clone &&
 | |
| 
 | |
| 	test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	error: missing value for ${SQ}fetch.output${SQ}
 | |
| 	fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
 | |
| 	EOF
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
 | |
| 	EOF
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
 | |
| 	EOF
 | |
| 	test_cmp expect actual.err
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch aligned output' '
 | |
| 	git clone . full-output &&
 | |
| 	test_commit looooooooooooong-tag &&
 | |
| 	(
 | |
| 		cd full-output &&
 | |
| 		git -c fetch.output=full fetch origin >actual 2>&1 &&
 | |
| 		grep -e "->" actual | cut -c 22- >../actual
 | |
| 	) &&
 | |
| 	cat >expect <<-\EOF &&
 | |
| 	main                 -> origin/main
 | |
| 	looooooooooooong-tag -> looooooooooooong-tag
 | |
| 	EOF
 | |
| 	test_cmp expect actual
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch compact output' '
 | |
| 	git clone . compact &&
 | |
| 	test_commit extraaa &&
 | |
| 	(
 | |
| 		cd compact &&
 | |
| 		git -c fetch.output=compact fetch origin >actual 2>&1 &&
 | |
| 		grep -e "->" actual | cut -c 22- >../actual
 | |
| 	) &&
 | |
| 	cat >expect <<-\EOF &&
 | |
| 	main       -> origin/*
 | |
| 	extraaa    -> *
 | |
| 	EOF
 | |
| 	test_cmp expect actual
 | |
| '
 | |
| 
 | |
| test_expect_success 'setup for fetch porcelain output' '
 | |
| 	# Set up a bunch of references that we can use to demonstrate different
 | |
| 	# kinds of flag symbols in the output format.
 | |
| 	test_commit commit-for-porcelain-output &&
 | |
| 	MAIN_OLD=$(git rev-parse HEAD) &&
 | |
| 	git branch "fast-forward" &&
 | |
| 	git branch "deleted-branch" &&
 | |
| 	git checkout -b force-updated &&
 | |
| 	test_commit --no-tag force-update-old &&
 | |
| 	FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
 | |
| 	git checkout main &&
 | |
| 
 | |
| 	# Backup to preseed.git
 | |
| 	git clone --mirror . preseed.git &&
 | |
| 
 | |
| 	# Continue changing our local references.
 | |
| 	git branch new-branch &&
 | |
| 	git branch -d deleted-branch &&
 | |
| 	git checkout fast-forward &&
 | |
| 	test_commit --no-tag fast-forward-new &&
 | |
| 	FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
 | |
| 	git checkout force-updated &&
 | |
| 	git reset --hard HEAD~ &&
 | |
| 	test_commit --no-tag force-update-new &&
 | |
| 	FORCE_UPDATED_NEW=$(git rev-parse HEAD)
 | |
| '
 | |
| 
 | |
| for opt in "" "--atomic"
 | |
| do
 | |
| 	test_expect_success "fetch porcelain output ${opt:+(atomic)}" '
 | |
| 		test_when_finished "rm -rf porcelain" &&
 | |
| 
 | |
| 		# Clone and pre-seed the repositories. We fetch references into two
 | |
| 		# namespaces so that we can test that rejected and force-updated
 | |
| 		# references are reported properly.
 | |
| 		refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
 | |
| 		git clone preseed.git porcelain &&
 | |
| 		git -C porcelain fetch origin $opt $refspecs &&
 | |
| 
 | |
| 		cat >expect <<-EOF &&
 | |
| 		- $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
 | |
| 		- $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
 | |
| 		  $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
 | |
| 		! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
 | |
| 		* $ZERO_OID $MAIN_OLD refs/unforced/new-branch
 | |
| 		  $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
 | |
| 		+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
 | |
| 		* $ZERO_OID $MAIN_OLD refs/forced/new-branch
 | |
| 		  $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
 | |
| 		+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
 | |
| 		* $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
 | |
| 		EOF
 | |
| 
 | |
| 		# Change the URL of the repository to fetch different references.
 | |
| 		git -C porcelain remote set-url origin .. &&
 | |
| 
 | |
| 		# Execute a dry-run fetch first. We do this to assert that the dry-run
 | |
| 		# and non-dry-run fetches produces the same output. Execution of the
 | |
| 		# fetch is expected to fail as we have a rejected reference update.
 | |
| 		test_must_fail git -C porcelain fetch $opt \
 | |
| 			--porcelain --dry-run --prune origin $refspecs >actual &&
 | |
| 		test_cmp expect actual &&
 | |
| 
 | |
| 		# And now we perform a non-dry-run fetch.
 | |
| 		test_must_fail git -C porcelain fetch $opt \
 | |
| 			--porcelain --prune origin $refspecs >actual 2>stderr &&
 | |
| 		test_cmp expect actual &&
 | |
| 		test_must_be_empty stderr
 | |
| 	'
 | |
| done
 | |
| 
 | |
| test_expect_success 'fetch porcelain with multiple remotes' '
 | |
| 	test_when_finished "rm -rf porcelain" &&
 | |
| 
 | |
| 	git switch --create multiple-remotes &&
 | |
| 	git clone . porcelain &&
 | |
| 	git -C porcelain remote add second-remote "$PWD" &&
 | |
| 	git -C porcelain fetch second-remote &&
 | |
| 
 | |
| 	test_commit --no-tag multi-commit &&
 | |
| 	old_commit=$(git rev-parse HEAD~) &&
 | |
| 	new_commit=$(git rev-parse HEAD) &&
 | |
| 
 | |
| 	cat >expect <<-EOF &&
 | |
| 	  $old_commit $new_commit refs/remotes/origin/multiple-remotes
 | |
| 	  $old_commit $new_commit refs/remotes/second-remote/multiple-remotes
 | |
| 	EOF
 | |
| 
 | |
| 	git -C porcelain fetch --porcelain --all >actual 2>stderr &&
 | |
| 	test_cmp expect actual &&
 | |
| 	test_must_be_empty stderr
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch porcelain refuses to work with submodules' '
 | |
| 	test_when_finished "rm -rf porcelain" &&
 | |
| 
 | |
| 	cat >expect <<-EOF &&
 | |
| 	fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
 | |
| 	EOF
 | |
| 
 | |
| 	git init porcelain &&
 | |
| 	test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
 | |
| 	test_cmp expect stderr &&
 | |
| 
 | |
| 	test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
 | |
| 	test_cmp expect stderr
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch porcelain overrides fetch.output config' '
 | |
| 	test_when_finished "rm -rf porcelain" &&
 | |
| 
 | |
| 	git switch --create config-override &&
 | |
| 	git clone . porcelain &&
 | |
| 	test_commit new-commit &&
 | |
| 	old_commit=$(git rev-parse HEAD~) &&
 | |
| 	new_commit=$(git rev-parse HEAD) &&
 | |
| 
 | |
| 	cat >expect <<-EOF &&
 | |
| 	  $old_commit $new_commit refs/remotes/origin/config-override
 | |
| 	* $ZERO_OID $new_commit refs/tags/new-commit
 | |
| 	EOF
 | |
| 
 | |
| 	git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
 | |
| 	test_must_be_empty stderr &&
 | |
| 	test_cmp expect stdout
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch --no-porcelain overrides previous --porcelain' '
 | |
| 	test_when_finished "rm -rf no-porcelain" &&
 | |
| 
 | |
| 	git switch --create no-porcelain &&
 | |
| 	git clone . no-porcelain &&
 | |
| 	test_commit --no-tag no-porcelain &&
 | |
| 	old_commit=$(git rev-parse --short HEAD~) &&
 | |
| 	new_commit=$(git rev-parse --short HEAD) &&
 | |
| 
 | |
| 	cat >expect <<-EOF &&
 | |
| 	From $(test-tool path-utils real_path .)/.
 | |
| 	   $old_commit..$new_commit  no-porcelain -> origin/no-porcelain
 | |
| 	EOF
 | |
| 
 | |
| 	git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
 | |
| 	test_cmp expect stderr &&
 | |
| 	test_must_be_empty stdout
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch output with HEAD' '
 | |
| 	test_when_finished "rm -rf head" &&
 | |
| 	git clone . head &&
 | |
| 
 | |
| 	git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	From $(test-tool path-utils real_path .)/.
 | |
| 	 * branch            HEAD       -> FETCH_HEAD
 | |
| 	EOF
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	git -C head fetch origin HEAD >actual.out 2>actual.err &&
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	From $(test-tool path-utils real_path .)/.
 | |
| 	 * [new ref]         HEAD       -> foo
 | |
| 	EOF
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch porcelain output with HEAD' '
 | |
| 	test_when_finished "rm -rf head" &&
 | |
| 	git clone . head &&
 | |
| 	COMMIT_ID=$(git rev-parse HEAD) &&
 | |
| 
 | |
| 	git -C head fetch --porcelain --dry-run origin HEAD >actual &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	* $ZERO_OID $COMMIT_ID FETCH_HEAD
 | |
| 	EOF
 | |
| 	test_cmp expect actual &&
 | |
| 
 | |
| 	git -C head fetch --porcelain origin HEAD >actual &&
 | |
| 	test_cmp expect actual &&
 | |
| 
 | |
| 	git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	* $ZERO_OID $COMMIT_ID refs/heads/foo
 | |
| 	EOF
 | |
| 	test_cmp expect actual &&
 | |
| 
 | |
| 	git -C head fetch --porcelain origin HEAD:foo >actual &&
 | |
| 	test_cmp expect actual
 | |
| '
 | |
| 
 | |
| test_expect_success 'fetch output with object ID' '
 | |
| 	test_when_finished "rm -rf object-id" &&
 | |
| 	git clone . object-id &&
 | |
| 	commit=$(git rev-parse HEAD) &&
 | |
| 
 | |
| 	git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
 | |
| 	cat >expect <<-EOF &&
 | |
| 	From $(test-tool path-utils real_path .)/.
 | |
| 	 * [new ref]         $commit -> object-id
 | |
| 	EOF
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err &&
 | |
| 
 | |
| 	git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
 | |
| 	test_must_be_empty actual.out &&
 | |
| 	test_cmp expect actual.err
 | |
| '
 | |
| 
 | |
| test_expect_success '--no-show-forced-updates' '
 | |
| 	mkdir forced-updates &&
 | |
| 	(
 | |
| 		cd forced-updates &&
 | |
| 		git init &&
 | |
| 		test_commit 1 &&
 | |
| 		test_commit 2
 | |
| 	) &&
 | |
| 	git clone forced-updates forced-update-clone &&
 | |
| 	git clone forced-updates no-forced-update-clone &&
 | |
| 	git -C forced-updates reset --hard HEAD~1 &&
 | |
| 	(
 | |
| 		cd forced-update-clone &&
 | |
| 		git fetch --show-forced-updates origin 2>output &&
 | |
| 		test_grep "(forced update)" output
 | |
| 	) &&
 | |
| 	(
 | |
| 		cd no-forced-update-clone &&
 | |
| 		git fetch --no-show-forced-updates origin 2>output &&
 | |
| 		test_grep ! "(forced update)" output
 | |
| 	)
 | |
| '
 | |
| 
 | |
| test_done
 |