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