Merge branch 'jc/doc-git-updates'
[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 nor 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 \
64     setup \
65     'echo frotz >frotz &&
66      echo nitfol >nitfol &&
67      cat bozbar-old >bozbar &&
68      echo rezrov >rezrov &&
69      echo yomin >yomin &&
70      git update-index --add nitfol bozbar rezrov &&
71      treeH=`git write-tree` &&
72      echo treeH $treeH &&
73      git ls-tree $treeH &&
74
75      cat bozbar-new >bozbar &&
76      git update-index --add frotz bozbar --force-remove rezrov &&
77      git ls-files --stage >M.out &&
78      treeM=`git write-tree` &&
79      echo treeM $treeM &&
80      git ls-tree $treeM &&
81      git diff-tree $treeH $treeM'
82
83 test_expect_success \
84     '1, 2, 3 - no carry forward' \
85     'rm -f .git/index &&
86      read_tree_twoway $treeH $treeM &&
87      git ls-files --stage >1-3.out &&
88      test_cmp M.out 1-3.out &&
89      check_cache_at bozbar dirty &&
90      check_cache_at frotz dirty &&
91      check_cache_at nitfol dirty'
92
93 echo '+100644 X 0       yomin' >expected
94
95 test_expect_success \
96     '4 - carry forward local addition.' \
97     'rm -f .git/index &&
98      read_tree_must_succeed $treeH &&
99      git checkout-index -u -f -q -a &&
100      git update-index --add yomin &&
101      read_tree_twoway $treeH $treeM &&
102      git ls-files --stage >4.out &&
103      test_must_fail git diff --no-index M.out 4.out >4diff.out &&
104      compare_change 4diff.out expected &&
105      check_cache_at yomin clean'
106
107 test_expect_success \
108     '5 - carry forward local addition.' \
109     'rm -f .git/index &&
110      read_tree_must_succeed $treeH &&
111      git checkout-index -u -f -q -a &&
112      echo yomin >yomin &&
113      git update-index --add yomin &&
114      echo yomin yomin >yomin &&
115      read_tree_twoway $treeH $treeM &&
116      git ls-files --stage >5.out &&
117      test_must_fail git diff --no-index M.out 5.out >5diff.out &&
118      compare_change 5diff.out expected &&
119      check_cache_at yomin dirty'
120
121 test_expect_success \
122     '6 - local addition already has the same.' \
123     'rm -f .git/index &&
124      read_tree_must_succeed $treeH &&
125      git checkout-index -u -f -q -a &&
126      git update-index --add frotz &&
127      read_tree_twoway $treeH $treeM &&
128      git ls-files --stage >6.out &&
129      test_cmp M.out 6.out &&
130      check_cache_at frotz clean'
131
132 test_expect_success \
133     '7 - local addition already has the same.' \
134     'rm -f .git/index &&
135      read_tree_must_succeed $treeH &&
136      git checkout-index -u -f -q -a &&
137      echo frotz >frotz &&
138      git update-index --add frotz &&
139      echo frotz frotz >frotz &&
140      read_tree_twoway $treeH $treeM &&
141      git ls-files --stage >7.out &&
142      test_cmp M.out 7.out &&
143      check_cache_at frotz dirty'
144
145 test_expect_success \
146     '8 - conflicting addition.' \
147     'rm -f .git/index &&
148      read_tree_must_succeed $treeH &&
149      git checkout-index -u -f -q -a &&
150      echo frotz frotz >frotz &&
151      git update-index --add frotz &&
152      if read_tree_twoway $treeH $treeM; then false; else :; fi'
153
154 test_expect_success \
155     '9 - conflicting addition.' \
156     'rm -f .git/index &&
157      read_tree_must_succeed $treeH &&
158      git checkout-index -u -f -q -a &&
159      echo frotz frotz >frotz &&
160      git update-index --add frotz &&
161      echo frotz >frotz &&
162      if read_tree_twoway $treeH $treeM; then false; else :; fi'
163
164 test_expect_success \
165     '10 - path removed.' \
166     'rm -f .git/index &&
167      read_tree_must_succeed $treeH &&
168      git checkout-index -u -f -q -a &&
169      echo rezrov >rezrov &&
170      git update-index --add rezrov &&
171      read_tree_twoway $treeH $treeM &&
172      git ls-files --stage >10.out &&
173      test_cmp M.out 10.out'
174
175 test_expect_success \
176     '11 - dirty path removed.' \
177     'rm -f .git/index &&
178      read_tree_must_succeed $treeH &&
179      git checkout-index -u -f -q -a &&
180      echo rezrov >rezrov &&
181      git update-index --add rezrov &&
182      echo rezrov rezrov >rezrov &&
183      if read_tree_twoway $treeH $treeM; then false; else :; fi'
184
185 test_expect_success \
186     '12 - unmatching local changes being removed.' \
187     'rm -f .git/index &&
188      read_tree_must_succeed $treeH &&
189      git checkout-index -u -f -q -a &&
190      echo rezrov rezrov >rezrov &&
191      git update-index --add rezrov &&
192      if read_tree_twoway $treeH $treeM; then false; else :; fi'
193
194 test_expect_success \
195     '13 - unmatching local changes being removed.' \
196     'rm -f .git/index &&
197      read_tree_must_succeed $treeH &&
198      git checkout-index -u -f -q -a &&
199      echo rezrov rezrov >rezrov &&
200      git update-index --add rezrov &&
201      echo rezrov >rezrov &&
202      if read_tree_twoway $treeH $treeM; then false; else :; fi'
203
204 cat >expected <<EOF
205 -100644 X 0     nitfol
206 +100644 X 0     nitfol
207 EOF
208
209 test_expect_success \
210     '14 - unchanged in two heads.' \
211     'rm -f .git/index &&
212      read_tree_must_succeed $treeH &&
213      git checkout-index -u -f -q -a &&
214      echo nitfol nitfol >nitfol &&
215      git update-index --add nitfol &&
216      read_tree_twoway $treeH $treeM &&
217      git ls-files --stage >14.out &&
218      test_must_fail git diff --no-index M.out 14.out >14diff.out &&
219      compare_change 14diff.out expected &&
220      check_cache_at nitfol clean'
221
222 test_expect_success \
223     '15 - unchanged in two heads.' \
224     'rm -f .git/index &&
225      read_tree_must_succeed $treeH &&
226      git checkout-index -u -f -q -a &&
227      echo nitfol nitfol >nitfol &&
228      git update-index --add nitfol &&
229      echo nitfol nitfol nitfol >nitfol &&
230      read_tree_twoway $treeH $treeM &&
231      git ls-files --stage >15.out &&
232      test_must_fail git diff --no-index M.out 15.out >15diff.out &&
233      compare_change 15diff.out expected &&
234      check_cache_at nitfol dirty'
235
236 test_expect_success \
237     '16 - conflicting local change.' \
238     'rm -f .git/index &&
239      read_tree_must_succeed $treeH &&
240      git checkout-index -u -f -q -a &&
241      echo bozbar bozbar >bozbar &&
242      git update-index --add bozbar &&
243      if read_tree_twoway $treeH $treeM; then false; else :; fi'
244
245 test_expect_success \
246     '17 - conflicting local change.' \
247     'rm -f .git/index &&
248      read_tree_must_succeed $treeH &&
249      git checkout-index -u -f -q -a &&
250      echo bozbar bozbar >bozbar &&
251      git update-index --add bozbar &&
252      echo bozbar bozbar bozbar >bozbar &&
253      if read_tree_twoway $treeH $treeM; then false; else :; fi'
254
255 test_expect_success \
256     '18 - local change already having a good result.' \
257     'rm -f .git/index &&
258      read_tree_must_succeed $treeH &&
259      git checkout-index -u -f -q -a &&
260      cat bozbar-new >bozbar &&
261      git update-index --add bozbar &&
262      read_tree_twoway $treeH $treeM &&
263      git ls-files --stage >18.out &&
264      test_cmp M.out 18.out &&
265      check_cache_at bozbar clean'
266
267 test_expect_success \
268     '19 - local change already having a good result, further modified.' \
269     'rm -f .git/index &&
270      read_tree_must_succeed $treeH &&
271      git checkout-index -u -f -q -a &&
272      cat bozbar-new >bozbar &&
273      git update-index --add bozbar &&
274      echo gnusto gnusto >bozbar &&
275      read_tree_twoway $treeH $treeM &&
276      git ls-files --stage >19.out &&
277      test_cmp M.out 19.out &&
278      check_cache_at bozbar dirty'
279
280 test_expect_success \
281     '20 - no local change, use new tree.' \
282     'rm -f .git/index &&
283      read_tree_must_succeed $treeH &&
284      git checkout-index -u -f -q -a &&
285      cat bozbar-old >bozbar &&
286      git update-index --add bozbar &&
287      read_tree_twoway $treeH $treeM &&
288      git ls-files --stage >20.out &&
289      test_cmp M.out 20.out &&
290      check_cache_at bozbar dirty'
291
292 test_expect_success \
293     '21 - no local change, dirty cache.' \
294     'rm -f .git/index &&
295      read_tree_must_succeed $treeH &&
296      git checkout-index -u -f -q -a &&
297      cat bozbar-old >bozbar &&
298      git update-index --add bozbar &&
299      echo gnusto gnusto >bozbar &&
300      if read_tree_twoway $treeH $treeM; then false; else :; fi'
301
302 # This fails with straight two-way fast-forward.
303 test_expect_success \
304     '22 - local change cache updated.' \
305     'rm -f .git/index &&
306      read_tree_must_succeed $treeH &&
307      git checkout-index -u -f -q -a &&
308      sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
309      git update-index --add bozbar &&
310      if read_tree_twoway $treeH $treeM; then false; else :; fi'
311
312 # Also make sure we did not break DF vs DF/DF case.
313 test_expect_success \
314     'DF vs DF/DF case setup.' \
315     'rm -f .git/index &&
316      echo DF >DF &&
317      git update-index --add DF &&
318      treeDF=`git write-tree` &&
319      echo treeDF $treeDF &&
320      git ls-tree $treeDF &&
321
322      rm -f DF &&
323      mkdir DF &&
324      echo DF/DF >DF/DF &&
325      git update-index --add --remove DF DF/DF &&
326      treeDFDF=`git write-tree` &&
327      echo treeDFDF $treeDFDF &&
328      git ls-tree $treeDFDF &&
329      git ls-files --stage >DFDF.out'
330
331 test_expect_success \
332     'DF vs DF/DF case test.' \
333     'rm -f .git/index &&
334      rm -fr DF &&
335      echo DF >DF &&
336      git update-index --add DF &&
337      read_tree_twoway $treeDF $treeDFDF &&
338      git ls-files --stage >DFDFcheck.out &&
339      test_cmp DFDF.out DFDFcheck.out &&
340      check_cache_at DF/DF dirty &&
341      :'
342
343 test_expect_success \
344     'a/b (untracked) vs a case setup.' \
345     'rm -f .git/index &&
346      : >a &&
347      git update-index --add a &&
348      treeM=`git write-tree` &&
349      echo treeM $treeM &&
350      git ls-tree $treeM &&
351      git ls-files --stage >treeM.out &&
352
353      rm -f a &&
354      git update-index --remove a &&
355      mkdir a &&
356      : >a/b &&
357      treeH=`git write-tree` &&
358      echo treeH $treeH &&
359      git ls-tree $treeH'
360
361 test_expect_success \
362     'a/b (untracked) vs a, plus c/d case test.' \
363     'read_tree_u_must_fail -u -m "$treeH" "$treeM" &&
364      git ls-files --stage &&
365      test -f a/b'
366
367 test_expect_success \
368     'a/b vs a, plus c/d case setup.' \
369     'rm -f .git/index &&
370      rm -fr a &&
371      : >a &&
372      mkdir c &&
373      : >c/d &&
374      git update-index --add a c/d &&
375      treeM=`git write-tree` &&
376      echo treeM $treeM &&
377      git ls-tree $treeM &&
378      git ls-files --stage >treeM.out &&
379
380      rm -f a &&
381      mkdir a &&
382      : >a/b &&
383      git update-index --add --remove a a/b &&
384      treeH=`git write-tree` &&
385      echo treeH $treeH &&
386      git ls-tree $treeH'
387
388 test_expect_success \
389     'a/b vs a, plus c/d case test.' \
390     'read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&
391      git ls-files --stage | tee >treeMcheck.out &&
392      test_cmp treeM.out treeMcheck.out'
393
394 test_expect_success '-m references the correct modified tree' '
395         echo >file-a &&
396         echo >file-b &&
397         git add file-a file-b &&
398         git commit -a -m "test for correct modified tree" &&
399         git branch initial-mod &&
400         echo b >file-b &&
401         git commit -a -m "B" &&
402         echo a >file-a &&
403         git add file-a &&
404         git ls-tree $(git write-tree) file-a >expect &&
405         read_tree_must_succeed -m HEAD initial-mod &&
406         git ls-tree $(git write-tree) file-a >actual &&
407         test_cmp expect actual
408 '
409
410 test_done