| #!/bin/sh | 
 |  | 
 | test_description='core.whitespace rules and git apply' | 
 |  | 
 | . ./test-lib.sh | 
 |  | 
 | prepare_test_file () { | 
 |  | 
 | 	# A line that has character X is touched iff RULE is in effect: | 
 | 	#       X  RULE | 
 | 	#   	!  trailing-space | 
 | 	#   	@  space-before-tab | 
 | 	#   	#  indent-with-non-tab (default tab width 8) | 
 | 	#	=  indent-with-non-tab,tabwidth=16 | 
 | 	#   	%  tab-in-indent | 
 | 	sed -e "s/_/ /g" -e "s/>/	/" <<-\EOF | 
 | 		An_SP in an ordinary line>and a HT. | 
 | 		>A HT (%). | 
 | 		_>A SP and a HT (@%). | 
 | 		_>_A SP, a HT and a SP (@%). | 
 | 		_______Seven SP. | 
 | 		________Eight SP (#). | 
 | 		_______>Seven SP and a HT (@%). | 
 | 		________>Eight SP and a HT (@#%). | 
 | 		_______>_Seven SP, a HT and a SP (@%). | 
 | 		________>_Eight SP, a HT and a SP (@#%). | 
 | 		_______________Fifteen SP (#). | 
 | 		_______________>Fifteen SP and a HT (@#%). | 
 | 		________________Sixteen SP (#=). | 
 | 		________________>Sixteen SP and a HT (@#%=). | 
 | 		_____a__Five SP, a non WS, two SP. | 
 | 		A line with a (!) trailing SP_ | 
 | 		A line with a (!) trailing HT> | 
 | 	EOF | 
 | } | 
 |  | 
 | apply_patch () { | 
 | 	>target && | 
 | 	sed -e "s|\([ab]\)/file|\1/target|" <patch | | 
 | 	git apply "$@" | 
 | } | 
 |  | 
 | test_fix () { | 
 | 	# fix should not barf | 
 | 	apply_patch --whitespace=fix || return 1 | 
 |  | 
 | 	# find touched lines | 
 | 	$DIFF file target | sed -n -e "s/^> //p" >fixed | 
 |  | 
 | 	# the changed lines are all expected to change | 
 | 	fixed_cnt=$(wc -l <fixed) | 
 | 	case "$1" in | 
 | 	'') expect_cnt=$fixed_cnt ;; | 
 | 	?*) expect_cnt=$(grep "[$1]" <fixed | wc -l) ;; | 
 | 	esac | 
 | 	test $fixed_cnt -eq $expect_cnt || return 1 | 
 |  | 
 | 	# and we are not missing anything | 
 | 	case "$1" in | 
 | 	'') expect_cnt=0 ;; | 
 | 	?*) expect_cnt=$(grep "[$1]" <file | wc -l) ;; | 
 | 	esac | 
 | 	test $fixed_cnt -eq $expect_cnt || return 1 | 
 |  | 
 | 	# Get the patch actually applied | 
 | 	git diff-files -p target >fixed-patch | 
 | 	test -s fixed-patch && return 0 | 
 |  | 
 | 	# Make sure it is complaint-free | 
 | 	>target | 
 | 	git apply --whitespace=error-all <fixed-patch | 
 |  | 
 | } | 
 |  | 
 | test_expect_success setup ' | 
 |  | 
 | 	>file && | 
 | 	git add file && | 
 | 	prepare_test_file >file && | 
 | 	git diff-files -p >patch && | 
 | 	>target && | 
 | 	git add target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=nowarn, default rule' ' | 
 |  | 
 | 	apply_patch --whitespace=nowarn && | 
 | 	test_cmp file target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=warn, default rule' ' | 
 |  | 
 | 	apply_patch --whitespace=warn && | 
 | 	test_cmp file target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=error-all, default rule' ' | 
 |  | 
 | 	test_must_fail apply_patch --whitespace=error-all && | 
 | 	test_must_be_empty target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=error-all, no rule' ' | 
 |  | 
 | 	git config core.whitespace -trailing,-space-before,-indent && | 
 | 	apply_patch --whitespace=error-all && | 
 | 	test_cmp file target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=error-all, no rule (attribute)' ' | 
 |  | 
 | 	git config --unset core.whitespace && | 
 | 	echo "target -whitespace" >.gitattributes && | 
 | 	apply_patch --whitespace=error-all && | 
 | 	test_cmp file target | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'spaces inserted by tab-in-indent' ' | 
 |  | 
 | 	git config core.whitespace -trailing,-space,-indent,tab && | 
 | 	rm -f .gitattributes && | 
 | 	test_fix % && | 
 | 	sed -e "s/_/ /g" -e "s/>/	/" <<-\EOF >expect && | 
 | 		An_SP in an ordinary line>and a HT. | 
 | 		________A HT (%). | 
 | 		________A SP and a HT (@%). | 
 | 		_________A SP, a HT and a SP (@%). | 
 | 		_______Seven SP. | 
 | 		________Eight SP (#). | 
 | 		________Seven SP and a HT (@%). | 
 | 		________________Eight SP and a HT (@#%). | 
 | 		_________Seven SP, a HT and a SP (@%). | 
 | 		_________________Eight SP, a HT and a SP (@#%). | 
 | 		_______________Fifteen SP (#). | 
 | 		________________Fifteen SP and a HT (@#%). | 
 | 		________________Sixteen SP (#=). | 
 | 		________________________Sixteen SP and a HT (@#%=). | 
 | 		_____a__Five SP, a non WS, two SP. | 
 | 		A line with a (!) trailing SP_ | 
 | 		A line with a (!) trailing HT> | 
 | 	EOF | 
 | 	test_cmp expect target | 
 |  | 
 | ' | 
 |  | 
 | for t in - '' | 
 | do | 
 | 	case "$t" in '') tt='!' ;; *) tt= ;; esac | 
 | 	for s in - '' | 
 | 	do | 
 | 		case "$s" in '') ts='@' ;; *) ts= ;; esac | 
 | 		for i in - '' | 
 | 		do | 
 | 			case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac | 
 | 			for h in - '' | 
 | 			do | 
 | 				[ -z "$h$i" ] && continue | 
 | 				case "$h" in '') th='%' ;; *) th= ;; esac | 
 | 				rule=${t}trailing,${s}space,${i}indent,${h}tab | 
 |  | 
 | 				rm -f .gitattributes | 
 | 				test_expect_success "rule=$rule" ' | 
 | 					git config core.whitespace "$rule" && | 
 | 					test_fix "$tt$ts$ti$th" | 
 | 				' | 
 |  | 
 | 				test_expect_success "rule=$rule,tabwidth=16" ' | 
 | 					git config core.whitespace "$rule,tabwidth=16" && | 
 | 					test_fix "$tt$ts$ti16$th" | 
 | 				' | 
 |  | 
 | 				test_expect_success "rule=$rule (attributes)" ' | 
 | 					git config --unset core.whitespace && | 
 | 					echo "target whitespace=$rule" >.gitattributes && | 
 | 					test_fix "$tt$ts$ti$th" | 
 | 				' | 
 |  | 
 | 				test_expect_success "rule=$rule,tabwidth=16 (attributes)" ' | 
 | 					echo "target whitespace=$rule,tabwidth=16" >.gitattributes && | 
 | 					test_fix "$tt$ts$ti16$th" | 
 | 				' | 
 |  | 
 | 			done | 
 | 		done | 
 | 	done | 
 | done | 
 |  | 
 | create_patch () { | 
 | 	sed -e "s/_/ /" <<-\EOF | 
 | 		diff --git a/target b/target | 
 | 		index e69de29..8bd6648 100644 | 
 | 		--- a/target | 
 | 		+++ b/target | 
 | 		@@ -0,0 +1,3 @@ | 
 | 		+An empty line follows | 
 | 		+ | 
 | 		+A line with trailing whitespace and no newline_ | 
 | 		\ No newline at end of file | 
 | 	EOF | 
 | } | 
 |  | 
 | test_expect_success 'trailing whitespace & no newline at the end of file' ' | 
 | 	>target && | 
 | 	create_patch >patch-file && | 
 | 	git apply --whitespace=fix patch-file && | 
 | 	grep "newline$" target && | 
 | 	grep "^$" target | 
 | ' | 
 |  | 
 | test_expect_success 'blank at EOF with --whitespace=fix (1)' ' | 
 | 	test_might_fail git config --unset core.whitespace && | 
 | 	rm -f .gitattributes && | 
 |  | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 | 	{ echo a; echo b; echo c; } >expect && | 
 | 	{ cat expect; echo; } >one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'blank at EOF with --whitespace=fix (2)' ' | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 | 	{ echo a; echo c; } >expect && | 
 | 	{ cat expect; echo; echo; } >one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'blank at EOF with --whitespace=fix (3)' ' | 
 | 	{ echo a; echo b; echo; } >one && | 
 | 	git add one && | 
 | 	{ echo a; echo c; echo; } >expect && | 
 | 	{ cat expect; echo; echo; } >one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' ' | 
 | 	{ echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one && | 
 | 	git add one && | 
 | 	{ echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect && | 
 | 	cp expect one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'blank at EOF with --whitespace=warn' ' | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 | 	echo >>one && | 
 | 	cat one >expect && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=warn patch 2>error && | 
 | 	test_cmp expect one && | 
 | 	grep "new blank line at EOF" error | 
 | ' | 
 |  | 
 | test_expect_success 'blank at EOF with --whitespace=error' ' | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 | 	cat one >expect && | 
 | 	echo >>one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	test_must_fail git apply --whitespace=error patch 2>error && | 
 | 	test_cmp expect one && | 
 | 	grep "new blank line at EOF" error | 
 | ' | 
 |  | 
 | test_expect_success 'blank but not empty at EOF' ' | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 | 	echo "   " >>one && | 
 | 	cat one >expect && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	git apply --whitespace=warn patch 2>error && | 
 | 	test_cmp expect one && | 
 | 	grep "new blank line at EOF" error | 
 | ' | 
 |  | 
 | test_expect_success 'applying beyond EOF requires one non-blank context line' ' | 
 | 	{ echo; echo; echo; echo; } >one && | 
 | 	git add one && | 
 | 	{ echo b; } >>one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	git checkout one && | 
 | 	{ echo a; echo; } >one && | 
 | 	cp one expect && | 
 | 	test_must_fail git apply --whitespace=fix patch && | 
 | 	test_cmp expect one && | 
 | 	test_must_fail git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'tons of blanks at EOF should not apply' ' | 
 | 	for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do | 
 | 		echo; echo; echo; echo; | 
 | 	done >one && | 
 | 	git add one && | 
 | 	echo a >>one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	>one && | 
 | 	test_must_fail git apply --whitespace=fix patch && | 
 | 	test_must_fail git apply --ignore-space-change --whitespace=fix patch | 
 | ' | 
 |  | 
 | test_expect_success 'missing blank line at end with --whitespace=fix' ' | 
 | 	echo a >one && | 
 | 	echo >>one && | 
 | 	git add one && | 
 | 	echo b >>one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	echo a >one && | 
 | 	cp one saved-one && | 
 | 	test_must_fail git apply patch && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one && | 
 | 	mv saved-one one && | 
 | 	git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'two missing blank lines at end with --whitespace=fix' ' | 
 | 	{ echo a; echo; echo b; echo c; } >one && | 
 | 	cp one no-blank-lines && | 
 | 	{ echo; echo; } >>one && | 
 | 	git add one && | 
 | 	echo d >>one && | 
 | 	cp one expect && | 
 | 	echo >>one && | 
 | 	git diff -- one >patch && | 
 | 	cp no-blank-lines one && | 
 | 	test_must_fail git apply patch && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one && | 
 | 	mv no-blank-lines one && | 
 | 	test_must_fail git apply patch && | 
 | 	git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' ' | 
 | 	{ echo a; echo; } >one && | 
 | 	git add one && | 
 | 	{ echo b; echo a; echo; } >one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	echo a >one && | 
 | 	test_must_fail git apply patch && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'shrink file with tons of missing blanks at end of file' ' | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	cp one no-blank-lines && | 
 | 	for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do | 
 | 		echo; echo; echo; echo; | 
 | 	done >>one && | 
 | 	git add one && | 
 | 	echo a >one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	cp no-blank-lines one && | 
 | 	test_must_fail git apply patch && | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one && | 
 | 	mv no-blank-lines one && | 
 | 	git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'missing blanks at EOF must only match blank lines' ' | 
 | 	{ echo a; echo b; } >one && | 
 | 	git add one && | 
 | 	{ echo c; echo d; } >>one && | 
 | 	git diff -- one >patch && | 
 |  | 
 | 	echo a >one && | 
 | 	test_must_fail git apply patch && | 
 | 	test_must_fail git apply --whitespace=fix patch && | 
 | 	test_must_fail git apply --ignore-space-change --whitespace=fix patch | 
 | ' | 
 |  | 
 | sed -e's/Z//' >one <<EOF | 
 | a | 
 | b | 
 | c | 
 | 		      Z | 
 | EOF | 
 |  | 
 | test_expect_success 'missing blank line should match context line with spaces' ' | 
 | 	git add one && | 
 | 	echo d >>one && | 
 | 	git diff -- one >patch && | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	cp one expect && | 
 | 	{ echo; echo d; } >>expect && | 
 | 	git add one && | 
 |  | 
 | 	git apply --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | sed -e's/Z//' >one <<EOF | 
 | a | 
 | b | 
 | c | 
 | 		      Z | 
 | EOF | 
 |  | 
 | test_expect_success 'same, but with the --ignore-space-option' ' | 
 | 	git add one && | 
 | 	echo d >>one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	{ echo a; echo b; echo c; } >one && | 
 | 	git add one && | 
 |  | 
 | 	git checkout-index -f one && | 
 | 	git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' ' | 
 | 	git config core.whitespace cr-at-eol && | 
 | 	printf "a\r\n" >one && | 
 | 	printf "b\r\n" >>one && | 
 | 	printf "c\r\n" >>one && | 
 | 	cp one save-one && | 
 | 	printf "                 \r\n" >>one && | 
 | 	git add one && | 
 | 	printf "d\r\n" >>one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	mv save-one one && | 
 |  | 
 | 	git apply --ignore-space-change --whitespace=fix patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'CR-LF line endings && add line && text=auto' ' | 
 | 	git config --unset core.whitespace && | 
 | 	printf "a\r\n" >one && | 
 | 	cp one save-one && | 
 | 	git add one && | 
 | 	printf "b\r\n" >>one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	mv save-one one && | 
 | 	echo "one text=auto" >.gitattributes && | 
 | 	git apply patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'CR-LF line endings && change line && text=auto' ' | 
 | 	printf "a\r\n" >one && | 
 | 	cp one save-one && | 
 | 	git add one && | 
 | 	printf "b\r\n" >one && | 
 | 	cp one expect && | 
 | 	git diff -- one >patch && | 
 | 	mv save-one one && | 
 | 	echo "one text=auto" >.gitattributes && | 
 | 	git apply patch && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'LF in repo, CRLF in worktree && change line && text=auto' ' | 
 | 	printf "a\n" >one && | 
 | 	git add one && | 
 | 	printf "b\r\n" >one && | 
 | 	git diff -- one >patch && | 
 | 	printf "a\r\n" >one && | 
 | 	echo "one text=auto" >.gitattributes && | 
 | 	git -c core.eol=CRLF apply patch && | 
 | 	printf "b\r\n" >expect && | 
 | 	test_cmp expect one | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace=fix to expand' ' | 
 | 	qz_to_tab_space >preimage <<-\EOF && | 
 | 	QQa | 
 | 	QQb | 
 | 	QQc | 
 | 	ZZZZZZZZZZZZZZZZd | 
 | 	QQe | 
 | 	QQf | 
 | 	QQg | 
 | 	EOF | 
 | 	qz_to_tab_space >patch <<-\EOF && | 
 | 	diff --git a/preimage b/preimage | 
 | 	--- a/preimage | 
 | 	+++ b/preimage | 
 | 	@@ -1,7 +1,6 @@ | 
 | 	 QQa | 
 | 	 QQb | 
 | 	 QQc | 
 | 	-QQd | 
 | 	 QQe | 
 | 	 QQf | 
 | 	 QQg | 
 | 	EOF | 
 | 	git -c core.whitespace=tab-in-indent apply --whitespace=fix patch | 
 | ' | 
 |  | 
 | test_expect_success 'whitespace check skipped for excluded paths' ' | 
 | 	git config core.whitespace blank-at-eol && | 
 | 	>used && | 
 | 	>unused && | 
 | 	git add used unused && | 
 | 	echo "used" >used && | 
 | 	echo "unused " >unused && | 
 | 	git diff-files -p used unused >patch && | 
 | 	git apply --include=used --stat --whitespace=error <patch | 
 | ' | 
 |  | 
 | test_done |