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), now thanks to #5ALT.
121 test_expect_success \
122 '6 - local addition already has the same.' \
123 'rm -f .git/index &&
124 git-update-cache --add frotz &&
125 read_tree_twoway $treeH $treeM &&
126 git-ls-files --stage >6.out &&
127 diff -u M.out 6.out &&
128 check_cache_at frotz clean'
130 # Exactly the same pattern as above but with dirty cache. This also
131 # should succeed, now thanks to #5ALT.
132 test_expect_success \
133 '7 - local addition already has the same.' \
134 'rm -f .git/index &&
135 echo frotz >frotz &&
136 git-update-cache --add frotz &&
137 echo frotz frotz >frotz &&
138 read_tree_twoway $treeH $treeM &&
139 git-ls-files --stage >7.out &&
140 diff -u M.out 7.out &&
141 check_cache_at frotz dirty'
143 test_expect_success \
144 '8 - conflicting addition.' \
145 'rm -f .git/index &&
146 echo frotz frotz >frotz &&
147 git-update-cache --add frotz &&
148 if read_tree_twoway $treeH $treeM; then false; else :; fi'
150 test_expect_success \
151 '9 - conflicting addition.' \
152 'rm -f .git/index &&
153 echo frotz frotz >frotz &&
154 git-update-cache --add frotz &&
155 echo frotz >frotz &&
156 if read_tree_twoway $treeH $treeM; then false; else :; fi'
158 test_expect_success \
159 '10 - path removed.' \
160 'rm -f .git/index &&
161 echo rezrov >rezrov &&
162 git-update-cache --add rezrov &&
163 read_tree_twoway $treeH $treeM &&
164 git-ls-files --stage >10.out &&
165 diff -u M.out 10.out'
167 test_expect_success \
168 '11 - dirty path removed.' \
169 'rm -f .git/index &&
170 echo rezrov >rezrov &&
171 git-update-cache --add rezrov &&
172 echo rezrov rezrov >rezrov &&
173 if read_tree_twoway $treeH $treeM; then false; else :; fi'
175 test_expect_success \
176 '12 - unmatching local changes being removed.' \
177 'rm -f .git/index &&
178 echo rezrov rezrov >rezrov &&
179 git-update-cache --add rezrov &&
180 if read_tree_twoway $treeH $treeM; then false; else :; fi'
182 test_expect_success \
183 '13 - unmatching local changes being removed.' \
184 'rm -f .git/index &&
185 echo rezrov rezrov >rezrov &&
186 git-update-cache --add rezrov &&
187 echo rezrov >rezrov &&
188 if read_tree_twoway $treeH $treeM; then false; else :; fi'
190 cat >expected <<EOF
191 -100644 X 0 nitfol
192 +100644 X 0 nitfol
193 EOF
195 test_expect_success \
196 '14 - unchanged in two heads.' \
197 'rm -f .git/index &&
198 echo nitfol nitfol >nitfol &&
199 git-update-cache --add nitfol &&
200 read_tree_twoway $treeH $treeM &&
201 git-ls-files --stage >14.out || exit
202 diff -u M.out 14.out >14diff.out
203 compare_change 14diff.out expected &&
204 check_cache_at nitfol clean'
206 test_expect_success \
207 '15 - unchanged in two heads.' \
208 'rm -f .git/index &&
209 echo nitfol nitfol >nitfol &&
210 git-update-cache --add nitfol &&
211 echo nitfol nitfol nitfol >nitfol &&
212 read_tree_twoway $treeH $treeM &&
213 git-ls-files --stage >15.out || exit
214 diff -u M.out 15.out >15diff.out
215 compare_change 15diff.out expected &&
216 check_cache_at nitfol dirty'
218 # This is different from straight 2-way merge in that it leaves
219 # three stages of bozbar in the index file without failing, so
220 # the user can run git-diff-stages to examine the situation.
221 test_expect_success \
222 '16 - conflicting local change.' \
223 'rm -f .git/index &&
224 echo bozbar bozbar >bozbar &&
225 git-update-cache --add bozbar &&
226 git-read-tree --emu23 $treeH $treeM &&
227 check_stages' <<\EOF
228 100644 X 1 bozbar
229 100644 X 2 bozbar
230 100644 X 3 bozbar
231 100644 X 3 frotz
232 100644 X 0 nitfol
233 100644 X 1 rezrov
234 100644 X 2 rezrov
235 EOF
237 test_expect_success \
238 '17 - conflicting local change.' \
239 'rm -f .git/index &&
240 echo bozbar bozbar >bozbar &&
241 git-update-cache --add bozbar &&
242 echo bozbar bozbar bozbar >bozbar &&
243 if read_tree_twoway $treeH $treeM; then false; else :; fi'
245 test_expect_success \
246 '18 - local change already having a good result.' \
247 'rm -f .git/index &&
248 echo gnusto >bozbar &&
249 git-update-cache --add bozbar &&
250 read_tree_twoway $treeH $treeM &&
251 git-ls-files --stage >18.out &&
252 diff -u M.out 18.out &&
253 check_cache_at bozbar clean'
255 test_expect_success \
256 '19 - local change already having a good result, further modified.' \
257 'rm -f .git/index &&
258 echo gnusto >bozbar &&
259 git-update-cache --add bozbar &&
260 echo gnusto gnusto >bozbar &&
261 read_tree_twoway $treeH $treeM &&
262 git-ls-files --stage >19.out &&
263 diff -u M.out 19.out &&
264 check_cache_at bozbar dirty'
266 test_expect_success \
267 '20 - no local change, use new tree.' \
268 'rm -f .git/index &&
269 echo bozbar >bozbar &&
270 git-update-cache --add bozbar &&
271 read_tree_twoway $treeH $treeM &&
272 git-ls-files --stage >20.out &&
273 diff -u M.out 20.out &&
274 check_cache_at bozbar dirty'
276 test_expect_success \
277 '21 - no local change, dirty cache.' \
278 'rm -f .git/index &&
279 echo bozbar >bozbar &&
280 git-update-cache --add bozbar &&
281 echo gnusto gnusto >bozbar &&
282 if read_tree_twoway $treeH $treeM; then false; else :; fi'
284 # Also make sure we did not break DF vs DF/DF case.
285 test_expect_success \
286 'DF vs DF/DF case setup.' \
287 'rm -f .git/index &&
288 echo DF >DF &&
289 git-update-cache --add DF &&
290 treeDF=`git-write-tree` &&
291 echo treeDF $treeDF &&
292 git-ls-tree $treeDF &&
294 rm -f DF &&
295 mkdir DF &&
296 echo DF/DF >DF/DF &&
297 git-update-cache --add --remove DF DF/DF &&
298 treeDFDF=`git-write-tree` &&
299 echo treeDFDF $treeDFDF &&
300 git-ls-tree $treeDFDF &&
301 git-ls-files --stage >DFDF.out'
303 test_expect_success \
304 'DF vs DF/DF case test.' \
305 'rm -f .git/index &&
306 rm -fr DF &&
307 echo DF >DF &&
308 git-update-cache --add DF &&
309 read_tree_twoway $treeDF $treeDFDF &&
310 git-ls-files --stage >DFDFcheck.out &&
311 diff -u DFDF.out DFDFcheck.out &&
312 check_cache_at DF/DF clean && # different from pure 2-way
313 :'
315 test_done