commit-graph: when incompatible with graphs, indicate why
[git] / t / t7800-difftool.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2009, 2010, 2012, 2013 David Aguilar
4 #
5
6 test_description='git-difftool
7
8 Testing basic diff tool invocation
9 '
10
11 . ./test-lib.sh
12
13 difftool_test_setup ()
14 {
15         test_config diff.tool test-tool &&
16         test_config difftool.test-tool.cmd 'cat "$LOCAL"' &&
17         test_config difftool.bogus-tool.cmd false
18 }
19
20 prompt_given ()
21 {
22         prompt="$1"
23         test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
24 }
25
26 test_expect_success 'basic usage requires no repo' '
27         test_expect_code 129 git difftool -h >output &&
28         test_i18ngrep ^usage: output &&
29         # create a ceiling directory to prevent Git from finding a repo
30         mkdir -p not/repo &&
31         test_when_finished rm -r not &&
32         test_expect_code 129 \
33         env GIT_CEILING_DIRECTORIES="$(pwd)/not" \
34         git -C not/repo difftool -h >output &&
35         test_i18ngrep ^usage: output
36 '
37
38 # Create a file on master and change it on branch
39 test_expect_success 'setup' '
40         echo master >file &&
41         git add file &&
42         git commit -m "added file" &&
43
44         git checkout -b branch master &&
45         echo branch >file &&
46         git commit -a -m "branch changed file" &&
47         git checkout master
48 '
49
50 # Configure a custom difftool.<tool>.cmd and use it
51 test_expect_success 'custom commands' '
52         difftool_test_setup &&
53         test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" &&
54         echo master >expect &&
55         git difftool --no-prompt branch >actual &&
56         test_cmp expect actual &&
57
58         test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" &&
59         echo branch >expect &&
60         git difftool --no-prompt branch >actual &&
61         test_cmp expect actual
62 '
63
64 test_expect_success 'custom tool commands override built-ins' '
65         test_config difftool.vimdiff.cmd "cat \"\$REMOTE\"" &&
66         echo master >expect &&
67         git difftool --tool vimdiff --no-prompt branch >actual &&
68         test_cmp expect actual
69 '
70
71 test_expect_success 'difftool ignores bad --tool values' '
72         : >expect &&
73         test_must_fail \
74                 git difftool --no-prompt --tool=bad-tool branch >actual &&
75         test_cmp expect actual
76 '
77
78 test_expect_success 'difftool forwards arguments to diff' '
79         difftool_test_setup &&
80         >for-diff &&
81         git add for-diff &&
82         echo changes>for-diff &&
83         git add for-diff &&
84         : >expect &&
85         git difftool --cached --no-prompt -- for-diff >actual &&
86         test_cmp expect actual &&
87         git reset -- for-diff &&
88         rm for-diff
89 '
90
91 test_expect_success 'difftool ignores exit code' '
92         test_config difftool.error.cmd false &&
93         git difftool -y -t error branch
94 '
95
96 test_expect_success 'difftool forwards exit code with --trust-exit-code' '
97         test_config difftool.error.cmd false &&
98         test_must_fail git difftool -y --trust-exit-code -t error branch
99 '
100
101 test_expect_success 'difftool forwards exit code with --trust-exit-code for built-ins' '
102         test_config difftool.vimdiff.path false &&
103         test_must_fail git difftool -y --trust-exit-code -t vimdiff branch
104 '
105
106 test_expect_success 'difftool honors difftool.trustExitCode = true' '
107         test_config difftool.error.cmd false &&
108         test_config difftool.trustExitCode true &&
109         test_must_fail git difftool -y -t error branch
110 '
111
112 test_expect_success 'difftool honors difftool.trustExitCode = false' '
113         test_config difftool.error.cmd false &&
114         test_config difftool.trustExitCode false &&
115         git difftool -y -t error branch
116 '
117
118 test_expect_success 'difftool ignores exit code with --no-trust-exit-code' '
119         test_config difftool.error.cmd false &&
120         test_config difftool.trustExitCode true &&
121         git difftool -y --no-trust-exit-code -t error branch
122 '
123
124 test_expect_success 'difftool stops on error with --trust-exit-code' '
125         test_when_finished "rm -f for-diff .git/fail-right-file" &&
126         test_when_finished "git reset -- for-diff" &&
127         write_script .git/fail-right-file <<-\EOF &&
128         echo failed
129         exit 1
130         EOF
131         >for-diff &&
132         git add for-diff &&
133         test_must_fail git difftool -y --trust-exit-code \
134                 --extcmd .git/fail-right-file branch >actual &&
135         test_line_count = 1 actual
136 '
137
138 test_expect_success 'difftool honors exit status if command not found' '
139         test_config difftool.nonexistent.cmd i-dont-exist &&
140         test_config difftool.trustExitCode false &&
141         test_must_fail git difftool -y -t nonexistent branch
142 '
143
144 test_expect_success 'difftool honors --gui' '
145         difftool_test_setup &&
146         test_config merge.tool bogus-tool &&
147         test_config diff.tool bogus-tool &&
148         test_config diff.guitool test-tool &&
149
150         echo branch >expect &&
151         git difftool --no-prompt --gui branch >actual &&
152         test_cmp expect actual
153 '
154
155 test_expect_success 'difftool --gui last setting wins' '
156         difftool_test_setup &&
157         : >expect &&
158         git difftool --no-prompt --gui --no-gui >actual &&
159         test_cmp expect actual &&
160
161         test_config merge.tool bogus-tool &&
162         test_config diff.tool bogus-tool &&
163         test_config diff.guitool test-tool &&
164         echo branch >expect &&
165         git difftool --no-prompt --no-gui --gui branch >actual &&
166         test_cmp expect actual
167 '
168
169 test_expect_success 'difftool --gui works without configured diff.guitool' '
170         difftool_test_setup &&
171         echo branch >expect &&
172         git difftool --no-prompt --gui branch >actual &&
173         test_cmp expect actual
174 '
175
176 # Specify the diff tool using $GIT_DIFF_TOOL
177 test_expect_success 'GIT_DIFF_TOOL variable' '
178         difftool_test_setup &&
179         git config --unset diff.tool &&
180         echo branch >expect &&
181         GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
182         test_cmp expect actual
183 '
184
185 # Test the $GIT_*_TOOL variables and ensure
186 # that $GIT_DIFF_TOOL always wins unless --tool is specified
187 test_expect_success 'GIT_DIFF_TOOL overrides' '
188         difftool_test_setup &&
189         test_config diff.tool bogus-tool &&
190         test_config merge.tool bogus-tool &&
191
192         echo branch >expect &&
193         GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
194         test_cmp expect actual &&
195
196         test_config diff.tool bogus-tool &&
197         test_config merge.tool bogus-tool &&
198         GIT_DIFF_TOOL=bogus-tool \
199                 git difftool --no-prompt --tool=test-tool branch >actual &&
200         test_cmp expect actual
201 '
202
203 # Test that we don't have to pass --no-prompt to difftool
204 # when $GIT_DIFFTOOL_NO_PROMPT is true
205 test_expect_success 'GIT_DIFFTOOL_NO_PROMPT variable' '
206         difftool_test_setup &&
207         echo branch >expect &&
208         GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual &&
209         test_cmp expect actual
210 '
211
212 # git-difftool supports the difftool.prompt variable.
213 # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
214 test_expect_success 'GIT_DIFFTOOL_PROMPT variable' '
215         difftool_test_setup &&
216         test_config difftool.prompt false &&
217         echo >input &&
218         GIT_DIFFTOOL_PROMPT=true git difftool branch <input >output &&
219         prompt=$(tail -1 <output) &&
220         prompt_given "$prompt"
221 '
222
223 # Test that we don't have to pass --no-prompt when difftool.prompt is false
224 test_expect_success 'difftool.prompt config variable is false' '
225         difftool_test_setup &&
226         test_config difftool.prompt false &&
227         echo branch >expect &&
228         git difftool branch >actual &&
229         test_cmp expect actual
230 '
231
232 # Test that we don't have to pass --no-prompt when mergetool.prompt is false
233 test_expect_success 'difftool merge.prompt = false' '
234         difftool_test_setup &&
235         test_might_fail git config --unset difftool.prompt &&
236         test_config mergetool.prompt false &&
237         echo branch >expect &&
238         git difftool branch >actual &&
239         test_cmp expect actual
240 '
241
242 # Test that the -y flag can override difftool.prompt = true
243 test_expect_success 'difftool.prompt can overridden with -y' '
244         difftool_test_setup &&
245         test_config difftool.prompt true &&
246         echo branch >expect &&
247         git difftool -y branch >actual &&
248         test_cmp expect actual
249 '
250
251 # Test that the --prompt flag can override difftool.prompt = false
252 test_expect_success 'difftool.prompt can overridden with --prompt' '
253         difftool_test_setup &&
254         test_config difftool.prompt false &&
255         echo >input &&
256         git difftool --prompt branch <input >output &&
257         prompt=$(tail -1 <output) &&
258         prompt_given "$prompt"
259 '
260
261 # Test that the last flag passed on the command-line wins
262 test_expect_success 'difftool last flag wins' '
263         difftool_test_setup &&
264         echo branch >expect &&
265         git difftool --prompt --no-prompt branch >actual &&
266         test_cmp expect actual &&
267         echo >input &&
268         git difftool --no-prompt --prompt branch <input >output &&
269         prompt=$(tail -1 <output) &&
270         prompt_given "$prompt"
271 '
272
273 # git-difftool falls back to git-mergetool config variables
274 # so test that behavior here
275 test_expect_success 'difftool + mergetool config variables' '
276         test_config merge.tool test-tool &&
277         test_config mergetool.test-tool.cmd "cat \$LOCAL" &&
278         echo branch >expect &&
279         git difftool --no-prompt branch >actual &&
280         test_cmp expect actual &&
281         git difftool --gui --no-prompt branch >actual &&
282         test_cmp expect actual &&
283
284         # set merge.tool to something bogus, diff.tool to test-tool
285         test_config merge.tool bogus-tool &&
286         test_config diff.tool test-tool &&
287         git difftool --no-prompt branch >actual &&
288         test_cmp expect actual &&
289         git difftool --gui --no-prompt branch >actual &&
290         test_cmp expect actual &&
291
292         # set merge.tool, diff.tool to something bogus, merge.guitool to test-tool
293         test_config diff.tool bogus-tool &&
294         test_config merge.guitool test-tool &&
295         git difftool --gui --no-prompt branch >actual &&
296         test_cmp expect actual &&
297
298         # set merge.tool, diff.tool, merge.guitool to something bogus, diff.guitool to test-tool
299         test_config merge.guitool bogus-tool &&
300         test_config diff.guitool test-tool &&
301         git difftool --gui --no-prompt branch >actual &&
302         test_cmp expect actual
303 '
304
305 test_expect_success 'difftool.<tool>.path' '
306         test_config difftool.tkdiff.path echo &&
307         git difftool --tool=tkdiff --no-prompt branch >output &&
308         grep file output >grep-output &&
309         test_line_count = 1 grep-output
310 '
311
312 test_expect_success 'difftool --extcmd=cat' '
313         echo branch >expect &&
314         echo master >>expect &&
315         git difftool --no-prompt --extcmd=cat branch >actual &&
316         test_cmp expect actual
317 '
318
319 test_expect_success 'difftool --extcmd cat' '
320         echo branch >expect &&
321         echo master >>expect &&
322         git difftool --no-prompt --extcmd=cat branch >actual &&
323         test_cmp expect actual
324 '
325
326 test_expect_success 'difftool -x cat' '
327         echo branch >expect &&
328         echo master >>expect &&
329         git difftool --no-prompt -x cat branch >actual &&
330         test_cmp expect actual
331 '
332
333 test_expect_success 'difftool --extcmd echo arg1' '
334         echo file >expect &&
335         git difftool --no-prompt \
336                 --extcmd sh\ -c\ \"echo\ \$1\" branch >actual &&
337         test_cmp expect actual
338 '
339
340 test_expect_success 'difftool --extcmd cat arg1' '
341         echo master >expect &&
342         git difftool --no-prompt \
343                 --extcmd sh\ -c\ \"cat\ \$1\" branch >actual &&
344         test_cmp expect actual
345 '
346
347 test_expect_success 'difftool --extcmd cat arg2' '
348         echo branch >expect &&
349         git difftool --no-prompt \
350                 --extcmd sh\ -c\ \"cat\ \\\"\$2\\\"\" branch >actual &&
351         test_cmp expect actual
352 '
353
354 # Create a second file on master and a different version on branch
355 test_expect_success 'setup with 2 files different' '
356         echo m2 >file2 &&
357         git add file2 &&
358         git commit -m "added file2" &&
359
360         git checkout branch &&
361         echo br2 >file2 &&
362         git add file2 &&
363         git commit -a -m "branch changed file2" &&
364         git checkout master
365 '
366
367 test_expect_success 'say no to the first file' '
368         (echo n && echo) >input &&
369         git difftool -x cat branch <input >output &&
370         grep m2 output &&
371         grep br2 output &&
372         ! grep master output &&
373         ! grep branch output
374 '
375
376 test_expect_success 'say no to the second file' '
377         (echo && echo n) >input &&
378         git difftool -x cat branch <input >output &&
379         grep master output &&
380         grep branch output &&
381         ! grep m2 output &&
382         ! grep br2 output
383 '
384
385 test_expect_success 'ending prompt input with EOF' '
386         git difftool -x cat branch </dev/null >output &&
387         ! grep master output &&
388         ! grep branch output &&
389         ! grep m2 output &&
390         ! grep br2 output
391 '
392
393 test_expect_success 'difftool --tool-help' '
394         git difftool --tool-help >output &&
395         grep tool output
396 '
397
398 test_expect_success 'setup change in subdirectory' '
399         git checkout master &&
400         mkdir sub &&
401         echo master >sub/sub &&
402         git add sub/sub &&
403         git commit -m "added sub/sub" &&
404         git tag v1 &&
405         echo test >>file &&
406         echo test >>sub/sub &&
407         git add file sub/sub &&
408         git commit -m "modified both"
409 '
410
411 test_expect_success 'difftool -d with growing paths' '
412         a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
413         git init growing &&
414         (
415                 cd growing &&
416                 echo "test -f \"\$2/b\"" | write_script .git/test-for-b.sh &&
417                 one=$(printf 1 | git hash-object -w --stdin) &&
418                 two=$(printf 2 | git hash-object -w --stdin) &&
419                 git update-index --add \
420                         --cacheinfo 100644,$one,$a --cacheinfo 100644,$two,b &&
421                 tree1=$(git write-tree) &&
422                 git update-index --add \
423                         --cacheinfo 100644,$two,$a --cacheinfo 100644,$one,b &&
424                 tree2=$(git write-tree) &&
425                 git checkout -- $a &&
426                 git difftool -d --extcmd .git/test-for-b.sh $tree1 $tree2
427         )
428 '
429
430 run_dir_diff_test () {
431         test_expect_success "$1 --no-symlinks" "
432                 symlinks=--no-symlinks &&
433                 $2
434         "
435         test_expect_success SYMLINKS "$1 --symlinks" "
436                 symlinks=--symlinks &&
437                 $2
438         "
439 }
440
441 run_dir_diff_test 'difftool -d' '
442         git difftool -d $symlinks --extcmd ls branch >output &&
443         grep sub output &&
444         grep file output
445 '
446
447 run_dir_diff_test 'difftool --dir-diff' '
448         git difftool --dir-diff $symlinks --extcmd ls branch >output &&
449         grep sub output &&
450         grep file output
451 '
452
453 run_dir_diff_test 'difftool --dir-diff ignores --prompt' '
454         git difftool --dir-diff $symlinks --prompt --extcmd ls branch >output &&
455         grep sub output &&
456         grep file output
457 '
458
459 run_dir_diff_test 'difftool --dir-diff branch from subdirectory' '
460         (
461                 cd sub &&
462                 git difftool --dir-diff $symlinks --extcmd ls branch >output &&
463                 # "sub" must only exist in "right"
464                 # "file" and "file2" must be listed in both "left" and "right"
465                 grep sub output >sub-output &&
466                 test_line_count = 1 sub-output &&
467                 grep file"$" output >file-output &&
468                 test_line_count = 2 file-output &&
469                 grep file2 output >file2-output &&
470                 test_line_count = 2 file2-output
471         )
472 '
473
474 run_dir_diff_test 'difftool --dir-diff v1 from subdirectory' '
475         (
476                 cd sub &&
477                 git difftool --dir-diff $symlinks --extcmd ls v1 >output &&
478                 # "sub" and "file" exist in both v1 and HEAD.
479                 # "file2" is unchanged.
480                 grep sub output >sub-output &&
481                 test_line_count = 2 sub-output &&
482                 grep file output >file-output &&
483                 test_line_count = 2 file-output &&
484                 ! grep file2 output
485         )
486 '
487
488 run_dir_diff_test 'difftool --dir-diff branch from subdirectory w/ pathspec' '
489         (
490                 cd sub &&
491                 git difftool --dir-diff $symlinks --extcmd ls branch -- .>output &&
492                 # "sub" only exists in "right"
493                 # "file" and "file2" must not be listed
494                 grep sub output >sub-output &&
495                 test_line_count = 1 sub-output &&
496                 ! grep file output
497         )
498 '
499
500 run_dir_diff_test 'difftool --dir-diff v1 from subdirectory w/ pathspec' '
501         (
502                 cd sub &&
503                 git difftool --dir-diff $symlinks --extcmd ls v1 -- .>output &&
504                 # "sub" exists in v1 and HEAD
505                 # "file" is filtered out by the pathspec
506                 grep sub output >sub-output &&
507                 test_line_count = 2 sub-output &&
508                 ! grep file output
509         )
510 '
511
512 run_dir_diff_test 'difftool --dir-diff from subdirectory with GIT_DIR set' '
513         (
514                 GIT_DIR=$(pwd)/.git &&
515                 export GIT_DIR &&
516                 GIT_WORK_TREE=$(pwd) &&
517                 export GIT_WORK_TREE &&
518                 cd sub &&
519                 git difftool --dir-diff $symlinks --extcmd ls \
520                         branch -- sub >output &&
521                 grep sub output &&
522                 ! grep file output
523         )
524 '
525
526 run_dir_diff_test 'difftool --dir-diff when worktree file is missing' '
527         test_when_finished git reset --hard &&
528         rm file2 &&
529         git difftool --dir-diff $symlinks --extcmd ls branch master >output &&
530         grep file2 output
531 '
532
533 run_dir_diff_test 'difftool --dir-diff with unmerged files' '
534         test_when_finished git reset --hard &&
535         test_config difftool.echo.cmd "echo ok" &&
536         git checkout -B conflict-a &&
537         git checkout -B conflict-b &&
538         git checkout conflict-a &&
539         echo a >>file &&
540         git add file &&
541         git commit -m conflict-a &&
542         git checkout conflict-b &&
543         echo b >>file &&
544         git add file &&
545         git commit -m conflict-b &&
546         git checkout master &&
547         git merge conflict-a &&
548         test_must_fail git merge conflict-b &&
549         cat >expect <<-EOF &&
550                 ok
551         EOF
552         git difftool --dir-diff $symlinks -t echo >actual &&
553         test_cmp expect actual
554 '
555
556 write_script .git/CHECK_SYMLINKS <<\EOF
557 for f in file file2 sub/sub
558 do
559         echo "$f"
560         ls -ld "$2/$f" | sed -e 's/.* -> //'
561 done >actual
562 EOF
563
564 test_expect_success SYMLINKS 'difftool --dir-diff --symlinks without unstaged changes' '
565         cat >expect <<-EOF &&
566         file
567         $PWD/file
568         file2
569         $PWD/file2
570         sub/sub
571         $PWD/sub/sub
572         EOF
573         git difftool --dir-diff --symlinks \
574                 --extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
575         test_cmp expect actual
576 '
577
578 write_script modify-right-file <<\EOF
579 echo "new content" >"$2/file"
580 EOF
581
582 run_dir_diff_test 'difftool --dir-diff syncs worktree with unstaged change' '
583         test_when_finished git reset --hard &&
584         echo "orig content" >file &&
585         git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
586         echo "new content" >expect &&
587         test_cmp expect file
588 '
589
590 run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' '
591         test_when_finished git reset --hard &&
592         git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
593         echo "new content" >expect &&
594         test_cmp expect file
595 '
596
597 write_script modify-file <<\EOF
598 echo "new content" >file
599 EOF
600
601 test_expect_success 'difftool --no-symlinks does not overwrite working tree file ' '
602         echo "orig content" >file &&
603         git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-file" branch &&
604         echo "new content" >expect &&
605         test_cmp expect file
606 '
607
608 write_script modify-both-files <<\EOF
609 echo "wt content" >file &&
610 echo "tmp content" >"$2/file" &&
611 echo "$2" >tmpdir
612 EOF
613
614 test_expect_success 'difftool --no-symlinks detects conflict ' '
615         (
616                 TMPDIR=$TRASH_DIRECTORY &&
617                 export TMPDIR &&
618                 echo "orig content" >file &&
619                 test_must_fail git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-both-files" branch &&
620                 echo "wt content" >expect &&
621                 test_cmp expect file &&
622                 echo "tmp content" >expect &&
623                 test_cmp expect "$(cat tmpdir)/file"
624         )
625 '
626
627 test_expect_success 'difftool properly honors gitlink and core.worktree' '
628         test_when_finished rm -rf submod/ule &&
629         git submodule add ./. submod/ule &&
630         test_config -C submod/ule diff.tool checktrees &&
631         test_config -C submod/ule difftool.checktrees.cmd '\''
632                 test -d "$LOCAL" && test -d "$REMOTE" && echo good
633                 '\'' &&
634         (
635                 cd submod/ule &&
636                 echo good >expect &&
637                 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
638                 test_cmp expect actual &&
639                 rm -f expect actual
640         )
641 '
642
643 test_expect_success SYMLINKS 'difftool --dir-diff symlinked directories' '
644         test_when_finished git reset --hard &&
645         git init dirlinks &&
646         (
647                 cd dirlinks &&
648                 git config diff.tool checktrees &&
649                 git config difftool.checktrees.cmd "echo good" &&
650                 mkdir foo &&
651                 : >foo/bar &&
652                 git add foo/bar &&
653                 test_commit symlink-one &&
654                 ln -s foo link &&
655                 git add link &&
656                 test_commit symlink-two &&
657                 echo good >expect &&
658                 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
659                 test_cmp expect actual
660         )
661 '
662
663 test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
664         test_when_finished git reset --hard &&
665         touch b &&
666         ln -s b c &&
667         git add b c &&
668         test_tick &&
669         git commit -m initial &&
670         touch d &&
671         rm c &&
672         ln -s d c &&
673         cat >expect <<-EOF &&
674                 b
675                 c
676
677                 c
678         EOF
679         git difftool --symlinks --dir-diff --extcmd ls >output &&
680         grep -v ^/ output >actual &&
681         test_cmp expect actual &&
682
683         git difftool --no-symlinks --dir-diff --extcmd ls >output &&
684         grep -v ^/ output >actual &&
685         test_cmp expect actual &&
686
687         # The left side contains symlink "c" that points to "b"
688         test_config difftool.cat.cmd "cat \$LOCAL/c" &&
689         printf "%s\n" b >expect &&
690
691         git difftool --symlinks --dir-diff --tool cat >actual &&
692         test_cmp expect actual &&
693
694         git difftool --symlinks --no-symlinks --dir-diff --tool cat >actual &&
695         test_cmp expect actual &&
696
697         # The right side contains symlink "c" that points to "d"
698         test_config difftool.cat.cmd "cat \$REMOTE/c" &&
699         printf "%s\n" d >expect &&
700
701         git difftool --symlinks --dir-diff --tool cat >actual &&
702         test_cmp expect actual &&
703
704         git difftool --no-symlinks --dir-diff --tool cat >actual &&
705         test_cmp expect actual &&
706
707         # Deleted symlinks
708         rm -f c &&
709         cat >expect <<-EOF &&
710                 b
711                 c
712
713         EOF
714         git difftool --symlinks --dir-diff --extcmd ls >output &&
715         grep -v ^/ output >actual &&
716         test_cmp expect actual &&
717
718         git difftool --no-symlinks --dir-diff --extcmd ls >output &&
719         grep -v ^/ output >actual &&
720         test_cmp expect actual
721 '
722
723 test_expect_success 'add -N and difftool -d' '
724         test_when_finished git reset --hard &&
725
726         test_write_lines A B C >intent-to-add &&
727         git add -N intent-to-add &&
728         git difftool --dir-diff --extcmd ls
729 '
730
731 test_expect_success 'difftool --cached with unmerged files' '
732         test_when_finished git reset --hard &&
733
734         test_commit conflicting &&
735         test_commit conflict-a conflict.t a &&
736         git reset --hard conflicting &&
737         test_commit conflict-b conflict.t b &&
738         test_must_fail git merge conflict-a &&
739
740         git difftool --cached --no-prompt >output &&
741         test_must_be_empty output
742 '
743
744 test_expect_success 'outside worktree' '
745         echo 1 >1 &&
746         echo 2 >2 &&
747         test_expect_code 1 nongit git \
748                 -c diff.tool=echo -c difftool.echo.cmd="echo \$LOCAL \$REMOTE" \
749                 difftool --no-prompt --no-index ../1 ../2 >actual &&
750         echo "../1 ../2" >expect &&
751         test_cmp expect actual
752 '
753
754 test_expect_success 'difftool --gui, --tool and --extcmd are mutually exclusive' '
755         difftool_test_setup &&
756         test_must_fail git difftool --gui --tool=test-tool &&
757         test_must_fail git difftool --gui --extcmd=cat &&
758         test_must_fail git difftool --tool=test-tool --extcmd=cat &&
759         test_must_fail git difftool --gui --tool=test-tool --extcmd=cat
760 '
761
762 test_done