3 # Copyright (c) 2009, 2010, 2012, 2013 David Aguilar
6 test_description
='git-difftool
8 Testing basic diff tool invocation
11 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
12 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
14 TEST_PASSES_SANITIZE_LEAK
=true
17 difftool_test_setup
()
19 test_config
diff.tool test-tool
&&
20 test_config difftool.test-tool.cmd
'cat "$LOCAL"' &&
21 test_config difftool.bogus-tool.cmd false
27 test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
30 test_expect_success
'basic usage requires no repo' '
31 test_expect_code 129 git difftool -h >output &&
32 test_grep ^usage: output &&
33 # create a ceiling directory to prevent Git from finding a repo
35 test_when_finished rm -r not &&
36 test_expect_code 129 \
37 env GIT_CEILING_DIRECTORIES="$(pwd)/not" \
38 git -C not/repo difftool -h >output &&
39 test_grep ^usage: output
42 # Create a file on main and change it on branch
43 test_expect_success
'setup' '
46 git commit -m "added file" &&
48 git checkout -b branch main &&
50 git commit -a -m "branch changed file" &&
54 # Configure a custom difftool.<tool>.cmd and use it
55 test_expect_success
'custom commands' '
56 difftool_test_setup &&
57 test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" &&
59 git difftool --no-prompt branch >actual &&
60 test_cmp expect actual &&
62 test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" &&
63 echo branch >expect &&
64 git difftool --no-prompt branch >actual &&
65 test_cmp expect actual
68 test_expect_success
'custom tool commands override built-ins' '
69 test_config difftool.vimdiff.cmd "cat \"\$REMOTE\"" &&
71 git difftool --tool vimdiff --no-prompt branch >actual &&
72 test_cmp expect actual
75 test_expect_success
'difftool ignores bad --tool values' '
78 git difftool --no-prompt --tool=bad-tool branch >actual &&
79 test_cmp expect actual
82 test_expect_success
'difftool forwards arguments to diff' '
83 difftool_test_setup &&
86 echo changes>for-diff &&
89 git difftool --cached --no-prompt -- for-diff >actual &&
90 test_cmp expect actual &&
91 git reset -- for-diff &&
95 for opt
in '' '--dir-diff'
97 test_expect_success
"difftool ${opt:-without options} ignores exit code" '
98 test_config difftool.error.cmd false &&
99 git difftool ${opt} -y -t error branch
102 test_expect_success
"difftool ${opt:-without options} forwards exit code with --trust-exit-code" '
103 test_config difftool.error.cmd false &&
104 test_must_fail git difftool ${opt} -y --trust-exit-code -t error branch
107 test_expect_success
"difftool ${opt:-without options} forwards exit code with --trust-exit-code for built-ins" '
108 test_config difftool.vimdiff.path false &&
109 test_must_fail git difftool ${opt} -y --trust-exit-code -t vimdiff branch
112 test_expect_success
"difftool ${opt:-without options} honors difftool.trustExitCode = true" '
113 test_config difftool.error.cmd false &&
114 test_config difftool.trustExitCode true &&
115 test_must_fail git difftool ${opt} -y -t error branch
118 test_expect_success
"difftool ${opt:-without options} honors difftool.trustExitCode = false" '
119 test_config difftool.error.cmd false &&
120 test_config difftool.trustExitCode false &&
121 git difftool ${opt} -y -t error branch
124 test_expect_success
"difftool ${opt:-without options} ignores exit code with --no-trust-exit-code" '
125 test_config difftool.error.cmd false &&
126 test_config difftool.trustExitCode true &&
127 git difftool ${opt} -y --no-trust-exit-code -t error branch
130 test_expect_success
"difftool ${opt:-without options} stops on error with --trust-exit-code" '
131 test_when_finished "rm -f for-diff .git/fail-right-file" &&
132 test_when_finished "git reset -- for-diff" &&
133 write_script .git/fail-right-file <<-\EOF &&
139 test_must_fail git difftool ${opt} -y --trust-exit-code \
140 --extcmd .git/fail-right-file branch >actual &&
141 test_line_count = 1 actual
144 test_expect_success
"difftool ${opt:-without options} honors exit status if command not found" '
145 test_config difftool.nonexistent.cmd i-dont-exist &&
146 test_config difftool.trustExitCode false &&
147 if test "${opt}" = --dir-diff
153 test_expect_code ${expected_code} git difftool ${opt} -y -t nonexistent branch
157 test_expect_success
'difftool honors --gui' '
158 difftool_test_setup &&
159 test_config merge.tool bogus-tool &&
160 test_config diff.tool bogus-tool &&
161 test_config diff.guitool test-tool &&
163 echo branch >expect &&
164 git difftool --no-prompt --gui branch >actual &&
165 test_cmp expect actual
168 test_expect_success
'difftool with guiDefault auto selects gui tool when there is DISPLAY' '
169 difftool_test_setup &&
170 test_config merge.tool bogus-tool &&
171 test_config diff.tool bogus-tool &&
172 test_config diff.guitool test-tool &&
173 test_config difftool.guiDefault auto &&
174 DISPLAY=SOMETHING && export DISPLAY &&
176 echo branch >expect &&
177 git difftool --no-prompt branch >actual &&
178 test_cmp expect actual
180 test_expect_success
'difftool with guiDefault auto selects regular tool when no DISPLAY' '
181 difftool_test_setup &&
182 test_config diff.guitool bogus-tool &&
183 test_config diff.tool test-tool &&
184 test_config difftool.guiDefault Auto &&
185 DISPLAY= && export DISPLAY &&
187 echo branch >expect &&
188 git difftool --no-prompt branch >actual &&
189 test_cmp expect actual
192 test_expect_success
'difftool with guiDefault true selects gui tool' '
193 difftool_test_setup &&
194 test_config diff.tool bogus-tool &&
195 test_config diff.guitool test-tool &&
196 test_config difftool.guiDefault true &&
198 DISPLAY= && export DISPLAY &&
199 echo branch >expect &&
200 git difftool --no-prompt branch >actual &&
201 test_cmp expect actual &&
203 DISPLAY=Something && export DISPLAY &&
204 echo branch >expect &&
205 git difftool --no-prompt branch >actual &&
206 test_cmp expect actual
209 test_expect_success
'difftool --no-gui trumps config guiDefault' '
210 difftool_test_setup &&
211 test_config diff.guitool bogus-tool &&
212 test_config diff.tool test-tool &&
213 test_config difftool.guiDefault true &&
215 echo branch >expect &&
216 git difftool --no-prompt --no-gui branch >actual &&
217 test_cmp expect actual
220 test_expect_success
'difftool --gui last setting wins' '
221 difftool_test_setup &&
223 git difftool --no-prompt --gui --no-gui >actual &&
224 test_cmp expect actual &&
226 test_config merge.tool bogus-tool &&
227 test_config diff.tool bogus-tool &&
228 test_config diff.guitool test-tool &&
229 echo branch >expect &&
230 git difftool --no-prompt --no-gui --gui branch >actual &&
231 test_cmp expect actual
234 test_expect_success
'difftool --gui works without configured diff.guitool' '
235 difftool_test_setup &&
236 echo branch >expect &&
237 git difftool --no-prompt --gui branch >actual &&
238 test_cmp expect actual
241 # Specify the diff tool using $GIT_DIFF_TOOL
242 test_expect_success
'GIT_DIFF_TOOL variable' '
243 difftool_test_setup &&
244 git config --unset diff.tool &&
245 echo branch >expect &&
246 GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
247 test_cmp expect actual
250 # Test the $GIT_*_TOOL variables and ensure
251 # that $GIT_DIFF_TOOL always wins unless --tool is specified
252 test_expect_success
'GIT_DIFF_TOOL overrides' '
253 difftool_test_setup &&
254 test_config diff.tool bogus-tool &&
255 test_config merge.tool bogus-tool &&
257 echo branch >expect &&
258 GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
259 test_cmp expect actual &&
261 test_config diff.tool bogus-tool &&
262 test_config merge.tool bogus-tool &&
263 GIT_DIFF_TOOL=bogus-tool \
264 git difftool --no-prompt --tool=test-tool branch >actual &&
265 test_cmp expect actual
268 # Test that we don't have to pass --no-prompt to difftool
269 # when $GIT_DIFFTOOL_NO_PROMPT is true
270 test_expect_success
'GIT_DIFFTOOL_NO_PROMPT variable' '
271 difftool_test_setup &&
272 echo branch >expect &&
273 GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual &&
274 test_cmp expect actual
277 # git-difftool supports the difftool.prompt variable.
278 # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
279 test_expect_success
'GIT_DIFFTOOL_PROMPT variable' '
280 difftool_test_setup &&
281 test_config difftool.prompt false &&
283 GIT_DIFFTOOL_PROMPT=true git difftool branch <input >output &&
284 prompt=$(tail -1 <output) &&
285 prompt_given "$prompt"
288 # Test that we don't have to pass --no-prompt when difftool.prompt is false
289 test_expect_success
'difftool.prompt config variable is false' '
290 difftool_test_setup &&
291 test_config difftool.prompt false &&
292 echo branch >expect &&
293 git difftool branch >actual &&
294 test_cmp expect actual
297 # Test that we don't have to pass --no-prompt when mergetool.prompt is false
298 test_expect_success
'difftool merge.prompt = false' '
299 difftool_test_setup &&
300 test_might_fail git config --unset difftool.prompt &&
301 test_config mergetool.prompt false &&
302 echo branch >expect &&
303 git difftool branch >actual &&
304 test_cmp expect actual
307 # Test that the -y flag can override difftool.prompt = true
308 test_expect_success
'difftool.prompt can overridden with -y' '
309 difftool_test_setup &&
310 test_config difftool.prompt true &&
311 echo branch >expect &&
312 git difftool -y branch >actual &&
313 test_cmp expect actual
316 # Test that the --prompt flag can override difftool.prompt = false
317 test_expect_success
'difftool.prompt can overridden with --prompt' '
318 difftool_test_setup &&
319 test_config difftool.prompt false &&
321 git difftool --prompt branch <input >output &&
322 prompt=$(tail -1 <output) &&
323 prompt_given "$prompt"
326 # Test that the last flag passed on the command-line wins
327 test_expect_success
'difftool last flag wins' '
328 difftool_test_setup &&
329 echo branch >expect &&
330 git difftool --prompt --no-prompt branch >actual &&
331 test_cmp expect actual &&
333 git difftool --no-prompt --prompt branch <input >output &&
334 prompt=$(tail -1 <output) &&
335 prompt_given "$prompt"
338 # git-difftool falls back to git-mergetool config variables
339 # so test that behavior here
340 test_expect_success
'difftool + mergetool config variables' '
341 test_config merge.tool test-tool &&
342 test_config mergetool.test-tool.cmd "cat \$LOCAL" &&
343 echo branch >expect &&
344 git difftool --no-prompt branch >actual &&
345 test_cmp expect actual &&
346 git difftool --gui --no-prompt branch >actual &&
347 test_cmp expect actual &&
349 # set merge.tool to something bogus, diff.tool to test-tool
350 test_config merge.tool bogus-tool &&
351 test_config diff.tool test-tool &&
352 git difftool --no-prompt branch >actual &&
353 test_cmp expect actual &&
354 git difftool --gui --no-prompt branch >actual &&
355 test_cmp expect actual &&
357 # set merge.tool, diff.tool to something bogus, merge.guitool to test-tool
358 test_config diff.tool bogus-tool &&
359 test_config merge.guitool test-tool &&
360 git difftool --gui --no-prompt branch >actual &&
361 test_cmp expect actual &&
363 # set merge.tool, diff.tool, merge.guitool to something bogus, diff.guitool to test-tool
364 test_config merge.guitool bogus-tool &&
365 test_config diff.guitool test-tool &&
366 git difftool --gui --no-prompt branch >actual &&
367 test_cmp expect actual
370 test_expect_success
'difftool.<tool>.path' '
371 test_config difftool.tkdiff.path echo &&
372 git difftool --tool=tkdiff --no-prompt branch >output &&
373 grep file output >grep-output &&
374 test_line_count = 1 grep-output
377 test_expect_success
'difftool --extcmd=cat' '
378 echo branch >expect &&
379 echo main >>expect &&
380 git difftool --no-prompt --extcmd=cat branch >actual &&
381 test_cmp expect actual
384 test_expect_success
'difftool --extcmd cat' '
385 echo branch >expect &&
386 echo main >>expect &&
387 git difftool --no-prompt --extcmd=cat branch >actual &&
388 test_cmp expect actual
391 test_expect_success
'difftool -x cat' '
392 echo branch >expect &&
393 echo main >>expect &&
394 git difftool --no-prompt -x cat branch >actual &&
395 test_cmp expect actual
398 test_expect_success
'difftool --extcmd echo arg1' '
400 git difftool --no-prompt \
401 --extcmd sh\ -c\ \"echo\ \$1\" branch >actual &&
402 test_cmp expect actual
405 test_expect_success
'difftool --extcmd cat arg1' '
407 git difftool --no-prompt \
408 --extcmd sh\ -c\ \"cat\ \$1\" branch >actual &&
409 test_cmp expect actual
412 test_expect_success
'difftool --extcmd cat arg2' '
413 echo branch >expect &&
414 git difftool --no-prompt \
415 --extcmd sh\ -c\ \"cat\ \\\"\$2\\\"\" branch >actual &&
416 test_cmp expect actual
419 # Create a second file on main and a different version on branch
420 test_expect_success
'setup with 2 files different' '
423 git commit -m "added file2" &&
425 git checkout branch &&
428 git commit -a -m "branch changed file2" &&
432 test_expect_success
'say no to the first file' '
433 (echo n && echo) >input &&
434 git difftool -x cat branch <input >output &&
437 ! grep main output &&
441 test_expect_success
'say no to the second file' '
442 (echo && echo n) >input &&
443 git difftool -x cat branch <input >output &&
445 grep branch output &&
450 test_expect_success
'ending prompt input with EOF' '
451 git difftool -x cat branch </dev/null >output &&
452 ! grep main output &&
453 ! grep branch output &&
458 test_expect_success
'difftool --tool-help' '
459 git difftool --tool-help >output &&
463 test_expect_success
'setup change in subdirectory' '
466 echo main >sub/sub &&
468 git commit -m "added sub/sub" &&
471 echo test >>sub/sub &&
472 git add file sub/sub &&
473 git commit -m "modified both"
476 test_expect_success
'difftool -d with growing paths' '
477 a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
481 echo "test -f \"\$2/b\"" | write_script .git/test-for-b.sh &&
482 one=$(printf 1 | git hash-object -w --stdin) &&
483 two=$(printf 2 | git hash-object -w --stdin) &&
484 git update-index --add \
485 --cacheinfo 100644,$one,$a --cacheinfo 100644,$two,b &&
486 tree1=$(git write-tree) &&
487 git update-index --add \
488 --cacheinfo 100644,$two,$a --cacheinfo 100644,$one,b &&
489 tree2=$(git write-tree) &&
490 git checkout -- $a &&
491 git difftool -d --extcmd .git/test-for-b.sh $tree1 $tree2
495 run_dir_diff_test
() {
496 test_expect_success
"$1 --no-symlinks" "
497 symlinks=--no-symlinks &&
500 test_expect_success SYMLINKS
"$1 --symlinks" "
501 symlinks=--symlinks &&
506 run_dir_diff_test
'difftool -d' '
507 git difftool -d $symlinks --extcmd ls branch >output &&
508 grep "^sub$" output &&
512 run_dir_diff_test
'difftool --dir-diff' '
513 git difftool --dir-diff $symlinks --extcmd ls branch >output &&
514 grep "^sub$" output &&
518 run_dir_diff_test
'difftool --dir-diff avoids repeated slashes in TMPDIR' '
519 TMPDIR="${TMPDIR:-/tmp}////" \
520 git difftool --dir-diff $symlinks --extcmd echo branch >output &&
521 grep -v // output >actual &&
522 test_line_count = 1 actual
525 run_dir_diff_test
'difftool --dir-diff ignores --prompt' '
526 git difftool --dir-diff $symlinks --prompt --extcmd ls branch >output &&
527 grep "^sub$" output &&
531 run_dir_diff_test
'difftool --dir-diff branch from subdirectory' '
534 git difftool --dir-diff $symlinks --extcmd ls branch >output &&
535 # "sub" must only exist in "right"
536 # "file" and "file2" must be listed in both "left" and "right"
537 grep "^sub$" output >sub-output &&
538 test_line_count = 1 sub-output &&
539 grep "^file$" output >file-output &&
540 test_line_count = 2 file-output &&
541 grep "^file2$" output >file2-output &&
542 test_line_count = 2 file2-output
546 run_dir_diff_test
'difftool --dir-diff v1 from subdirectory' '
549 git difftool --dir-diff $symlinks --extcmd ls v1 >output &&
550 # "sub" and "file" exist in both v1 and HEAD.
551 # "file2" is unchanged.
552 grep "^sub$" output >sub-output &&
553 test_line_count = 2 sub-output &&
554 grep "^file$" output >file-output &&
555 test_line_count = 2 file-output &&
556 ! grep "^file2$" output
560 run_dir_diff_test
'difftool --dir-diff branch from subdirectory w/ pathspec' '
563 git difftool --dir-diff $symlinks --extcmd ls branch -- .>output &&
564 # "sub" only exists in "right"
565 # "file" and "file2" must not be listed
566 grep "^sub$" output >sub-output &&
567 test_line_count = 1 sub-output &&
568 ! grep "^file$" output
572 run_dir_diff_test
'difftool --dir-diff v1 from subdirectory w/ pathspec' '
575 git difftool --dir-diff $symlinks --extcmd ls v1 -- .>output &&
576 # "sub" exists in v1 and HEAD
577 # "file" is filtered out by the pathspec
578 grep "^sub$" output >sub-output &&
579 test_line_count = 2 sub-output &&
580 ! grep "^file$" output
584 run_dir_diff_test
'difftool --dir-diff from subdirectory with GIT_DIR set' '
586 GIT_DIR=$(pwd)/.git &&
588 GIT_WORK_TREE=$(pwd) &&
589 export GIT_WORK_TREE &&
591 git difftool --dir-diff $symlinks --extcmd ls \
592 branch -- sub >output &&
593 grep "^sub$" output &&
594 ! grep "^file$" output
598 run_dir_diff_test
'difftool --dir-diff when worktree file is missing' '
599 test_when_finished git reset --hard &&
601 git difftool --dir-diff $symlinks --extcmd ls branch main >output &&
602 grep "^file2$" output
605 run_dir_diff_test
'difftool --dir-diff with unmerged files' '
606 test_when_finished git reset --hard &&
607 test_config difftool.echo.cmd "echo ok" &&
608 git checkout -B conflict-a &&
609 git checkout -B conflict-b &&
610 git checkout conflict-a &&
613 git commit -m conflict-a &&
614 git checkout conflict-b &&
617 git commit -m conflict-b &&
619 git merge conflict-a &&
620 test_must_fail git merge conflict-b &&
621 cat >expect <<-EOF &&
624 git difftool --dir-diff $symlinks -t echo >actual &&
625 test_cmp expect actual
628 write_script .git
/CHECK_SYMLINKS
<<\EOF
629 for f
in file file2 sub
/sub
632 ls -ld "$2/$f" |
sed -e 's/.* -> //'
636 test_expect_success SYMLINKS
'difftool --dir-diff --symlinks without unstaged changes' '
637 cat >expect <<-EOF &&
645 git difftool --dir-diff --symlinks \
646 --extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
647 test_cmp expect actual
650 write_script modify-right-file
<<\EOF
651 echo "new content" >"$2/file"
654 run_dir_diff_test
'difftool --dir-diff syncs worktree with unstaged change' '
655 test_when_finished git reset --hard &&
656 echo "orig content" >file &&
657 git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
658 echo "new content" >expect &&
662 run_dir_diff_test
'difftool --dir-diff syncs worktree without unstaged change' '
663 test_when_finished git reset --hard &&
664 git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
665 echo "new content" >expect &&
669 write_script modify-file
<<\EOF
670 echo "new content" >file
673 test_expect_success
'difftool --no-symlinks does not overwrite working tree file ' '
674 echo "orig content" >file &&
675 git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-file" branch &&
676 echo "new content" >expect &&
680 write_script modify-both-files
<<\EOF
681 echo "wt content" >file &&
682 echo "tmp content" >"$2/file" &&
686 test_expect_success
'difftool --no-symlinks detects conflict ' '
688 TMPDIR=$TRASH_DIRECTORY &&
690 echo "orig content" >file &&
691 test_must_fail git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-both-files" branch &&
692 echo "wt content" >expect &&
693 test_cmp expect file &&
694 echo "tmp content" >expect &&
695 test_cmp expect "$(cat tmpdir)/file"
699 test_expect_success
'difftool properly honors gitlink and core.worktree' '
700 test_when_finished rm -rf submod/ule &&
701 test_config_global protocol.file.allow always &&
702 git submodule add ./. submod/ule &&
703 test_config -C submod/ule diff.tool checktrees &&
704 test_config -C submod/ule difftool.checktrees.cmd '\''
705 test -d "$LOCAL" && test -d "$REMOTE" && echo good
710 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
711 test_cmp expect actual &&
716 test_expect_success SYMLINKS
'difftool --dir-diff symlinked directories' '
717 test_when_finished git reset --hard &&
721 git config diff.tool checktrees &&
722 git config difftool.checktrees.cmd "echo good" &&
726 test_commit symlink-one &&
729 test_commit symlink-two &&
731 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
732 test_cmp expect actual
736 test_expect_success SYMLINKS
'difftool --dir-diff handles modified symlinks' '
737 test_when_finished git reset --hard &&
742 git commit -m initial &&
746 cat >expect <<-EOF &&
751 git difftool --symlinks --dir-diff --extcmd ls >output &&
752 grep -v ^/ output >actual &&
753 test_cmp expect actual &&
755 git difftool --no-symlinks --dir-diff --extcmd ls >output &&
756 grep -v ^/ output >actual &&
757 test_cmp expect actual &&
759 # The left side contains symlink "c" that points to "b"
760 test_config difftool.cat.cmd "cat \$LOCAL/c" &&
761 printf "%s\n" b >expect &&
763 git difftool --symlinks --dir-diff --tool cat >actual &&
764 test_cmp expect actual &&
766 git difftool --symlinks --no-symlinks --dir-diff --tool cat >actual &&
767 test_cmp expect actual &&
769 # The right side contains symlink "c" that points to "d"
770 test_config difftool.cat.cmd "cat \$REMOTE/c" &&
771 printf "%s\n" d >expect &&
773 git difftool --symlinks --dir-diff --tool cat >actual &&
774 test_cmp expect actual &&
776 git difftool --no-symlinks --dir-diff --tool cat >actual &&
777 test_cmp expect actual &&
781 cat >expect <<-EOF &&
785 git difftool --symlinks --dir-diff --extcmd ls >output &&
786 grep -v ^/ output >actual &&
787 test_cmp expect actual &&
789 git difftool --no-symlinks --dir-diff --extcmd ls >output &&
790 grep -v ^/ output >actual &&
791 test_cmp expect actual
794 test_expect_success SYMLINKS
'difftool --dir-diff writes symlinks as raw text' '
795 # Start out on a branch called "branch-init".
796 git init -b branch-init symlink-files &&
799 # This test ensures that symlinks are written as raw text.
800 # The "cat" tools output link and file contents.
801 git config difftool.cat-left-link.cmd "cat \"\$LOCAL/link\"" &&
802 git config difftool.cat-left-a.cmd "cat \"\$LOCAL/file-a\"" &&
803 git config difftool.cat-right-link.cmd "cat \"\$REMOTE/link\"" &&
804 git config difftool.cat-right-b.cmd "cat \"\$REMOTE/file-b\"" &&
806 # Record the empty initial state so that we can come back here
807 # later and not have to consider the any cases where difftool
808 # will create symlinks back into the worktree.
810 git commit --allow-empty -m init &&
812 # Create a file called "file-a" with a symlink pointing to it.
813 git switch -c branch-a &&
816 git add file-a link &&
818 git commit -m link-to-file-a &&
820 # Create a file called "file-b" and point the symlink to it.
821 git switch -c branch-b &&
825 git add file-b link &&
828 git commit -m link-to-file-b &&
830 # Checkout the initial branch so that the --symlinks behavior is
831 # not activated. The two directories should be completely
832 # independent with no symlinks pointing back here.
833 git switch branch-init &&
835 # The left link must be "file-a" and "file-a" must contain "a".
836 echo file-a >expect &&
837 git difftool --symlinks --dir-diff --tool cat-left-link \
838 branch-a branch-b >actual &&
839 test_cmp expect actual &&
842 git difftool --symlinks --dir-diff --tool cat-left-a \
843 branch-a branch-b >actual &&
844 test_cmp expect actual &&
846 # The right link must be "file-b" and "file-b" must contain "b".
847 echo file-b >expect &&
848 git difftool --symlinks --dir-diff --tool cat-right-link \
849 branch-a branch-b >actual &&
850 test_cmp expect actual &&
853 git difftool --symlinks --dir-diff --tool cat-right-b \
854 branch-a branch-b >actual &&
855 test_cmp expect actual
859 test_expect_success
'add -N and difftool -d' '
860 test_when_finished git reset --hard &&
862 test_write_lines A B C >intent-to-add &&
863 git add -N intent-to-add &&
864 git difftool --dir-diff --extcmd ls
867 test_expect_success
'difftool --cached with unmerged files' '
868 test_when_finished git reset --hard &&
870 test_commit conflicting &&
871 test_commit conflict-a conflict.t a &&
872 git reset --hard conflicting &&
873 test_commit conflict-b conflict.t b &&
874 test_must_fail git merge conflict-a &&
876 git difftool --cached --no-prompt >output &&
877 test_must_be_empty output
880 test_expect_success
'outside worktree' '
883 test_expect_code 1 nongit git \
884 -c diff.tool=echo -c difftool.echo.cmd="echo \$LOCAL \$REMOTE" \
885 difftool --no-prompt --no-index ../1 ../2 >actual &&
886 echo "../1 ../2" >expect &&
887 test_cmp expect actual
890 test_expect_success
'difftool --gui, --tool and --extcmd are mutually exclusive' '
891 difftool_test_setup &&
892 test_must_fail git difftool --gui --tool=test-tool &&
893 test_must_fail git difftool --gui --extcmd=cat &&
894 test_must_fail git difftool --tool=test-tool --extcmd=cat &&
895 test_must_fail git difftool --gui --tool=test-tool --extcmd=cat
898 test_expect_success
'difftool --rotate-to' '
899 difftool_test_setup &&
900 test_when_finished git reset --hard &&
905 git commit -a -m "124" &&
906 git difftool --no-prompt --extcmd=cat --rotate-to="2" HEAD^ >output &&
907 cat >expect <<-\EOF &&
912 test_cmp output expect
915 test_expect_success
'difftool --skip-to' '
916 difftool_test_setup &&
917 test_when_finished git reset --hard &&
918 git difftool --no-prompt --extcmd=cat --skip-to="2" HEAD^ >output &&
919 cat >expect <<-\EOF &&
923 test_cmp output expect
926 test_expect_success
'difftool --rotate/skip-to error condition' '
927 test_must_fail git difftool --no-prompt --extcmd=cat --rotate-to="3" HEAD^ &&
928 test_must_fail git difftool --no-prompt --extcmd=cat --skip-to="3" HEAD^