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