1#!/bin/sh
2
3test_description='diff --no-index'
4
5. ./test-lib.sh
6
7test_expect_success 'setup' '
8	mkdir a &&
9	mkdir b &&
10	echo 1 >a/1 &&
11	echo 2 >a/2 &&
12	git init repo &&
13	echo 1 >repo/a &&
14	mkdir -p non/git &&
15	echo 1 >non/git/a &&
16	echo 1 >non/git/b
17'
18
19test_expect_success 'git diff --no-index --exit-code' '
20	git diff --no-index --exit-code a/1 non/git/a &&
21	test_expect_code 1 git diff --no-index --exit-code a/1 a/2
22'
23
24test_expect_success 'git diff --no-index directories' '
25	test_expect_code 1 git diff --no-index a b >cnt &&
26	test_line_count = 14 cnt
27'
28
29test_expect_success 'git diff --no-index relative path outside repo' '
30	(
31		cd repo &&
32		test_expect_code 0 git diff --no-index a ../non/git/a &&
33		test_expect_code 0 git diff --no-index ../non/git/a ../non/git/b
34	)
35'
36
37test_expect_success 'git diff --no-index with broken index' '
38	(
39		cd repo &&
40		echo broken >.git/index &&
41		git diff --no-index a ../non/git/a
42	)
43'
44
45test_expect_success 'git diff outside repo with broken index' '
46	(
47		cd repo &&
48		git diff ../non/git/a ../non/git/b
49	)
50'
51
52test_expect_success 'git diff --no-index executed outside repo gives correct error message' '
53	(
54		GIT_CEILING_DIRECTORIES=$TRASH_DIRECTORY/non &&
55		export GIT_CEILING_DIRECTORIES &&
56		cd non/git &&
57		test_must_fail git diff --no-index a 2>actual.err &&
58		test_i18ngrep "usage: git diff --no-index" actual.err
59	)
60'
61
62test_expect_success 'diff D F and diff F D' '
63	(
64		cd repo &&
65		echo in-repo >a &&
66		echo non-repo >../non/git/a &&
67		mkdir sub &&
68		echo sub-repo >sub/a &&
69
70		test_must_fail git diff --no-index sub/a ../non/git/a >expect &&
71		test_must_fail git diff --no-index sub/a ../non/git/ >actual &&
72		test_cmp expect actual &&
73
74		test_must_fail git diff --no-index a ../non/git/a >expect &&
75		test_must_fail git diff --no-index a ../non/git/ >actual &&
76		test_cmp expect actual &&
77
78		test_must_fail git diff --no-index ../non/git/a a >expect &&
79		test_must_fail git diff --no-index ../non/git a >actual &&
80		test_cmp expect actual
81	)
82'
83
84test_expect_success 'turning a file into a directory' '
85	(
86		cd non/git &&
87		mkdir d e e/sub &&
88		echo 1 >d/sub &&
89		echo 2 >e/sub/file &&
90		printf "D\td/sub\nA\te/sub/file\n" >expect &&
91		test_must_fail git diff --no-index --name-status d e >actual &&
92		test_cmp expect actual
93	)
94'
95
96test_expect_success 'diff from repo subdir shows real paths (explicit)' '
97	echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
98	test_expect_code 1 \
99		git -C repo/sub \
100		diff --no-index ../../non/git/a ../../non/git/b >actual &&
101	head -n 1 <actual >actual.head &&
102	test_cmp expect actual.head
103'
104
105test_expect_success 'diff from repo subdir shows real paths (implicit)' '
106	echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
107	test_expect_code 1 \
108		git -C repo/sub \
109		diff ../../non/git/a ../../non/git/b >actual &&
110	head -n 1 <actual >actual.head &&
111	test_cmp expect actual.head
112'
113
114test_expect_success 'diff --no-index from repo subdir respects config (explicit)' '
115	echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
116	test_config -C repo diff.noprefix true &&
117	test_expect_code 1 \
118		git -C repo/sub \
119		diff --no-index ../../non/git/a ../../non/git/b >actual &&
120	head -n 1 <actual >actual.head &&
121	test_cmp expect actual.head
122'
123
124test_expect_success 'diff --no-index from repo subdir respects config (implicit)' '
125	echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
126	test_config -C repo diff.noprefix true &&
127	test_expect_code 1 \
128		git -C repo/sub \
129		diff ../../non/git/a ../../non/git/b >actual &&
130	head -n 1 <actual >actual.head &&
131	test_cmp expect actual.head
132'
133
134test_expect_success 'diff --no-index from repo subdir with absolute paths' '
135	cat <<-EOF >expect &&
136	1	1	$(pwd)/non/git/{a => b}
137	EOF
138	test_expect_code 1 \
139		git -C repo/sub diff --numstat \
140		"$(pwd)/non/git/a" "$(pwd)/non/git/b" >actual &&
141	test_cmp expect actual
142'
143
144test_expect_success 'diff --no-index allows external diff' '
145	test_expect_code 1 \
146		env GIT_EXTERNAL_DIFF="echo external ;:" \
147		git diff --no-index non/git/a non/git/b >actual &&
148	echo external >expect &&
149	test_cmp expect actual
150'
151
152test_expect_success 'diff --no-index normalizes mode: no changes' '
153	echo foo >x &&
154	cp x y &&
155	git diff --no-index x y >out &&
156	test_must_be_empty out
157'
158
159test_expect_success POSIXPERM 'diff --no-index normalizes mode: chmod +x' '
160	chmod +x y &&
161	cat >expected <<-\EOF &&
162	diff --git a/x b/y
163	old mode 100644
164	new mode 100755
165	EOF
166	test_expect_code 1 git diff --no-index x y >actual &&
167	test_cmp expected actual
168'
169
170test_expect_success POSIXPERM 'diff --no-index normalizes: mode not like git mode' '
171	chmod 666 x &&
172	chmod 777 y &&
173	cat >expected <<-\EOF &&
174	diff --git a/x b/y
175	old mode 100644
176	new mode 100755
177	EOF
178	test_expect_code 1 git diff --no-index x y >actual &&
179	test_cmp expected actual
180'
181
182test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not like git mode (symlink)' '
183	ln -s y z &&
184	X_OID=$(git hash-object --stdin <x) &&
185	Z_OID=$(printf y | git hash-object --stdin) &&
186	cat >expected <<-EOF &&
187	diff --git a/x b/x
188	deleted file mode 100644
189	index $X_OID..$ZERO_OID
190	--- a/x
191	+++ /dev/null
192	@@ -1 +0,0 @@
193	-foo
194	diff --git a/z b/z
195	new file mode 120000
196	index $ZERO_OID..$Z_OID
197	--- /dev/null
198	+++ b/z
199	@@ -0,0 +1 @@
200	+y
201	\ No newline at end of file
202	EOF
203	test_expect_code 1 git -c core.abbrev=no diff --no-index x z >actual &&
204	test_cmp expected actual
205'
206
207test_done
208