1#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano
4#
5
6test_description='Two way merge with read-tree --emu23 $H $M
7
8This test tries two-way merge (aka fast forward with carry forward).
9
10There is the head (called H) and another commit (called M), which is
11simply ahead of H. The index and the work tree contains a state that
12is derived from H, but may also have local changes. This test checks
13all the combinations described in the two-tree merge "carry forward"
14rules, found in <Documentation/git-rev-tree.txt>.
15
16In 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
25read_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"
34compare_change () {
35 cat current
36 sed -n >current \
37 -e '/^--- /d; /^+++ /d; /^@@ /d;' \
38 -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
39 "$1"
40 diff -u expected current
41}
42
43check_cache_at () {
44 clean_if_empty=`git-diff-files "$1"`
45 case "$clean_if_empty" in
46 '') echo "$1: clean" ;;
47 ?*) echo "$1: dirty" ;;
48 esac
49 case "$2,$clean_if_empty" in
50 clean,) : ;;
51 clean,?*) false ;;
52 dirty,) false ;;
53 dirty,?*) : ;;
54 esac
55}
56
57check_stages () {
58 cat >expected_stages
59 git-ls-files --stage | sed -e "s/ $_x40 / X /" >current_stages
60 diff -u expected_stages current_stages
61}
62
63test_expect_success \
64 setup \
65 'echo frotz >frotz &&
66 echo nitfol >nitfol &&
67 echo bozbar >bozbar &&
68 echo rezrov >rezrov &&
69 echo yomin >yomin &&
70 git-update-cache --add nitfol bozbar rezrov &&
71 treeH=`git-write-tree` &&
72 echo treeH $treeH &&
73 git-ls-tree $treeH &&
74
75 echo gnusto >bozbar &&
76 git-update-cache --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
83test_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 diff -u M.out 1-3.out &&
89 check_cache_at bozbar dirty &&
90 check_cache_at frotz clean && # different from pure 2-way
91 check_cache_at nitfol dirty'
92
93echo '+100644 X 0 yomin' >expected
94
95test_expect_success \
96 '4 - carry forward local addition.' \
97 'rm -f .git/index &&
98 git-update-cache --add yomin &&
99 read_tree_twoway $treeH $treeM &&
100 git-ls-files --stage >4.out || exit
101 diff -u M.out 4.out >4diff.out
102 compare_change 4diff.out expected &&
103 check_cache_at yomin clean'
104
105# "read-tree -m H I+H M" where !H && !M; so (I+H) not being up-to-date
106# should not matter, but without #3ALT this does not work.
107: test_expect_success \
108 '5 - carry forward local addition.' \
109 'rm -f .git/index &&
110 echo yomin >yomin &&
111 git-update-cache --add yomin &&
112 echo yomin yomin >yomin &&
113 read_tree_twoway $treeH $treeM &&
114 git-ls-files --stage >5.out || exit
115 diff -u M.out 5.out >5diff.out
116 compare_change 5diff.out expected &&
117 check_cache_at yomin dirty'
118
119# "read-tree -m H I+H M" where !H && M && (I+H) == M, so this should
120# succeed (even the entry is clean), but without #5ALT this does not
121# work.
122: test_expect_success \
123 '6 - local addition already has the same.' \
124 'rm -f .git/index &&
125 git-update-cache --add frotz &&
126 read_tree_twoway $treeH $treeM &&
127 git-ls-files --stage >6.out &&
128 diff -u M.out 6.out &&
129 check_cache_at frotz clean'
130
131# Exactly the same pattern as above but with dirty cache. This also
132# should succeed, but without #5ALT it does not.
133: test_expect_success \
134 '7 - local addition already has the same.' \
135 'rm -f .git/index &&
136 echo frotz >frotz &&
137 git-update-cache --add frotz &&
138 echo frotz frotz >frotz &&
139 read_tree_twoway $treeH $treeM &&
140 git-ls-files --stage >7.out &&
141 diff -u M.out 7.out &&
142 check_cache_at frotz dirty'
143
144test_expect_success \
145 '8 - conflicting addition.' \
146 'rm -f .git/index &&
147 echo frotz frotz >frotz &&
148 git-update-cache --add frotz &&
149 if read_tree_twoway $treeH $treeM; then false; else :; fi'
150
151test_expect_success \
152 '9 - conflicting addition.' \
153 'rm -f .git/index &&
154 echo frotz frotz >frotz &&
155 git-update-cache --add frotz &&
156 echo frotz >frotz &&
157 if read_tree_twoway $treeH $treeM; then false; else :; fi'
158
159test_expect_success \
160 '10 - path removed.' \
161 'rm -f .git/index &&
162 echo rezrov >rezrov &&
163 git-update-cache --add rezrov &&
164 read_tree_twoway $treeH $treeM &&
165 git-ls-files --stage >10.out &&
166 diff -u M.out 10.out'
167
168test_expect_success \
169 '11 - dirty path removed.' \
170 'rm -f .git/index &&
171 echo rezrov >rezrov &&
172 git-update-cache --add rezrov &&
173 echo rezrov rezrov >rezrov &&
174 if read_tree_twoway $treeH $treeM; then false; else :; fi'
175
176test_expect_success \
177 '12 - unmatching local changes being removed.' \
178 'rm -f .git/index &&
179 echo rezrov rezrov >rezrov &&
180 git-update-cache --add rezrov &&
181 if read_tree_twoway $treeH $treeM; then false; else :; fi'
182
183test_expect_success \
184 '13 - unmatching local changes being removed.' \
185 'rm -f .git/index &&
186 echo rezrov rezrov >rezrov &&
187 git-update-cache --add rezrov &&
188 echo rezrov >rezrov &&
189 if read_tree_twoway $treeH $treeM; then false; else :; fi'
190
191cat >expected <<EOF
192-100644 X 0 nitfol
193+100644 X 0 nitfol
194EOF
195
196test_expect_success \
197 '14 - unchanged in two heads.' \
198 'rm -f .git/index &&
199 echo nitfol nitfol >nitfol &&
200 git-update-cache --add nitfol &&
201 read_tree_twoway $treeH $treeM &&
202 git-ls-files --stage >14.out || exit
203 diff -u M.out 14.out >14diff.out
204 compare_change 14diff.out expected &&
205 check_cache_at nitfol clean'
206
207test_expect_success \
208 '15 - unchanged in two heads.' \
209 'rm -f .git/index &&
210 echo nitfol nitfol >nitfol &&
211 git-update-cache --add nitfol &&
212 echo nitfol nitfol nitfol >nitfol &&
213 read_tree_twoway $treeH $treeM &&
214 git-ls-files --stage >15.out || exit
215 diff -u M.out 15.out >15diff.out
216 compare_change 15diff.out expected &&
217 check_cache_at nitfol dirty'
218
219# This is different from straight 2-way merge in that it leaves
220# three stages of bozbar in the index file without failing, so
221# the user can run git-diff-stages to examine the situation.
222test_expect_success \
223 '16 - conflicting local change.' \
224 'rm -f .git/index &&
225 echo bozbar bozbar >bozbar &&
226 git-update-cache --add bozbar &&
227 git-read-tree --emu23 $treeH $treeM &&
228 check_stages' <<\EOF
229100644 X 1 bozbar
230100644 X 2 bozbar
231100644 X 3 bozbar
232100644 X 3 frotz
233100644 X 0 nitfol
234100644 X 1 rezrov
235100644 X 2 rezrov
236EOF
237
238test_expect_success \
239 '17 - conflicting local change.' \
240 'rm -f .git/index &&
241 echo bozbar bozbar >bozbar &&
242 git-update-cache --add bozbar &&
243 echo bozbar bozbar bozbar >bozbar &&
244 if read_tree_twoway $treeH $treeM; then false; else :; fi'
245
246test_expect_success \
247 '18 - local change already having a good result.' \
248 'rm -f .git/index &&
249 echo gnusto >bozbar &&
250 git-update-cache --add bozbar &&
251 read_tree_twoway $treeH $treeM &&
252 git-ls-files --stage >18.out &&
253 diff -u M.out 18.out &&
254 check_cache_at bozbar clean'
255
256test_expect_success \
257 '19 - local change already having a good result, further modified.' \
258 'rm -f .git/index &&
259 echo gnusto >bozbar &&
260 git-update-cache --add bozbar &&
261 echo gnusto gnusto >bozbar &&
262 read_tree_twoway $treeH $treeM &&
263 git-ls-files --stage >19.out &&
264 diff -u M.out 19.out &&
265 check_cache_at bozbar dirty'
266
267test_expect_success \
268 '20 - no local change, use new tree.' \
269 'rm -f .git/index &&
270 echo bozbar >bozbar &&
271 git-update-cache --add bozbar &&
272 read_tree_twoway $treeH $treeM &&
273 git-ls-files --stage >20.out &&
274 diff -u M.out 20.out &&
275 check_cache_at bozbar dirty'
276
277test_expect_success \
278 '21 - no local change, dirty cache.' \
279 'rm -f .git/index &&
280 echo bozbar >bozbar &&
281 git-update-cache --add bozbar &&
282 echo gnusto gnusto >bozbar &&
283 if read_tree_twoway $treeH $treeM; then false; else :; fi'
284
285# Also make sure we did not break DF vs DF/DF case.
286test_expect_success \
287 'DF vs DF/DF case setup.' \
288 'rm -f .git/index &&
289 echo DF >DF &&
290 git-update-cache --add DF &&
291 treeDF=`git-write-tree` &&
292 echo treeDF $treeDF &&
293 git-ls-tree $treeDF &&
294
295 rm -f DF &&
296 mkdir DF &&
297 echo DF/DF >DF/DF &&
298 git-update-cache --add --remove DF DF/DF &&
299 treeDFDF=`git-write-tree` &&
300 echo treeDFDF $treeDFDF &&
301 git-ls-tree $treeDFDF &&
302 git-ls-files --stage >DFDF.out'
303
304test_expect_success \
305 'DF vs DF/DF case test.' \
306 'rm -f .git/index &&
307 rm -fr DF &&
308 echo DF >DF &&
309 git-update-cache --add DF &&
310 read_tree_twoway $treeDF $treeDFDF &&
311 git-ls-files --stage >DFDFcheck.out &&
312 diff -u DFDF.out DFDFcheck.out &&
313 check_cache_at DF/DF clean && # different from pure 2-way
314 :'
315
316test_done