1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
6 test_description='Two way merge with read-tree --emu23 $H $M
8 This test tries two-way merge (aka fast forward with carry forward).
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>.
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
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 }
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 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 }
43 check_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 }
57 check_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 }
63 test_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 &&
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'
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 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'
93 echo '+100644 X 0 yomin' >expected
95 test_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'
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'
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'
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'
144 test_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'
151 test_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'
159 test_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'
168 test_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'
176 test_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'
183 test_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'
191 cat >expected <<EOF
192 -100644 X 0 nitfol
193 +100644 X 0 nitfol
194 EOF
196 test_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'
207 test_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'
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.
222 test_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
229 100644 X 1 bozbar
230 100644 X 2 bozbar
231 100644 X 3 bozbar
232 100644 X 3 frotz
233 100644 X 0 nitfol
234 100644 X 1 rezrov
235 100644 X 2 rezrov
236 EOF
238 test_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'
246 test_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'
256 test_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'
267 test_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'
277 test_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'
285 # Also make sure we did not break DF vs DF/DF case.
286 test_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 &&
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'
304 test_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 :'
316 test_done