| #!/bin/sh | 
 |  | 
 | test_description='diff --relative tests' | 
 |  | 
 | . ./test-lib.sh | 
 |  | 
 | test_expect_success 'setup' ' | 
 | 	git commit --allow-empty -m empty && | 
 | 	echo content >file1 && | 
 | 	mkdir subdir && | 
 | 	echo other content >subdir/file2 && | 
 | 	blob_file1=$(git hash-object file1) && | 
 | 	blob_file2=$(git hash-object subdir/file2) && | 
 | 	git add . && | 
 | 	git commit -m one | 
 | ' | 
 |  | 
 | check_diff () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	short_blob=$(git rev-parse --short $blob_file2) | 
 | 	cat >expected <<-EOF | 
 | 	diff --git a/$expect b/$expect | 
 | 	new file mode 100644 | 
 | 	index 0000000..$short_blob | 
 | 	--- /dev/null | 
 | 	+++ b/$expect | 
 | 	@@ -0,0 +1 @@ | 
 | 	+other content | 
 | 	EOF | 
 | 	test_expect_success "-p $*" " | 
 | 		git -C '$dir' diff -p $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | check_numstat () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	cat >expected <<-EOF | 
 | 	1	0	$expect | 
 | 	EOF | 
 | 	test_expect_success "--numstat $*" " | 
 | 		echo '1	0	$expect' >expected && | 
 | 		git -C '$dir' diff --numstat $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | check_stat () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	cat >expected <<-EOF | 
 | 	 $expect | 1 + | 
 | 	 1 file changed, 1 insertion(+) | 
 | 	EOF | 
 | 	test_expect_success "--stat $*" " | 
 | 		git -C '$dir' diff --stat $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | check_raw () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	cat >expected <<-EOF | 
 | 	:000000 100644 $ZERO_OID $blob_file2 A	$expect | 
 | 	EOF | 
 | 	test_expect_success "--raw $*" " | 
 | 		git -C '$dir' diff --no-abbrev --raw $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | for type in diff numstat stat raw | 
 | do | 
 | 	check_$type . file2 --relative=subdir/ | 
 | 	check_$type . file2 --relative=subdir | 
 | 	check_$type subdir file2 --relative | 
 | 	check_$type . dir/file2 --relative=sub | 
 | done | 
 |  | 
 | check_diff_relative_option () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	relative_opt=$1 | 
 | 	shift | 
 | 	test_expect_success "config diff.relative $relative_opt -p $*" " | 
 | 		short_blob=\$(git rev-parse --short $blob_file2) && | 
 | 		cat >expected <<-EOF && | 
 | 		diff --git a/$expect b/$expect | 
 | 		new file mode 100644 | 
 | 		index 0000000..\$short_blob | 
 | 		--- /dev/null | 
 | 		+++ b/$expect | 
 | 		@@ -0,0 +1 @@ | 
 | 		+other content | 
 | 		EOF | 
 | 		test_config -C $dir diff.relative $relative_opt && | 
 | 		git -C '$dir' diff -p $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | check_diff_no_relative_option () { | 
 | 	dir=$1 | 
 | 	shift | 
 | 	expect=$1 | 
 | 	shift | 
 | 	relative_opt=$1 | 
 | 	shift | 
 | 	test_expect_success "config diff.relative $relative_opt -p $*" " | 
 | 		short_blob_file1=\$(git rev-parse --short $blob_file1) && | 
 | 		short_blob_file2=\$(git rev-parse --short $blob_file2) && | 
 | 		cat >expected <<-EOF && | 
 | 		diff --git a/file1 b/file1 | 
 | 		new file mode 100644 | 
 | 		index 0000000..\$short_blob_file1 | 
 | 		--- /dev/null | 
 | 		+++ b/file1 | 
 | 		@@ -0,0 +1 @@ | 
 | 		+content | 
 | 		diff --git a/$expect b/$expect | 
 | 		new file mode 100644 | 
 | 		index 0000000..\$short_blob_file2 | 
 | 		--- /dev/null | 
 | 		+++ b/$expect | 
 | 		@@ -0,0 +1 @@ | 
 | 		+other content | 
 | 		EOF | 
 | 		test_config -C $dir diff.relative $relative_opt && | 
 | 		git -C '$dir' diff -p $* HEAD^ >actual && | 
 | 		test_cmp expected actual | 
 | 	" | 
 | } | 
 |  | 
 | check_diff_no_relative_option . subdir/file2 false | 
 | check_diff_no_relative_option . subdir/file2 true --no-relative | 
 | check_diff_no_relative_option . subdir/file2 false --no-relative | 
 | check_diff_no_relative_option subdir subdir/file2 false | 
 | check_diff_no_relative_option subdir subdir/file2 true --no-relative | 
 | check_diff_no_relative_option subdir subdir/file2 false --no-relative | 
 |  | 
 | check_diff_relative_option . file2 false --relative=subdir/ | 
 | check_diff_relative_option . file2 false --relative=subdir | 
 | check_diff_relative_option . file2 true --relative=subdir/ | 
 | check_diff_relative_option . file2 true --relative=subdir | 
 | check_diff_relative_option subdir file2 false --relative | 
 | check_diff_relative_option subdir file2 true --relative | 
 | check_diff_relative_option subdir file2 true | 
 | check_diff_relative_option subdir file2 false --no-relative --relative | 
 | check_diff_relative_option subdir file2 true --no-relative --relative | 
 | check_diff_relative_option . file2 false --no-relative --relative=subdir | 
 | check_diff_relative_option . file2 true --no-relative --relative=subdir | 
 |  | 
 | test_expect_success 'external diff with --relative' ' | 
 | 	test_when_finished "git reset --hard" && | 
 | 	echo changed >file1 && | 
 | 	echo changed >subdir/file2 && | 
 |  | 
 | 	write_script mydiff <<-\EOF && | 
 | 	# hacky pretend diff; the goal here is just to make sure we got | 
 | 	# passed sensible input that we _could_ diff, without relying on | 
 | 	# the specific output of a system diff tool. | 
 | 	echo "diff a/$1 b/$1" && | 
 | 	echo "--- a/$1" && | 
 | 	echo "+++ b/$1" && | 
 | 	echo "@@ -1 +0,0 @@" && | 
 | 	sed "s/^/-/" "$2" && | 
 | 	sed "s/^/+/" "$5" | 
 | 	EOF | 
 |  | 
 | 	cat >expect <<-\EOF && | 
 | 	diff a/file2 b/file2 | 
 | 	--- a/file2 | 
 | 	+++ b/file2 | 
 | 	@@ -1 +0,0 @@ | 
 | 	-other content | 
 | 	+changed | 
 | 	EOF | 
 | 	GIT_EXTERNAL_DIFF=./mydiff git diff --relative=subdir >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'setup diff --relative unmerged' ' | 
 | 	test_commit zero file0 && | 
 | 	test_commit base subdir/file0 && | 
 | 	git switch -c br1 && | 
 | 	test_commit one file0 && | 
 | 	test_commit sub1 subdir/file0 && | 
 | 	git switch -c br2 base && | 
 | 	test_commit two file0 && | 
 | 	git switch -c br3 && | 
 | 	test_commit sub3 subdir/file0 | 
 | ' | 
 |  | 
 | test_expect_success 'diff --relative without change in subdir' ' | 
 | 	git switch br2 && | 
 | 	test_when_finished "git merge --abort" && | 
 | 	test_must_fail git merge one && | 
 | 	git -C subdir diff --relative >out && | 
 | 	test_must_be_empty out && | 
 | 	git -C subdir diff --relative --name-only >out && | 
 | 	test_must_be_empty out | 
 | ' | 
 |  | 
 | test_expect_success 'diff --relative --name-only with change in subdir' ' | 
 | 	git switch br3 && | 
 | 	test_when_finished "git merge --abort" && | 
 | 	test_must_fail git merge sub1 && | 
 | 	test_write_lines file0 file0 >expected && | 
 | 	git -C subdir diff --relative --name-only >out && | 
 | 	test_cmp expected out | 
 | ' | 
 |  | 
 | test_expect_failure 'diff --relative with change in subdir' ' | 
 | 	git switch br3 && | 
 | 	br1_blob=$(git rev-parse --short --verify br1:subdir/file0) && | 
 | 	br3_blob=$(git rev-parse --short --verify br3:subdir/file0) && | 
 | 	test_when_finished "git merge --abort" && | 
 | 	test_must_fail git merge br1 && | 
 | 	cat >expected <<-EOF && | 
 | 	diff --cc file0 | 
 | 	index $br3_blob,$br1_blob..0000000 | 
 | 	--- a/file0 | 
 | 	+++ b/file0 | 
 | 	@@@ -1,1 -1,1 +1,5 @@@ | 
 | 	++<<<<<<< HEAD | 
 | 	 +sub3 | 
 | 	++======= | 
 | 	+ sub1 | 
 | 	++>>>>>>> br1 | 
 | 	EOF | 
 | 	git -C subdir diff --relative >out && | 
 | 	test_cmp expected out | 
 | ' | 
 |  | 
 | test_done |