The eighteenth batch
[git.git] / t / t4020-diff-external.sh
blob3baa52a9bf653da9e45df720435cb23d0713e1db
1 #!/bin/sh
3 test_description='external diff interface test'
5 TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
8 test_expect_success setup '
10 test_tick &&
11 echo initial >file &&
12 git add file &&
13 git commit -m initial &&
15 test_tick &&
16 echo second >file &&
17 before=$(git hash-object file) &&
18 before=$(git rev-parse --short $before) &&
19 git add file &&
20 git commit -m second &&
22 test_tick &&
23 echo third >file
26 test_expect_success 'GIT_EXTERNAL_DIFF environment' '
27 cat >expect <<-EOF &&
28 file $(git rev-parse --verify HEAD:file) 100644 file $(test_oid zero) 100644
29 EOF
30 GIT_EXTERNAL_DIFF=echo git diff >out &&
31 cut -d" " -f1,3- <out >actual &&
32 test_cmp expect actual
36 test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' '
37 GIT_EXTERNAL_DIFF=echo git log -p -1 HEAD >out &&
38 grep "^diff --git a/file b/file" out
42 test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
43 GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff >out &&
44 grep "^diff --git a/file b/file" out
48 test_expect_success SYMLINKS 'typechange diff' '
49 rm -f file &&
50 ln -s elif file &&
52 cat >expect <<-EOF &&
53 file $(git rev-parse --verify HEAD:file) 100644 $(test_oid zero) 120000
54 EOF
55 GIT_EXTERNAL_DIFF=echo git diff >out &&
56 cut -d" " -f1,3-4,6- <out >actual &&
57 test_cmp expect actual &&
59 GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff >actual &&
60 git diff >expect &&
61 test_cmp expect actual
64 test_expect_success 'diff.external' '
65 git reset --hard &&
66 echo third >file &&
67 test_config diff.external echo &&
69 cat >expect <<-EOF &&
70 file $(git rev-parse --verify HEAD:file) 100644 $(test_oid zero) 100644
71 EOF
72 git diff >out &&
73 cut -d" " -f1,3-4,6- <out >actual &&
74 test_cmp expect actual
77 test_expect_success 'diff.external should apply only to diff' '
78 test_config diff.external echo &&
79 git log -p -1 HEAD >out &&
80 grep "^diff --git a/file b/file" out
83 test_expect_success 'diff.external and --no-ext-diff' '
84 test_config diff.external echo &&
85 git diff --no-ext-diff >out &&
86 grep "^diff --git a/file b/file" out
89 test_expect_success 'diff attribute' '
90 git reset --hard &&
91 echo third >file &&
93 git config diff.parrot.command echo &&
95 echo >.gitattributes "file diff=parrot" &&
97 cat >expect <<-EOF &&
98 file $(git rev-parse --verify HEAD:file) 100644 $(test_oid zero) 100644
99 EOF
100 git diff >out &&
101 cut -d" " -f1,3-4,6- <out >actual &&
102 test_cmp expect actual
105 test_expect_success !SANITIZE_LEAK 'diff attribute should apply only to diff' '
106 git log -p -1 HEAD >out &&
107 grep "^diff --git a/file b/file" out
111 test_expect_success 'diff attribute and --no-ext-diff' '
112 git diff --no-ext-diff >out &&
113 grep "^diff --git a/file b/file" out
117 test_expect_success 'diff attribute' '
119 git config --unset diff.parrot.command &&
120 git config diff.color.command echo &&
122 echo >.gitattributes "file diff=color" &&
124 cat >expect <<-EOF &&
125 file $(git rev-parse --verify HEAD:file) 100644 $(test_oid zero) 100644
127 git diff >out &&
128 cut -d" " -f1,3-4,6- <out >actual &&
129 test_cmp expect actual
132 test_expect_success !SANITIZE_LEAK 'diff attribute should apply only to diff' '
133 git log -p -1 HEAD >out &&
134 grep "^diff --git a/file b/file" out
138 test_expect_success 'diff attribute and --no-ext-diff' '
139 git diff --no-ext-diff >out &&
140 grep "^diff --git a/file b/file" out
144 test_expect_success 'GIT_EXTERNAL_DIFF trumps diff.external' '
145 >.gitattributes &&
146 test_config diff.external "echo ext-global" &&
148 cat >expect <<-EOF &&
149 ext-env file $(git rev-parse --verify HEAD:file) 100644 file $(test_oid zero) 100644
151 GIT_EXTERNAL_DIFF="echo ext-env" git diff >out &&
152 cut -d" " -f1-2,4- <out >actual &&
153 test_cmp expect actual
156 test_expect_success 'attributes trump GIT_EXTERNAL_DIFF and diff.external' '
157 test_config diff.foo.command "echo ext-attribute" &&
158 test_config diff.external "echo ext-global" &&
159 echo "file diff=foo" >.gitattributes &&
161 cat >expect <<-EOF &&
162 ext-attribute file $(git rev-parse --verify HEAD:file) 100644 file $(test_oid zero) 100644
164 GIT_EXTERNAL_DIFF="echo ext-env" git diff >out &&
165 cut -d" " -f1-2,4- <out >actual &&
166 test_cmp expect actual
169 test_expect_success 'no diff with -diff' '
170 echo >.gitattributes "file -diff" &&
171 git diff >out &&
172 grep Binary out
175 check_external_diff () {
176 expect_code=$1
177 expect_out=$2
178 expect_err=$3
179 command_code=$4
180 trust_exit_code=$5
181 shift 5
182 options="$@"
184 command="echo output; exit $command_code;"
185 desc="external diff '$command' with trustExitCode=$trust_exit_code"
186 with_options="${options:+ with }$options"
188 test_expect_success "$desc via attribute$with_options" "
189 test_config diff.foo.command \"$command\" &&
190 test_config diff.foo.trustExitCode $trust_exit_code &&
191 echo \"file diff=foo\" >.gitattributes &&
192 test_expect_code $expect_code git diff $options >out 2>err &&
193 test_cmp $expect_out out &&
194 test_cmp $expect_err err
197 test_expect_success "$desc via diff.external$with_options" "
198 test_config diff.external \"$command\" &&
199 test_config diff.trustExitCode $trust_exit_code &&
200 >.gitattributes &&
201 test_expect_code $expect_code git diff $options >out 2>err &&
202 test_cmp $expect_out out &&
203 test_cmp $expect_err err
206 test_expect_success "$desc via GIT_EXTERNAL_DIFF$with_options" "
207 >.gitattributes &&
208 test_expect_code $expect_code env \
209 GIT_EXTERNAL_DIFF=\"$command\" \
210 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE=$trust_exit_code \
211 git diff $options >out 2>err &&
212 test_cmp $expect_out out &&
213 test_cmp $expect_err err
217 test_expect_success 'setup output files' '
218 : >empty &&
219 echo output >output &&
220 echo "fatal: external diff died, stopping at file" >error
223 check_external_diff 0 output empty 0 off
224 check_external_diff 128 output error 1 off
225 check_external_diff 0 output empty 0 on
226 check_external_diff 0 output empty 1 on
227 check_external_diff 128 output error 2 on
229 check_external_diff 1 output empty 0 off --exit-code
230 check_external_diff 128 output error 1 off --exit-code
231 check_external_diff 0 output empty 0 on --exit-code
232 check_external_diff 1 output empty 1 on --exit-code
233 check_external_diff 128 output error 2 on --exit-code
235 check_external_diff 1 empty empty 0 off --quiet
236 check_external_diff 1 empty empty 1 off --quiet # we don't even call the program
237 check_external_diff 0 empty empty 0 on --quiet
238 check_external_diff 1 empty empty 1 on --quiet
239 check_external_diff 128 empty error 2 on --quiet
241 echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
243 test_expect_success 'force diff with "diff"' '
244 after=$(git hash-object file) &&
245 after=$(git rev-parse --short $after) &&
246 echo >.gitattributes "file diff" &&
247 git diff >actual &&
248 sed -e "s/^index .*/index $before..$after 100644/" \
249 "$TEST_DIRECTORY"/t4020/diff.NUL >expected-diff &&
250 test_cmp expected-diff actual
253 test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
254 echo anotherfile > file2 &&
255 git add file2 &&
256 git commit -m "added 2nd file" &&
257 echo modified >file2 &&
258 GIT_EXTERNAL_DIFF=echo git diff
261 test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' '
262 write_script external-diff.sh <<-\EOF &&
263 echo $GIT_DIFF_PATH_COUNTER of $GIT_DIFF_PATH_TOTAL >>counter.txt
265 >counter.txt &&
266 cat >expect <<-\EOF &&
267 1 of 2
268 2 of 2
270 GIT_EXTERNAL_DIFF=./external-diff.sh git diff &&
271 test_cmp expect counter.txt
274 test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
275 test_when_finished "git rm -f file.ext" &&
276 touch file.ext &&
277 git add file.ext &&
278 echo with extension > file.ext &&
280 cat >expect <<-EOF &&
281 file.ext
283 GIT_EXTERNAL_DIFF=echo git diff file.ext >out &&
284 basename $(cut -d" " -f2 <out) >actual &&
285 test_cmp expect actual
288 echo "#!$SHELL_PATH" >fake-diff.sh
289 cat >> fake-diff.sh <<\EOF
290 cat $2 >> crlfed.txt
292 chmod a+x fake-diff.sh
294 keep_only_cr () {
295 tr -dc '\015'
298 test_expect_success 'external diff with autocrlf = true' '
299 test_config core.autocrlf true &&
300 GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
301 test $(wc -l <crlfed.txt) = $(keep_only_cr <crlfed.txt | wc -c)
304 test_expect_success 'diff --cached' '
305 test_config core.autocrlf true &&
306 git add file &&
307 git update-index --assume-unchanged file &&
308 echo second >file &&
309 git diff --cached >actual &&
310 test_cmp expected-diff actual
313 test_expect_success 'clean up crlf leftovers' '
314 git update-index --no-assume-unchanged file &&
315 rm -f file* &&
316 git reset --hard
319 test_expect_success 'submodule diff' '
320 git init sub &&
321 ( cd sub && test_commit sub1 ) &&
322 git add sub &&
323 test_tick &&
324 git commit -m "add submodule" &&
325 ( cd sub && test_commit sub2 ) &&
326 write_script gather_pre_post.sh <<-\EOF &&
327 echo "$1 $4" # path, mode
328 cat "$2" # old file
329 cat "$5" # new file
331 GIT_EXTERNAL_DIFF=./gather_pre_post.sh git diff >actual &&
332 cat >expected <<-EOF &&
333 sub 160000
334 Subproject commit $(git rev-parse HEAD:sub)
335 Subproject commit $(cd sub && git rev-parse HEAD)
337 test_cmp expected actual
340 test_done