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