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