difftool: fix bug when printing usage
[git.git] / t / t7800-difftool.sh
blob1c81f46cbf3b9a229c285afd13dfe627c95b7460
1 #!/bin/sh
3 # Copyright (c) 2009, 2010, 2012, 2013 David Aguilar
6 test_description='git-difftool
8 Testing basic diff tool invocation
11 . ./test-lib.sh
13 difftool_test_setup ()
15 test_config diff.tool test-tool &&
16 test_config difftool.test-tool.cmd 'cat "$LOCAL"' &&
17 test_config difftool.bogus-tool.cmd false
20 prompt_given ()
22 prompt="$1"
23 test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
26 test_expect_success 'basic usage requires no repo' '
27 lines=$(git difftool -h | grep ^usage: | wc -l) &&
28 test "$lines" -eq 1 &&
29 # create a ceiling directory to prevent Git from finding a repo
30 mkdir -p not/repo &&
31 ceiling="$PWD/not" &&
32 lines=$(cd not/repo &&
33 GIT_CEILING_DIRECTORIES="$ceiling" git difftool -h |
34 grep ^usage: | wc -l) &&
35 test "$lines" -eq 1 &&
36 rmdir -p not/repo
39 # Create a file on master and change it on branch
40 test_expect_success 'setup' '
41 echo master >file &&
42 git add file &&
43 git commit -m "added file" &&
45 git checkout -b branch master &&
46 echo branch >file &&
47 git commit -a -m "branch changed file" &&
48 git checkout master
51 # Configure a custom difftool.<tool>.cmd and use it
52 test_expect_success 'custom commands' '
53 difftool_test_setup &&
54 test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" &&
55 echo master >expect &&
56 git difftool --no-prompt branch >actual &&
57 test_cmp expect actual &&
59 test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" &&
60 echo branch >expect &&
61 git difftool --no-prompt branch >actual &&
62 test_cmp expect actual
65 test_expect_success 'custom tool commands override built-ins' '
66 test_config difftool.vimdiff.cmd "cat \"\$REMOTE\"" &&
67 echo master >expect &&
68 git difftool --tool vimdiff --no-prompt branch >actual &&
69 test_cmp expect actual
72 test_expect_success 'difftool ignores bad --tool values' '
73 : >expect &&
74 test_must_fail \
75 git difftool --no-prompt --tool=bad-tool branch >actual &&
76 test_cmp expect actual
79 test_expect_success 'difftool forwards arguments to diff' '
80 difftool_test_setup &&
81 >for-diff &&
82 git add for-diff &&
83 echo changes>for-diff &&
84 git add for-diff &&
85 : >expect &&
86 git difftool --cached --no-prompt -- for-diff >actual &&
87 test_cmp expect actual &&
88 git reset -- for-diff &&
89 rm for-diff
92 test_expect_success 'difftool ignores exit code' '
93 test_config difftool.error.cmd false &&
94 git difftool -y -t error branch
97 test_expect_success 'difftool forwards exit code with --trust-exit-code' '
98 test_config difftool.error.cmd false &&
99 test_must_fail git difftool -y --trust-exit-code -t error branch
102 test_expect_success 'difftool forwards exit code with --trust-exit-code for built-ins' '
103 test_config difftool.vimdiff.path false &&
104 test_must_fail git difftool -y --trust-exit-code -t vimdiff branch
107 test_expect_success 'difftool honors difftool.trustExitCode = true' '
108 test_config difftool.error.cmd false &&
109 test_config difftool.trustExitCode true &&
110 test_must_fail git difftool -y -t error branch
113 test_expect_success 'difftool honors difftool.trustExitCode = false' '
114 test_config difftool.error.cmd false &&
115 test_config difftool.trustExitCode false &&
116 git difftool -y -t error branch
119 test_expect_success 'difftool ignores exit code with --no-trust-exit-code' '
120 test_config difftool.error.cmd false &&
121 test_config difftool.trustExitCode true &&
122 git difftool -y --no-trust-exit-code -t error branch
125 test_expect_success 'difftool stops on error with --trust-exit-code' '
126 test_when_finished "rm -f for-diff .git/fail-right-file" &&
127 test_when_finished "git reset -- for-diff" &&
128 write_script .git/fail-right-file <<-\EOF &&
129 echo "$2"
130 exit 1
132 >for-diff &&
133 git add for-diff &&
134 echo file >expect &&
135 test_must_fail git difftool -y --trust-exit-code \
136 --extcmd .git/fail-right-file branch >actual &&
137 test_cmp expect actual
140 test_expect_success 'difftool honors exit status if command not found' '
141 test_config difftool.nonexistent.cmd i-dont-exist &&
142 test_config difftool.trustExitCode false &&
143 test_must_fail git difftool -y -t nonexistent branch
146 test_expect_success 'difftool honors --gui' '
147 difftool_test_setup &&
148 test_config merge.tool bogus-tool &&
149 test_config diff.tool bogus-tool &&
150 test_config diff.guitool test-tool &&
152 echo branch >expect &&
153 git difftool --no-prompt --gui branch >actual &&
154 test_cmp expect actual
157 test_expect_success 'difftool --gui last setting wins' '
158 difftool_test_setup &&
159 : >expect &&
160 git difftool --no-prompt --gui --no-gui >actual &&
161 test_cmp expect actual &&
163 test_config merge.tool bogus-tool &&
164 test_config diff.tool bogus-tool &&
165 test_config diff.guitool test-tool &&
166 echo branch >expect &&
167 git difftool --no-prompt --no-gui --gui branch >actual &&
168 test_cmp expect actual
171 test_expect_success 'difftool --gui works without configured diff.guitool' '
172 difftool_test_setup &&
173 echo branch >expect &&
174 git difftool --no-prompt --gui branch >actual &&
175 test_cmp expect actual
178 # Specify the diff tool using $GIT_DIFF_TOOL
179 test_expect_success 'GIT_DIFF_TOOL variable' '
180 difftool_test_setup &&
181 git config --unset diff.tool &&
182 echo branch >expect &&
183 GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
184 test_cmp expect actual
187 # Test the $GIT_*_TOOL variables and ensure
188 # that $GIT_DIFF_TOOL always wins unless --tool is specified
189 test_expect_success 'GIT_DIFF_TOOL overrides' '
190 difftool_test_setup &&
191 test_config diff.tool bogus-tool &&
192 test_config merge.tool bogus-tool &&
194 echo branch >expect &&
195 GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
196 test_cmp expect actual &&
198 test_config diff.tool bogus-tool &&
199 test_config merge.tool bogus-tool &&
200 GIT_DIFF_TOOL=bogus-tool \
201 git difftool --no-prompt --tool=test-tool branch >actual &&
202 test_cmp expect actual
205 # Test that we don't have to pass --no-prompt to difftool
206 # when $GIT_DIFFTOOL_NO_PROMPT is true
207 test_expect_success 'GIT_DIFFTOOL_NO_PROMPT variable' '
208 difftool_test_setup &&
209 echo branch >expect &&
210 GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual &&
211 test_cmp expect actual
214 # git-difftool supports the difftool.prompt variable.
215 # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
216 test_expect_success 'GIT_DIFFTOOL_PROMPT variable' '
217 difftool_test_setup &&
218 test_config difftool.prompt false &&
219 echo >input &&
220 GIT_DIFFTOOL_PROMPT=true git difftool branch <input >output &&
221 prompt=$(tail -1 <output) &&
222 prompt_given "$prompt"
225 # Test that we don't have to pass --no-prompt when difftool.prompt is false
226 test_expect_success 'difftool.prompt config variable is false' '
227 difftool_test_setup &&
228 test_config difftool.prompt false &&
229 echo branch >expect &&
230 git difftool branch >actual &&
231 test_cmp expect actual
234 # Test that we don't have to pass --no-prompt when mergetool.prompt is false
235 test_expect_success 'difftool merge.prompt = false' '
236 difftool_test_setup &&
237 test_might_fail git config --unset difftool.prompt &&
238 test_config mergetool.prompt false &&
239 echo branch >expect &&
240 git difftool branch >actual &&
241 test_cmp expect actual
244 # Test that the -y flag can override difftool.prompt = true
245 test_expect_success 'difftool.prompt can overridden with -y' '
246 difftool_test_setup &&
247 test_config difftool.prompt true &&
248 echo branch >expect &&
249 git difftool -y branch >actual &&
250 test_cmp expect actual
253 # Test that the --prompt flag can override difftool.prompt = false
254 test_expect_success 'difftool.prompt can overridden with --prompt' '
255 difftool_test_setup &&
256 test_config difftool.prompt false &&
257 echo >input &&
258 git difftool --prompt branch <input >output &&
259 prompt=$(tail -1 <output) &&
260 prompt_given "$prompt"
263 # Test that the last flag passed on the command-line wins
264 test_expect_success 'difftool last flag wins' '
265 difftool_test_setup &&
266 echo branch >expect &&
267 git difftool --prompt --no-prompt branch >actual &&
268 test_cmp expect actual &&
269 echo >input &&
270 git difftool --no-prompt --prompt branch <input >output &&
271 prompt=$(tail -1 <output) &&
272 prompt_given "$prompt"
275 # git-difftool falls back to git-mergetool config variables
276 # so test that behavior here
277 test_expect_success 'difftool + mergetool config variables' '
278 test_config merge.tool test-tool &&
279 test_config mergetool.test-tool.cmd "cat \$LOCAL" &&
280 echo branch >expect &&
281 git difftool --no-prompt branch >actual &&
282 test_cmp expect actual &&
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
291 test_expect_success 'difftool.<tool>.path' '
292 test_config difftool.tkdiff.path echo &&
293 git difftool --tool=tkdiff --no-prompt branch >output &&
294 lines=$(grep file output | wc -l) &&
295 test "$lines" -eq 1
298 test_expect_success 'difftool --extcmd=cat' '
299 echo branch >expect &&
300 echo master >>expect &&
301 git difftool --no-prompt --extcmd=cat branch >actual &&
302 test_cmp expect actual
305 test_expect_success 'difftool --extcmd cat' '
306 echo branch >expect &&
307 echo master >>expect &&
308 git difftool --no-prompt --extcmd=cat branch >actual &&
309 test_cmp expect actual
312 test_expect_success 'difftool -x cat' '
313 echo branch >expect &&
314 echo master >>expect &&
315 git difftool --no-prompt -x cat branch >actual &&
316 test_cmp expect actual
319 test_expect_success 'difftool --extcmd echo arg1' '
320 echo file >expect &&
321 git difftool --no-prompt \
322 --extcmd sh\ -c\ \"echo\ \$1\" branch >actual &&
323 test_cmp expect actual
326 test_expect_success 'difftool --extcmd cat arg1' '
327 echo master >expect &&
328 git difftool --no-prompt \
329 --extcmd sh\ -c\ \"cat\ \$1\" branch >actual &&
330 test_cmp expect actual
333 test_expect_success 'difftool --extcmd cat arg2' '
334 echo branch >expect &&
335 git difftool --no-prompt \
336 --extcmd sh\ -c\ \"cat\ \$2\" branch >actual &&
337 test_cmp expect actual
340 # Create a second file on master and a different version on branch
341 test_expect_success 'setup with 2 files different' '
342 echo m2 >file2 &&
343 git add file2 &&
344 git commit -m "added file2" &&
346 git checkout branch &&
347 echo br2 >file2 &&
348 git add file2 &&
349 git commit -a -m "branch changed file2" &&
350 git checkout master
353 test_expect_success 'say no to the first file' '
354 (echo n && echo) >input &&
355 git difftool -x cat branch <input >output &&
356 grep m2 output &&
357 grep br2 output &&
358 ! grep master output &&
359 ! grep branch output
362 test_expect_success 'say no to the second file' '
363 (echo && echo n) >input &&
364 git difftool -x cat branch <input >output &&
365 grep master output &&
366 grep branch output &&
367 ! grep m2 output &&
368 ! grep br2 output
371 test_expect_success 'ending prompt input with EOF' '
372 git difftool -x cat branch </dev/null >output &&
373 ! grep master output &&
374 ! grep branch output &&
375 ! grep m2 output &&
376 ! grep br2 output
379 test_expect_success 'difftool --tool-help' '
380 git difftool --tool-help >output &&
381 grep tool output
384 test_expect_success 'setup change in subdirectory' '
385 git checkout master &&
386 mkdir sub &&
387 echo master >sub/sub &&
388 git add sub/sub &&
389 git commit -m "added sub/sub" &&
390 echo test >>file &&
391 echo test >>sub/sub &&
392 git add file sub/sub &&
393 git commit -m "modified both"
396 run_dir_diff_test () {
397 test_expect_success "$1 --no-symlinks" "
398 symlinks=--no-symlinks &&
401 test_expect_success SYMLINKS "$1 --symlinks" "
402 symlinks=--symlinks &&
407 run_dir_diff_test 'difftool -d' '
408 git difftool -d $symlinks --extcmd ls branch >output &&
409 grep sub output &&
410 grep file output
413 run_dir_diff_test 'difftool --dir-diff' '
414 git difftool --dir-diff $symlinks --extcmd ls branch >output &&
415 grep sub output &&
416 grep file output
419 run_dir_diff_test 'difftool --dir-diff ignores --prompt' '
420 git difftool --dir-diff $symlinks --prompt --extcmd ls branch >output &&
421 grep sub output &&
422 grep file output
425 run_dir_diff_test 'difftool --dir-diff from subdirectory' '
427 cd sub &&
428 git difftool --dir-diff $symlinks --extcmd ls branch >output &&
429 grep sub output &&
430 grep file output
434 run_dir_diff_test 'difftool --dir-diff from subdirectory with GIT_DIR set' '
436 GIT_DIR=$(pwd)/.git &&
437 export GIT_DIR &&
438 GIT_WORK_TREE=$(pwd) &&
439 export GIT_WORK_TREE &&
440 cd sub &&
441 git difftool --dir-diff $symlinks --extcmd ls \
442 branch -- sub >output &&
443 grep sub output &&
444 ! grep file output
448 run_dir_diff_test 'difftool --dir-diff when worktree file is missing' '
449 test_when_finished git reset --hard &&
450 rm file2 &&
451 git difftool --dir-diff $symlinks --extcmd ls branch master >output &&
452 grep file2 output
455 run_dir_diff_test 'difftool --dir-diff with unmerged files' '
456 test_when_finished git reset --hard &&
457 test_config difftool.echo.cmd "echo ok" &&
458 git checkout -B conflict-a &&
459 git checkout -B conflict-b &&
460 git checkout conflict-a &&
461 echo a >>file &&
462 git add file &&
463 git commit -m conflict-a &&
464 git checkout conflict-b &&
465 echo b >>file &&
466 git add file &&
467 git commit -m conflict-b &&
468 git checkout master &&
469 git merge conflict-a &&
470 test_must_fail git merge conflict-b &&
471 cat >expect <<-EOF &&
474 git difftool --dir-diff $symlinks -t echo >actual &&
475 test_cmp expect actual
478 write_script .git/CHECK_SYMLINKS <<\EOF
479 for f in file file2 sub/sub
481 echo "$f"
482 ls -ld "$2/$f" | sed -e 's/.* -> //'
483 done >actual
486 test_expect_success SYMLINKS 'difftool --dir-diff --symlink without unstaged changes' '
487 cat >expect <<-EOF &&
488 file
489 $PWD/file
490 file2
491 $PWD/file2
492 sub/sub
493 $PWD/sub/sub
495 git difftool --dir-diff --symlink \
496 --extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
497 test_cmp actual expect
500 write_script modify-right-file <<\EOF
501 echo "new content" >"$2/file"
504 run_dir_diff_test 'difftool --dir-diff syncs worktree with unstaged change' '
505 test_when_finished git reset --hard &&
506 echo "orig content" >file &&
507 git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
508 echo "new content" >expect &&
509 test_cmp expect file
512 run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' '
513 test_when_finished git reset --hard &&
514 git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
515 echo "new content" >expect &&
516 test_cmp expect file
519 write_script modify-file <<\EOF
520 echo "new content" >file
523 test_expect_success 'difftool --no-symlinks does not overwrite working tree file ' '
524 echo "orig content" >file &&
525 git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-file" branch &&
526 echo "new content" >expect &&
527 test_cmp expect file
530 write_script modify-both-files <<\EOF
531 echo "wt content" >file &&
532 echo "tmp content" >"$2/file" &&
533 echo "$2" >tmpdir
536 test_expect_success 'difftool --no-symlinks detects conflict ' '
538 TMPDIR=$TRASH_DIRECTORY &&
539 export TMPDIR &&
540 echo "orig content" >file &&
541 test_must_fail git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-both-files" branch &&
542 echo "wt content" >expect &&
543 test_cmp expect file &&
544 echo "tmp content" >expect &&
545 test_cmp expect "$(cat tmpdir)/file"
549 test_expect_success 'difftool properly honors gitlink and core.worktree' '
550 git submodule add ./. submod/ule &&
551 test_config -C submod/ule diff.tool checktrees &&
552 test_config -C submod/ule difftool.checktrees.cmd '\''
553 test -d "$LOCAL" && test -d "$REMOTE" && echo good
554 '\'' &&
556 cd submod/ule &&
557 echo good >expect &&
558 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
559 test_cmp expect actual
563 test_expect_success SYMLINKS 'difftool --dir-diff symlinked directories' '
564 git init dirlinks &&
566 cd dirlinks &&
567 git config diff.tool checktrees &&
568 git config difftool.checktrees.cmd "echo good" &&
569 mkdir foo &&
570 : >foo/bar &&
571 git add foo/bar &&
572 test_commit symlink-one &&
573 ln -s foo link &&
574 git add link &&
575 test_commit symlink-two &&
576 echo good >expect &&
577 git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
578 test_cmp expect actual
582 test_done