Merge branch 'jk/diff-highlight-graph-fix'
[git] / t / t1001-read-tree-m-2way.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
5
6 test_description='Two way merge with read-tree -m $H $M
7
8 This test tries two-way merge (aka fast-forward with carry forward).
9
10 There is the head (called H) and another commit (called M), which is
11 simply ahead of H.  The index and the work tree contains a state that
12 is derived from H, but may also have local changes.  This test checks
13 all the combinations described in the two-tree merge "carry forward"
14 rules, found in <Documentation/git read-tree.txt>.
15
16 In the test, these paths are used:
17         bozbar  - in H, stays in M, modified from bozbar to gnusto
18         frotz   - not in H added in M
19         nitfol  - in H, stays in M unmodified
20         rezrov  - in H, deleted in M
21         yomin   - not in H or M
22 '
23 . ./test-lib.sh
24 . "$TEST_DIRECTORY"/lib-read-tree.sh
25
26 read_tree_twoway () {
27     git read-tree -m "$1" "$2" && git ls-files --stage
28 }
29
30 compare_change () {
31         sed -n >current \
32             -e '/^--- /d; /^+++ /d; /^@@ /d;' \
33             -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
34             "$1"
35         test_cmp expected current
36 }
37
38 check_cache_at () {
39         clean_if_empty=$(git diff-files -- "$1")
40         case "$clean_if_empty" in
41         '')  echo "$1: clean" ;;
42         ?*)  echo "$1: dirty" ;;
43         esac
44         case "$2,$clean_if_empty" in
45         clean,)         :     ;;
46         clean,?*)       false ;;
47         dirty,)         false ;;
48         dirty,?*)       :     ;;
49         esac
50 }
51
52 cat >bozbar-old <<\EOF
53 This is a sample file used in two-way fast-forward merge
54 tests.  Its second line ends with a magic word bozbar
55 which will be modified by the merged head to gnusto.
56 It has some extra lines so that external tools can
57 successfully merge independent changes made to later
58 lines (such as this one), avoiding line conflicts.
59 EOF
60
61 sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
62
63 test_expect_success 'setup' '
64         echo frotz >frotz &&
65         echo nitfol >nitfol &&
66         cat bozbar-old >bozbar &&
67         echo rezrov >rezrov &&
68         echo yomin >yomin &&
69         git update-index --add nitfol bozbar rezrov &&
70         treeH=$(git write-tree) &&
71         echo treeH $treeH &&
72         git ls-tree $treeH &&
73
74         cat bozbar-new >bozbar &&
75         git update-index --add frotz bozbar --force-remove rezrov &&
76         git ls-files --stage >M.out &&
77         treeM=$(git write-tree) &&
78         echo treeM $treeM &&
79         git ls-tree $treeM &&
80         git diff-tree $treeH $treeM
81 '
82
83 test_expect_success '1, 2, 3 - no carry forward' '
84         rm -f .git/index &&
85         read_tree_twoway $treeH $treeM &&
86         git ls-files --stage >1-3.out &&
87         test_cmp M.out 1-3.out &&
88         check_cache_at bozbar dirty &&
89         check_cache_at frotz dirty &&
90         check_cache_at nitfol dirty
91 '
92 echo '+100644 X 0       yomin' >expected
93
94 test_expect_success '4 - carry forward local addition.' '
95         rm -f .git/index &&
96         read_tree_must_succeed $treeH &&
97         git checkout-index -u -f -q -a &&
98         git update-index --add yomin &&
99         read_tree_twoway $treeH $treeM &&
100         git ls-files --stage >4.out &&
101         test_must_fail git diff --no-index M.out 4.out >4diff.out &&
102         compare_change 4diff.out expected &&
103         check_cache_at yomin clean
104 '
105
106 test_expect_success '5 - carry forward local addition.' '
107         rm -f .git/index &&
108         read_tree_must_succeed $treeH &&
109         git checkout-index -u -f -q -a &&
110         echo yomin >yomin &&
111         git update-index --add yomin &&
112         echo yomin yomin >yomin &&
113         read_tree_twoway $treeH $treeM &&
114         git ls-files --stage >5.out &&
115         test_must_fail git diff --no-index M.out 5.out >5diff.out &&
116         compare_change 5diff.out expected &&
117         check_cache_at yomin dirty
118 '
119
120 test_expect_success '6 - local addition already has the same.' '
121         rm -f .git/index &&
122         read_tree_must_succeed $treeH &&
123         git checkout-index -u -f -q -a &&
124         git update-index --add frotz &&
125         read_tree_twoway $treeH $treeM &&
126         git ls-files --stage >6.out &&
127         test_cmp M.out 6.out &&
128         check_cache_at frotz clean
129 '
130
131 test_expect_success '7 - local addition already has the same.' '
132         rm -f .git/index &&
133         read_tree_must_succeed $treeH &&
134         git checkout-index -u -f -q -a &&
135         echo frotz >frotz &&
136         git update-index --add frotz &&
137         echo frotz frotz >frotz &&
138         read_tree_twoway $treeH $treeM &&
139         git ls-files --stage >7.out &&
140         test_cmp M.out 7.out &&
141         check_cache_at frotz dirty
142 '
143
144 test_expect_success '8 - conflicting addition.' '
145         rm -f .git/index &&
146         read_tree_must_succeed $treeH &&
147         git checkout-index -u -f -q -a &&
148         echo frotz frotz >frotz &&
149         git update-index --add frotz &&
150         if read_tree_twoway $treeH $treeM; then false; else :; fi
151 '
152
153 test_expect_success '9 - conflicting addition.' '
154         rm -f .git/index &&
155         read_tree_must_succeed $treeH &&
156         git checkout-index -u -f -q -a &&
157         echo frotz frotz >frotz &&
158         git update-index --add frotz &&
159         echo frotz >frotz &&
160         if read_tree_twoway $treeH $treeM; then false; else :; fi
161 '
162
163 test_expect_success '10 - path removed.' '
164         rm -f .git/index &&
165         read_tree_must_succeed $treeH &&
166         git checkout-index -u -f -q -a &&
167         echo rezrov >rezrov &&
168         git update-index --add rezrov &&
169         read_tree_twoway $treeH $treeM &&
170         git ls-files --stage >10.out &&
171         test_cmp M.out 10.out
172 '
173
174 test_expect_success '11 - dirty path removed.' '
175         rm -f .git/index &&
176         read_tree_must_succeed $treeH &&
177         git checkout-index -u -f -q -a &&
178         echo rezrov >rezrov &&
179         git update-index --add rezrov &&
180         echo rezrov rezrov >rezrov &&
181         if read_tree_twoway $treeH $treeM; then false; else :; fi
182 '
183
184 test_expect_success '12 - unmatching local changes being removed.' '
185         rm -f .git/index &&
186         read_tree_must_succeed $treeH &&
187         git checkout-index -u -f -q -a &&
188         echo rezrov rezrov >rezrov &&
189         git update-index --add rezrov &&
190         if read_tree_twoway $treeH $treeM; then false; else :; fi
191 '
192
193 test_expect_success '13 - unmatching local changes being removed.' '
194         rm -f .git/index &&
195         read_tree_must_succeed $treeH &&
196         git checkout-index -u -f -q -a &&
197         echo rezrov rezrov >rezrov &&
198         git update-index --add rezrov &&
199         echo rezrov >rezrov &&
200         if read_tree_twoway $treeH $treeM; then false; else :; fi
201 '
202
203 cat >expected <<EOF
204 -100644 X 0     nitfol
205 +100644 X 0     nitfol
206 EOF
207
208 test_expect_success '14 - unchanged in two heads.' '
209         rm -f .git/index &&
210         read_tree_must_succeed $treeH &&
211         git checkout-index -u -f -q -a &&
212         echo nitfol nitfol >nitfol &&
213         git update-index --add nitfol &&
214         read_tree_twoway $treeH $treeM &&
215         git ls-files --stage >14.out &&
216         test_must_fail git diff --no-index M.out 14.out >14diff.out &&
217         compare_change 14diff.out expected &&
218         check_cache_at nitfol clean
219 '
220
221 test_expect_success '15 - unchanged in two heads.' '
222         rm -f .git/index &&
223         read_tree_must_succeed $treeH &&
224         git checkout-index -u -f -q -a &&
225         echo nitfol nitfol >nitfol &&
226         git update-index --add nitfol &&
227         echo nitfol nitfol nitfol >nitfol &&
228         read_tree_twoway $treeH $treeM &&
229         git ls-files --stage >15.out &&
230         test_must_fail git diff --no-index M.out 15.out >15diff.out &&
231         compare_change 15diff.out expected &&
232         check_cache_at nitfol dirty
233 '
234
235 test_expect_success '16 - conflicting local change.' '
236         rm -f .git/index &&
237         read_tree_must_succeed $treeH &&
238         git checkout-index -u -f -q -a &&
239         echo bozbar bozbar >bozbar &&
240         git update-index --add bozbar &&
241         if read_tree_twoway $treeH $treeM; then false; else :; fi
242 '
243
244 test_expect_success '17 - conflicting local change.' '
245         rm -f .git/index &&
246         read_tree_must_succeed $treeH &&
247         git checkout-index -u -f -q -a &&
248         echo bozbar bozbar >bozbar &&
249         git update-index --add bozbar &&
250         echo bozbar bozbar bozbar >bozbar &&
251         if read_tree_twoway $treeH $treeM; then false; else :; fi
252 '
253
254 test_expect_success '18 - local change already having a good result.' '
255         rm -f .git/index &&
256         read_tree_must_succeed $treeH &&
257         git checkout-index -u -f -q -a &&
258         cat bozbar-new >bozbar &&
259         git update-index --add bozbar &&
260         read_tree_twoway $treeH $treeM &&
261         git ls-files --stage >18.out &&
262         test_cmp M.out 18.out &&
263         check_cache_at bozbar clean
264 '
265
266 test_expect_success '19 - local change already having a good result, further modified.' '
267         rm -f .git/index &&
268         read_tree_must_succeed $treeH &&
269         git checkout-index -u -f -q -a &&
270         cat bozbar-new >bozbar &&
271         git update-index --add bozbar &&
272         echo gnusto gnusto >bozbar &&
273         read_tree_twoway $treeH $treeM &&
274         git ls-files --stage >19.out &&
275         test_cmp M.out 19.out &&
276         check_cache_at bozbar dirty
277 '
278
279 test_expect_success '20 - no local change, use new tree.' '
280         rm -f .git/index &&
281         read_tree_must_succeed $treeH &&
282         git checkout-index -u -f -q -a &&
283         cat bozbar-old >bozbar &&
284         git update-index --add bozbar &&
285         read_tree_twoway $treeH $treeM &&
286         git ls-files --stage >20.out &&
287         test_cmp M.out 20.out &&
288         check_cache_at bozbar dirty
289 '
290
291 test_expect_success '21 - no local change, dirty cache.' '
292         rm -f .git/index &&
293         read_tree_must_succeed $treeH &&
294         git checkout-index -u -f -q -a &&
295         cat bozbar-old >bozbar &&
296         git update-index --add bozbar &&
297         echo gnusto gnusto >bozbar &&
298         if read_tree_twoway $treeH $treeM; then false; else :; fi
299 '
300
301 # This fails with straight two-way fast-forward.
302 test_expect_success '22 - local change cache updated.' '
303         rm -f .git/index &&
304         read_tree_must_succeed $treeH &&
305         git checkout-index -u -f -q -a &&
306         sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
307         git update-index --add bozbar &&
308         if read_tree_twoway $treeH $treeM; then false; else :; fi
309 '
310
311 # Also make sure we did not break DF vs DF/DF case.
312 test_expect_success 'DF vs DF/DF case setup.' '
313         rm -f .git/index &&
314         echo DF >DF &&
315         git update-index --add DF &&
316         treeDF=$(git write-tree) &&
317         echo treeDF $treeDF &&
318         git ls-tree $treeDF &&
319
320         rm -f DF &&
321         mkdir DF &&
322         echo DF/DF >DF/DF &&
323         git update-index --add --remove DF DF/DF &&
324         treeDFDF=$(git write-tree) &&
325         echo treeDFDF $treeDFDF &&
326         git ls-tree $treeDFDF &&
327         git ls-files --stage >DFDF.out
328 '
329
330 test_expect_success 'DF vs DF/DF case test.' '
331         rm -f .git/index &&
332         rm -fr DF &&
333         echo DF >DF &&
334         git update-index --add DF &&
335         read_tree_twoway $treeDF $treeDFDF &&
336         git ls-files --stage >DFDFcheck.out &&
337         test_cmp DFDF.out DFDFcheck.out &&
338         check_cache_at DF/DF dirty &&
339         :
340 '
341
342 test_expect_success 'a/b (untracked) vs a case setup.' '
343         rm -f .git/index &&
344         : >a &&
345         git update-index --add a &&
346         treeM=$(git write-tree) &&
347         echo treeM $treeM &&
348         git ls-tree $treeM &&
349         git ls-files --stage >treeM.out &&
350
351         rm -f a &&
352         git update-index --remove a &&
353         mkdir a &&
354         : >a/b &&
355         treeH=$(git write-tree) &&
356         echo treeH $treeH &&
357         git ls-tree $treeH
358 '
359
360 test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '
361         read_tree_u_must_fail -u -m "$treeH" "$treeM" &&
362         git ls-files --stage &&
363         test -f a/b
364 '
365
366 test_expect_success 'read-tree supports the super-prefix' '
367         cat <<-EOF >expect &&
368                 error: Updating '\''fictional/a'\'' would lose untracked files in it
369         EOF
370         test_must_fail git --super-prefix fictional/ read-tree -u -m "$treeH" "$treeM" 2>actual &&
371         test_cmp expect actual
372 '
373
374 test_expect_success 'a/b vs a, plus c/d case setup.' '
375         rm -f .git/index &&
376         rm -fr a &&
377         : >a &&
378         mkdir c &&
379         : >c/d &&
380         git update-index --add a c/d &&
381         treeM=$(git write-tree) &&
382         echo treeM $treeM &&
383         git ls-tree $treeM &&
384         git ls-files --stage >treeM.out &&
385
386         rm -f a &&
387         mkdir a &&
388         : >a/b &&
389         git update-index --add --remove a a/b &&
390         treeH=$(git write-tree) &&
391         echo treeH $treeH &&
392         git ls-tree $treeH
393 '
394
395 test_expect_success 'a/b vs a, plus c/d case test.' '
396         read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&
397         git ls-files --stage | tee >treeMcheck.out &&
398         test_cmp treeM.out treeMcheck.out
399 '
400
401 test_expect_success '-m references the correct modified tree' '
402         echo >file-a &&
403         echo >file-b &&
404         git add file-a file-b &&
405         git commit -a -m "test for correct modified tree" &&
406         git branch initial-mod &&
407         echo b >file-b &&
408         git commit -a -m "B" &&
409         echo a >file-a &&
410         git add file-a &&
411         git ls-tree $(git write-tree) file-a >expect &&
412         read_tree_must_succeed -m HEAD initial-mod &&
413         git ls-tree $(git write-tree) file-a >actual &&
414         test_cmp expect actual
415 '
416
417 test_done