Raw
1 #!/bin/sh
2
3 test_description='diff --no-index'
4
5 . ./test-lib.sh
6
7 test_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
19 test_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
24 test_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
29 test_expect_success 'git diff --no-index with -' '
30 cat >expect <<-\EOF &&
31 diff --git a/- b/-
32 new file mode 100644
33 --- /dev/null
34 +++ b/-
35 @@ -0,0 +1 @@
36 +frotz
37 EOF
38 (
39 cd a &&
40 echo frotz |
41 test_expect_code 1 git diff --no-index /dev/null - >../actual
42 ) &&
43 test_cmp expect actual
44 '
45
46 test_expect_success 'git diff --no-index relative path outside repo' '
47 (
48 cd repo &&
49 test_expect_code 0 git diff --no-index a ../non/git/a &&
50 test_expect_code 0 git diff --no-index ../non/git/a ../non/git/b
51 )
52 '
53
54 test_expect_success 'git diff --no-index with broken index' '
55 (
56 cd repo &&
57 echo broken >.git/index &&
58 git diff --no-index a ../non/git/a
59 )
60 '
61
62 test_expect_success 'git diff outside repo with broken index' '
63 (
64 cd repo &&
65 git diff ../non/git/a ../non/git/b
66 )
67 '
68
69 test_expect_success 'git diff --no-index executed outside repo gives correct error message' '
70 (
71 GIT_CEILING_DIRECTORIES=$TRASH_DIRECTORY/non &&
72 export GIT_CEILING_DIRECTORIES &&
73 cd non/git &&
74 test_must_fail git diff --no-index a 2>actual.err &&
75 test_grep "usage: git diff --no-index" actual.err
76 )
77 '
78
79 test_expect_success 'git diff --find-object outside repo fails gracefully' '
80 (
81 GIT_CEILING_DIRECTORIES=$TRASH_DIRECTORY/non &&
82 export GIT_CEILING_DIRECTORIES &&
83 cd non/git &&
84 test_must_fail git diff --find-object=abc123 2>err &&
85 test_grep "find-object requires a git repository" err
86 )
87 '
88
89 test_expect_success 'diff D F and diff F D' '
90 (
91 cd repo &&
92 echo in-repo >a &&
93 echo non-repo >../non/git/a &&
94 mkdir sub &&
95 echo sub-repo >sub/a &&
96
97 test_must_fail git diff --no-index sub/a ../non/git/a >expect &&
98 test_must_fail git diff --no-index sub/a ../non/git/ >actual &&
99 test_cmp expect actual &&
100
101 test_must_fail git diff --no-index a ../non/git/a >expect &&
102 test_must_fail git diff --no-index a ../non/git/ >actual &&
103 test_cmp expect actual &&
104
105 test_must_fail git diff --no-index ../non/git/a a >expect &&
106 test_must_fail git diff --no-index ../non/git a >actual &&
107 test_cmp expect actual
108 )
109 '
110
111 test_expect_success 'turning a file into a directory' '
112 (
113 cd non/git &&
114 mkdir d e e/sub &&
115 echo 1 >d/sub &&
116 echo 2 >e/sub/file &&
117 printf "D\td/sub\nA\te/sub/file\n" >expect &&
118 test_must_fail git diff --no-index --name-status d e >actual &&
119 test_cmp expect actual
120 )
121 '
122
123 test_expect_success 'diff from repo subdir shows real paths (explicit)' '
124 echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
125 test_expect_code 1 \
126 git -C repo/sub \
127 diff --no-index ../../non/git/a ../../non/git/b >actual &&
128 head -n 1 <actual >actual.head &&
129 test_cmp expect actual.head
130 '
131
132 test_expect_success 'diff from repo subdir shows real paths (implicit)' '
133 echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
134 test_expect_code 1 \
135 git -C repo/sub \
136 diff ../../non/git/a ../../non/git/b >actual &&
137 head -n 1 <actual >actual.head &&
138 test_cmp expect actual.head
139 '
140
141 test_expect_success 'diff --no-index from repo subdir respects config (explicit)' '
142 echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
143 test_config -C repo diff.noprefix true &&
144 test_expect_code 1 \
145 git -C repo/sub \
146 diff --no-index ../../non/git/a ../../non/git/b >actual &&
147 head -n 1 <actual >actual.head &&
148 test_cmp expect actual.head
149 '
150
151 test_expect_success 'diff --no-index from repo subdir respects config (implicit)' '
152 echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
153 test_config -C repo diff.noprefix true &&
154 test_expect_code 1 \
155 git -C repo/sub \
156 diff ../../non/git/a ../../non/git/b >actual &&
157 head -n 1 <actual >actual.head &&
158 test_cmp expect actual.head
159 '
160
161 test_expect_success 'diff --no-index from repo subdir with absolute paths' '
162 cat <<-EOF >expect &&
163 1 1 $(pwd)/non/git/{a => b}
164 EOF
165 test_expect_code 1 \
166 git -C repo/sub diff --numstat \
167 "$(pwd)/non/git/a" "$(pwd)/non/git/b" >actual &&
168 test_cmp expect actual
169 '
170
171 test_expect_success 'diff --no-index allows external diff' '
172 test_expect_code 1 \
173 env GIT_EXTERNAL_DIFF="echo external ;:" \
174 git diff --no-index non/git/a non/git/b >actual &&
175 echo external >expect &&
176 test_cmp expect actual
177 '
178
179 test_expect_success 'diff --no-index normalizes mode: no changes' '
180 echo foo >x &&
181 cp x y &&
182 git diff --no-index x y >out &&
183 test_must_be_empty out
184 '
185
186 test_expect_success POSIXPERM 'diff --no-index normalizes mode: chmod +x' '
187 chmod +x y &&
188 cat >expected <<-\EOF &&
189 diff --git a/x b/y
190 old mode 100644
191 new mode 100755
192 EOF
193 test_expect_code 1 git diff --no-index x y >actual &&
194 test_cmp expected actual
195 '
196
197 test_expect_success POSIXPERM 'diff --no-index normalizes: mode not like git mode' '
198 chmod 666 x &&
199 chmod 777 y &&
200 cat >expected <<-\EOF &&
201 diff --git a/x b/y
202 old mode 100644
203 new mode 100755
204 EOF
205 test_expect_code 1 git diff --no-index x y >actual &&
206 test_cmp expected actual
207 '
208
209 test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not like git mode (symlink)' '
210 ln -s y z &&
211 X_OID=$(git hash-object --stdin <x) &&
212 Z_OID=$(printf y | git hash-object --stdin) &&
213 cat >expected <<-EOF &&
214 diff --git a/x b/x
215 deleted file mode 100644
216 index $X_OID..$ZERO_OID
217 --- a/x
218 +++ /dev/null
219 @@ -1 +0,0 @@
220 -foo
221 diff --git a/z b/z
222 new file mode 120000
223 index $ZERO_OID..$Z_OID
224 --- /dev/null
225 +++ b/z
226 @@ -0,0 +1 @@
227 +y
228 \ No newline at end of file
229 EOF
230 test_expect_code 1 git -c core.abbrev=no diff --no-index x z >actual &&
231 test_cmp expected actual
232 '
233
234 test_expect_success POSIXPERM 'external diff with mode-only change' '
235 echo content >not-executable &&
236 echo content >executable &&
237 chmod +x executable &&
238 echo executable executable $(test_oid zero) 100755 \
239 not-executable $(test_oid zero) 100644 not-executable \
240 >expect &&
241 test_expect_code 1 git -c diff.external=echo diff \
242 --no-index executable not-executable >actual &&
243 test_cmp expect actual
244 '
245
246 test_expect_success "diff --no-index treats '-' as stdin" '
247 cat >expect <<-EOF &&
248 diff --git a/- b/a/1
249 index $ZERO_OID..$(git hash-object --stdin <a/1) 100644
250 --- a/-
251 +++ b/a/1
252 @@ -1 +1 @@
253 -x
254 +1
255 EOF
256
257 test_write_lines x | test_expect_code 1 \
258 git -c core.abbrev=no diff --no-index -- - a/1 >actual &&
259 test_cmp expect actual &&
260
261 test_write_lines 1 | git diff --no-index -- a/1 - >actual &&
262 test_must_be_empty actual
263 '
264
265 test_expect_success "diff --no-index -R treats '-' as stdin" '
266 cat >expect <<-EOF &&
267 diff --git b/a/1 a/-
268 index $(git hash-object --stdin <a/1)..$ZERO_OID 100644
269 --- b/a/1
270 +++ a/-
271 @@ -1 +1 @@
272 -1
273 +x
274 EOF
275
276 test_write_lines x | test_expect_code 1 \
277 git -c core.abbrev=no diff --no-index -R -- - a/1 >actual &&
278 test_cmp expect actual &&
279
280 test_write_lines 1 | git diff --no-index -R -- a/1 - >actual &&
281 test_must_be_empty actual
282 '
283
284 test_expect_success 'diff --no-index refuses to diff stdin and a directory' '
285 test_must_fail git diff --no-index -- - a </dev/null 2>err &&
286 grep "fatal: cannot compare stdin to a directory" err
287 '
288
289 test_expect_success PIPE 'diff --no-index refuses to diff a named pipe and a directory' '
290 test_when_finished "rm -f pipe" &&
291 mkfifo pipe &&
292 test_must_fail git diff --no-index -- pipe a 2>err &&
293 grep "fatal: cannot compare a named pipe to a directory" err
294 '
295
296 test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' '
297 test_when_finished "rm -f old new new-link" &&
298 mkfifo old &&
299 mkfifo new &&
300 ln -s new new-link &&
301 {
302 (test_write_lines a b c >old) &
303 } &&
304 test_when_finished "kill $! || :" &&
305 {
306 (test_write_lines a x c >new) &
307 } &&
308 test_when_finished "kill $! || :" &&
309
310 cat >expect <<-EOF &&
311 diff --git a/old b/new-link
312 --- a/old
313 +++ b/new-link
314 @@ -1,3 +1,3 @@
315 a
316 -b
317 +x
318 c
319 EOF
320
321 test_expect_code 1 git diff --no-index old new-link >actual &&
322 test_cmp expect actual
323 '
324
325 test_expect_success 'diff --no-index F F rejects pathspecs' '
326 test_must_fail git diff --no-index -- a/1 a/2 a 2>actual.err &&
327 test_grep "usage: git diff --no-index" actual.err
328 '
329
330 test_expect_success 'diff --no-index D F rejects pathspecs' '
331 test_must_fail git diff --no-index -- a a/2 a 2>actual.err &&
332 test_grep "usage: git diff --no-index" actual.err
333 '
334
335 test_expect_success 'diff --no-index F D rejects pathspecs' '
336 test_must_fail git diff --no-index -- a/1 b b 2>actual.err &&
337 test_grep "usage: git diff --no-index" actual.err
338 '
339
340 test_expect_success 'diff --no-index rejects absolute pathspec' '
341 test_must_fail git diff --no-index -- a b $(pwd)/a/1
342 '
343
344 test_expect_success 'diff --no-index with pathspec' '
345 test_expect_code 1 git diff --name-status --no-index a b 1 >actual &&
346 cat >expect <<-EOF &&
347 D a/1
348 EOF
349 test_cmp expect actual
350 '
351
352 test_expect_success 'diff --no-index first path ending in slash with pathspec' '
353 test_expect_code 1 git diff --name-status --no-index a/ b 1 >actual &&
354 cat >expect <<-EOF &&
355 D a/1
356 EOF
357 test_cmp expect actual
358 '
359
360 test_expect_success 'diff --no-index second path ending in slash with pathspec' '
361 test_expect_code 1 git diff --name-status --no-index a b/ 1 >actual &&
362 cat >expect <<-EOF &&
363 D a/1
364 EOF
365 test_cmp expect actual
366 '
367
368 test_expect_success 'diff --no-index with pathspec no matches' '
369 test_expect_code 0 git diff --name-status --no-index a b missing
370 '
371
372 test_expect_success 'diff --no-index with negative pathspec' '
373 test_expect_code 1 git diff --name-status --no-index a b ":!2" >actual &&
374 cat >expect <<-EOF &&
375 D a/1
376 EOF
377 test_cmp expect actual
378 '
379
380 test_expect_success 'setup nested' '
381 mkdir -p c/1/2 &&
382 mkdir -p d/1/2 &&
383 echo 1 >c/1/2/a &&
384 echo 2 >c/1/2/b
385 '
386
387 test_expect_success 'diff --no-index with pathspec nested negative pathspec' '
388 test_expect_code 0 git diff --no-index c d ":!1"
389 '
390
391 test_expect_success 'diff --no-index with pathspec nested pathspec' '
392 test_expect_code 1 git diff --name-status --no-index c d 1/2 >actual &&
393 cat >expect <<-EOF &&
394 D c/1/2/a
395 D c/1/2/b
396 EOF
397 test_cmp expect actual
398 '
399
400 test_expect_success 'diff --no-index with pathspec glob' '
401 test_expect_code 1 git diff --name-status --no-index c d ":(glob)**/a" >actual &&
402 cat >expect <<-EOF &&
403 D c/1/2/a
404 EOF
405 test_cmp expect actual
406 '
407
408 test_expect_success 'diff --no-index with pathspec glob and exclude' '
409 test_expect_code 1 git diff --name-status --no-index c d ":(glob,exclude)**/a" >actual &&
410 cat >expect <<-EOF &&
411 D c/1/2/b
412 EOF
413 test_cmp expect actual
414 '
415
416 test_done