Merge branch 'ds/more-index-cleanups'
[git] / t / t4038-diff-combined.sh
1 #!/bin/sh
2
3 test_description='combined diff'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/diff-lib.sh
10
11 setup_helper () {
12         one=$1 branch=$2 side=$3 &&
13
14         git branch $side $branch &&
15         for l in $one two three fyra
16         do
17                 echo $l
18         done >file &&
19         git add file &&
20         test_tick &&
21         git commit -m $branch &&
22         git checkout $side &&
23         for l in $one two three quatro
24         do
25                 echo $l
26         done >file &&
27         git add file &&
28         test_tick &&
29         git commit -m $side &&
30         test_must_fail git merge $branch &&
31         for l in $one three four
32         do
33                 echo $l
34         done >file &&
35         git add file &&
36         test_tick &&
37         git commit -m "merge $branch into $side"
38 }
39
40 verify_helper () {
41         it=$1 &&
42
43         # Ignore lines that were removed only from the other parent
44         sed -e '
45                 1,/^@@@/d
46                 /^ -/d
47                 s/^\(.\)./\1/
48         ' "$it" >"$it.actual.1" &&
49         sed -e '
50                 1,/^@@@/d
51                 /^- /d
52                 s/^.\(.\)/\1/
53         ' "$it" >"$it.actual.2" &&
54
55         git diff "$it^" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.1" &&
56         test_cmp "$it.expect.1" "$it.actual.1" &&
57
58         git diff "$it^2" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.2" &&
59         test_cmp "$it.expect.2" "$it.actual.2"
60 }
61
62 test_expect_success setup '
63         >file &&
64         git add file &&
65         test_tick &&
66         git commit -m initial &&
67
68         git branch withone &&
69         git branch sansone &&
70
71         git checkout withone &&
72         setup_helper one withone sidewithone &&
73
74         git checkout sansone &&
75         setup_helper "" sansone sidesansone
76 '
77
78 test_expect_success 'check combined output (1)' '
79         git show sidewithone -- >sidewithone &&
80         verify_helper sidewithone
81 '
82
83 test_expect_success 'check combined output (2)' '
84         git show sidesansone -- >sidesansone &&
85         verify_helper sidesansone
86 '
87
88 test_expect_success 'diagnose truncated file' '
89         >file &&
90         git add file &&
91         git commit --amend -C HEAD &&
92         git show >out &&
93         grep "diff --cc file" out
94 '
95
96 test_expect_success 'setup for --cc --raw' '
97         blob=$(echo file | git hash-object --stdin -w) &&
98         base_tree=$(echo "100644 blob $blob     file" | git mktree) &&
99         trees= &&
100         for i in $(test_seq 1 40)
101         do
102                 blob=$(echo file$i | git hash-object --stdin -w) &&
103                 trees="$trees$(echo "100644 blob $blob  file" | git mktree)$LF"
104         done
105 '
106
107 test_expect_success 'check --cc --raw with four trees' '
108         four_trees=$(echo "$trees" | sed -e 4q) &&
109         git diff --cc --raw $four_trees $base_tree >out &&
110         # Check for four leading colons in the output:
111         grep "^::::[^:]" out
112 '
113
114 test_expect_success 'check --cc --raw with forty trees' '
115         git diff --cc --raw $trees $base_tree >out &&
116         # Check for forty leading colons in the output:
117         grep "^::::::::::::::::::::::::::::::::::::::::[^:]" out
118 '
119
120 test_expect_success 'setup combined ignore spaces' '
121         git checkout main &&
122         >test &&
123         git add test &&
124         git commit -m initial &&
125
126         tr -d Q <<-\EOF >test &&
127         always coalesce
128         eol space coalesce Q
129         space  change coalesce
130         all spa ces coalesce
131         eol spaces Q
132         space  change
133         all spa ces
134         EOF
135         git commit -m "test space change" -a &&
136
137         git checkout -b side HEAD^ &&
138         tr -d Q <<-\EOF >test &&
139         always coalesce
140         eol space coalesce
141         space change coalesce
142         all spaces coalesce
143         eol spaces
144         space change
145         all spaces
146         EOF
147         git commit -m "test other space changes" -a &&
148
149         test_must_fail git merge main &&
150         tr -d Q <<-\EOF >test &&
151         eol spaces Q
152         space  change
153         all spa ces
154         EOF
155         git commit -m merged -a
156 '
157
158 test_expect_success 'check combined output (no ignore space)' '
159         git show >actual.tmp &&
160         sed -e "1,/^@@@/d" < actual.tmp >actual &&
161         tr -d Q <<-\EOF >expected &&
162         --always coalesce
163         - eol space coalesce
164         - space change coalesce
165         - all spaces coalesce
166         - eol spaces
167         - space change
168         - all spaces
169          -eol space coalesce Q
170          -space  change coalesce
171          -all spa ces coalesce
172         + eol spaces Q
173         + space  change
174         + all spa ces
175         EOF
176         compare_diff_patch expected actual
177 '
178
179 test_expect_success 'check combined output (ignore space at eol)' '
180         git show --ignore-space-at-eol >actual.tmp &&
181         sed -e "1,/^@@@/d" < actual.tmp >actual &&
182         tr -d Q <<-\EOF >expected &&
183         --always coalesce
184         --eol space coalesce
185         - space change coalesce
186         - all spaces coalesce
187          -space  change coalesce
188          -all spa ces coalesce
189           eol spaces Q
190         - space change
191         - all spaces
192         + space  change
193         + all spa ces
194         EOF
195         compare_diff_patch expected actual
196 '
197
198 test_expect_success 'check combined output (ignore space change)' '
199         git show -b >actual.tmp &&
200         sed -e "1,/^@@@/d" < actual.tmp >actual &&
201         tr -d Q <<-\EOF >expected &&
202         --always coalesce
203         --eol space coalesce
204         --space change coalesce
205         - all spaces coalesce
206          -all spa ces coalesce
207           eol spaces Q
208           space  change
209         - all spaces
210         + all spa ces
211         EOF
212         compare_diff_patch expected actual
213 '
214
215 test_expect_success 'check combined output (ignore all spaces)' '
216         git show -w >actual.tmp &&
217         sed -e "1,/^@@@/d" < actual.tmp >actual &&
218         tr -d Q <<-\EOF >expected &&
219         --always coalesce
220         --eol space coalesce
221         --space change coalesce
222         --all spaces coalesce
223           eol spaces Q
224           space  change
225           all spa ces
226         EOF
227         compare_diff_patch expected actual
228 '
229
230 test_expect_success 'combine diff coalesce simple' '
231         >test &&
232         git add test &&
233         git commit -m initial &&
234         test_seq 4 >test &&
235         git commit -a -m empty1 &&
236         git branch side1 &&
237         git checkout HEAD^ &&
238         test_seq 5 >test &&
239         git commit -a -m empty2 &&
240         test_must_fail git merge side1 &&
241         >test &&
242         git commit -a -m merge &&
243         git show >actual.tmp &&
244         sed -e "1,/^@@@/d" < actual.tmp >actual &&
245         tr -d Q <<-\EOF >expected &&
246         --1
247         --2
248         --3
249         --4
250         - 5
251         EOF
252         compare_diff_patch expected actual
253 '
254
255 test_expect_success 'combine diff coalesce tricky' '
256         >test &&
257         git add test &&
258         git commit -m initial --allow-empty &&
259         cat <<-\EOF >test &&
260         3
261         1
262         2
263         3
264         4
265         EOF
266         git commit -a -m empty1 &&
267         git branch -f side1 &&
268         git checkout HEAD^ &&
269         cat <<-\EOF >test &&
270         1
271         3
272         5
273         4
274         EOF
275         git commit -a -m empty2 &&
276         git branch -f side2 &&
277         test_must_fail git merge side1 &&
278         >test &&
279         git commit -a -m merge &&
280         git show >actual.tmp &&
281         sed -e "1,/^@@@/d" < actual.tmp >actual &&
282         tr -d Q <<-\EOF >expected &&
283          -3
284         --1
285          -2
286         --3
287         - 5
288         --4
289         EOF
290         compare_diff_patch expected actual &&
291         git checkout -f side1 &&
292         test_must_fail git merge side2 &&
293         >test &&
294         git commit -a -m merge &&
295         git show >actual.tmp &&
296         sed -e "1,/^@@@/d" < actual.tmp >actual &&
297         tr -d Q <<-\EOF >expected &&
298         - 3
299         --1
300         - 2
301         --3
302          -5
303         --4
304         EOF
305         compare_diff_patch expected actual
306 '
307
308 test_expect_failure 'combine diff coalesce three parents' '
309         >test &&
310         git add test &&
311         git commit -m initial --allow-empty &&
312         cat <<-\EOF >test &&
313         3
314         1
315         2
316         3
317         4
318         EOF
319         git commit -a -m empty1 &&
320         git checkout -B side1 &&
321         git checkout HEAD^ &&
322         cat <<-\EOF >test &&
323         1
324         3
325         7
326         5
327         4
328         EOF
329         git commit -a -m empty2 &&
330         git branch -f side2 &&
331         git checkout HEAD^ &&
332         cat <<-\EOF >test &&
333         3
334         1
335         6
336         5
337         4
338         EOF
339         git commit -a -m empty3 &&
340         >test &&
341         git add test &&
342         TREE=$(git write-tree) &&
343         COMMIT=$(git commit-tree -p HEAD -p side1 -p side2 -m merge $TREE) &&
344         git show $COMMIT >actual.tmp &&
345         sed -e "1,/^@@@/d" < actual.tmp >actual &&
346         tr -d Q <<-\EOF >expected &&
347         -- 3
348         ---1
349         -  6
350          - 2
351          --3
352           -7
353         - -5
354         ---4
355         EOF
356         compare_diff_patch expected actual
357 '
358
359 # Test for a bug reported at
360 # https://lore.kernel.org/git/20130515143508.GO25742@login.drsnuggles.stderr.nl/
361 # where a delete lines were missing from combined diff output when they
362 # occurred exactly before the context lines of a later change.
363 test_expect_success 'combine diff missing delete bug' '
364         git commit -m initial --allow-empty &&
365         cat <<-\EOF >test &&
366         1
367         2
368         3
369         4
370         EOF
371         git add test &&
372         git commit -a -m side1 &&
373         git checkout -B side1 &&
374         git checkout HEAD^ &&
375         cat <<-\EOF >test &&
376         0
377         1
378         2
379         3
380         4modified
381         EOF
382         git add test &&
383         git commit -m side2 &&
384         git branch -f side2 &&
385         test_must_fail git merge --no-commit side1 &&
386         cat <<-\EOF >test &&
387         1
388         2
389         3
390         4modified
391         EOF
392         git add test &&
393         git commit -a -m merge &&
394         git diff-tree -c -p HEAD >actual.tmp &&
395         sed -e "1,/^@@@/d" < actual.tmp >actual &&
396         tr -d Q <<-\EOF >expected &&
397         - 0
398           1
399           2
400           3
401          -4
402          +4modified
403         EOF
404         compare_diff_patch expected actual
405 '
406
407 test_expect_success 'combine diff gets tree sorting right' '
408         # create a directory and a file that sort differently in trees
409         # versus byte-wise (implied "/" sorts after ".")
410         git checkout -f main &&
411         mkdir foo &&
412         echo base >foo/one &&
413         echo base >foo/two &&
414         echo base >foo.ext &&
415         git add foo foo.ext &&
416         git commit -m base &&
417
418         # one side modifies a file in the directory, along with the root
419         # file...
420         echo main >foo/one &&
421         echo main >foo.ext &&
422         git commit -a -m main &&
423
424         # the other side modifies the other file in the directory
425         git checkout -b other HEAD^ &&
426         echo other >foo/two &&
427         git commit -a -m other &&
428
429         # And now we merge. The files in the subdirectory will resolve cleanly,
430         # meaning that a combined diff will not find them interesting. But it
431         # will find the tree itself interesting, because it had to be merged.
432         git checkout main &&
433         git merge other &&
434
435         printf "MM\tfoo\n" >expect &&
436         git diff-tree -c --name-status -t HEAD >actual.tmp &&
437         sed 1d <actual.tmp >actual &&
438         test_cmp expect actual
439 '
440
441 test_expect_success 'setup for --combined-all-paths' '
442         git branch side1c &&
443         git branch side2c &&
444         git checkout side1c &&
445         test_seq 1 10 >filename-side1c &&
446         side1cf=$(git hash-object filename-side1c) &&
447         git add filename-side1c &&
448         git commit -m with &&
449         git checkout side2c &&
450         test_seq 1 9 >filename-side2c &&
451         echo ten >>filename-side2c &&
452         side2cf=$(git hash-object filename-side2c) &&
453         git add filename-side2c &&
454         git commit -m iam &&
455         git checkout -b mergery side1c &&
456         git merge --no-commit side2c &&
457         git rm filename-side1c &&
458         echo eleven >>filename-side2c &&
459         git mv filename-side2c filename-merged &&
460         mergedf=$(git hash-object filename-merged) &&
461         git add filename-merged &&
462         git commit
463 '
464
465 test_expect_success '--combined-all-paths and --raw' '
466         cat <<-EOF >expect &&
467         ::100644 100644 100644 $side1cf $side2cf $mergedf RR    filename-side1c filename-side2c filename-merged
468         EOF
469         git diff-tree -c -M --raw --combined-all-paths HEAD >actual.tmp &&
470         sed 1d <actual.tmp >actual &&
471         test_cmp expect actual
472 '
473
474 test_expect_success '--combined-all-paths and --cc' '
475         cat <<-\EOF >expect &&
476         --- a/filename-side1c
477         --- a/filename-side2c
478         +++ b/filename-merged
479         EOF
480         git diff-tree --cc -M --combined-all-paths HEAD >actual.tmp &&
481         grep ^[-+][-+][-+] <actual.tmp >actual &&
482         test_cmp expect actual
483 '
484
485 test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names' '
486         git branch side1d &&
487         git branch side2d &&
488         git checkout side1d &&
489         test_seq 1 10 >"$(printf "file\twith\ttabs")" &&
490         git add file* &&
491         side1df=$(git hash-object *tabs) &&
492         git commit -m with &&
493         git checkout side2d &&
494         test_seq 1 9 >"$(printf "i\tam\ttabbed")" &&
495         echo ten >>"$(printf "i\tam\ttabbed")" &&
496         git add *tabbed &&
497         side2df=$(git hash-object *tabbed) &&
498         git commit -m iam &&
499         git checkout -b funny-names-mergery side1d &&
500         git merge --no-commit side2d &&
501         git rm *tabs &&
502         echo eleven >>"$(printf "i\tam\ttabbed")" &&
503         git mv "$(printf "i\tam\ttabbed")" "$(printf "fickle\tnaming")" &&
504         git add fickle* &&
505         headf=$(git hash-object fickle*) &&
506         git commit &&
507         head=$(git rev-parse HEAD)
508 '
509
510 test_expect_success FUNNYNAMES '--combined-all-paths and --raw and funny names' '
511         cat <<-EOF >expect &&
512         ::100644 100644 100644 $side1df $side2df $headf RR      "file\twith\ttabs"      "i\tam\ttabbed" "fickle\tnaming"
513         EOF
514         git diff-tree -c -M --raw --combined-all-paths HEAD >actual.tmp &&
515         sed 1d <actual.tmp >actual &&
516         test_cmp expect actual
517 '
518
519 test_expect_success FUNNYNAMES '--combined-all-paths and --raw -and -z and funny names' '
520         printf "$head\0::100644 100644 100644 $side1df $side2df $headf RR\0file\twith\ttabs\0i\tam\ttabbed\0fickle\tnaming\0" >expect &&
521         git diff-tree -c -M --raw --combined-all-paths -z HEAD >actual &&
522         test_cmp expect actual
523 '
524
525 test_expect_success FUNNYNAMES '--combined-all-paths and --cc and funny names' '
526         cat <<-\EOF >expect &&
527         --- "a/file\twith\ttabs"
528         --- "a/i\tam\ttabbed"
529         +++ "b/fickle\tnaming"
530         EOF
531         git diff-tree --cc -M --combined-all-paths HEAD >actual.tmp &&
532         grep ^[-+][-+][-+] <actual.tmp >actual &&
533         test_cmp expect actual
534 '
535
536 test_done