]>
Commit | Line | Data |
---|---|---|
c94736a2 JH |
1 | #!/bin/sh |
2 | ||
695576fd | 3 | test_description='recursive merge corner cases involving criss-cross merges' |
c94736a2 JH |
4 | |
5 | . ./test-lib.sh | |
6 | ||
7 | # | |
8 | # L1 L2 | |
9 | # o---o | |
10 | # / \ / \ | |
11 | # o X ? | |
12 | # \ / \ / | |
13 | # o---o | |
14 | # R1 R2 | |
15 | # | |
16 | ||
c976260d | 17 | test_expect_success 'setup basic criss-cross + rename with no modifications' ' |
2a4c19ef EN |
18 | test_create_repo basic-rename && |
19 | ( | |
20 | cd basic-rename && | |
21 | ||
22 | ten="0 1 2 3 4 5 6 7 8 9" && | |
23 | for i in $ten | |
24 | do | |
25 | echo line $i in a sample file | |
26 | done >one && | |
27 | for i in $ten | |
28 | do | |
29 | echo line $i in another sample file | |
30 | done >two && | |
31 | git add one two && | |
32 | test_tick && git commit -m initial && | |
33 | ||
34 | git branch L1 && | |
35 | git checkout -b R1 && | |
36 | git mv one three && | |
37 | test_tick && git commit -m R1 && | |
38 | ||
39 | git checkout L1 && | |
40 | git mv two three && | |
41 | test_tick && git commit -m L1 && | |
42 | ||
43 | git checkout L1^0 && | |
44 | test_tick && git merge -s ours R1 && | |
45 | git tag L2 && | |
46 | ||
47 | git checkout R1^0 && | |
48 | test_tick && git merge -s ours L1 && | |
49 | git tag R2 | |
50 | ) | |
c94736a2 JH |
51 | ' |
52 | ||
c976260d | 53 | test_expect_success 'merge simple rename+criss-cross with no modifications' ' |
2a4c19ef EN |
54 | ( |
55 | cd basic-rename && | |
56 | ||
57 | git reset --hard && | |
58 | git checkout L2^0 && | |
c94736a2 | 59 | |
2a4c19ef | 60 | test_must_fail git merge -s recursive R2^0 && |
c976260d | 61 | |
0cdabc10 EN |
62 | git ls-files -s >out && |
63 | test_line_count = 2 out && | |
64 | git ls-files -u >out && | |
65 | test_line_count = 2 out && | |
66 | git ls-files -o >out && | |
bbafc9c4 | 67 | test_line_count = 1 out && |
c976260d | 68 | |
6ac767e5 | 69 | git rev-parse >expect \ |
6ac767e5 EN |
70 | L2:three R2:three && |
71 | git rev-parse >actual \ | |
72 | :2:three :3:three && | |
6ac767e5 | 73 | test_cmp expect actual |
2a4c19ef | 74 | ) |
c94736a2 JH |
75 | ' |
76 | ||
583942df EN |
77 | # |
78 | # Same as before, but modify L1 slightly: | |
79 | # | |
80 | # L1m L2 | |
81 | # o---o | |
82 | # / \ / \ | |
83 | # o X ? | |
84 | # \ / \ / | |
85 | # o---o | |
86 | # R1 R2 | |
87 | # | |
88 | ||
89 | test_expect_success 'setup criss-cross + rename merges with basic modification' ' | |
2a4c19ef EN |
90 | test_create_repo rename-modify && |
91 | ( | |
92 | cd rename-modify && | |
93 | ||
94 | ten="0 1 2 3 4 5 6 7 8 9" && | |
95 | for i in $ten | |
96 | do | |
97 | echo line $i in a sample file | |
98 | done >one && | |
99 | for i in $ten | |
100 | do | |
101 | echo line $i in another sample file | |
102 | done >two && | |
103 | git add one two && | |
104 | test_tick && git commit -m initial && | |
105 | ||
106 | git branch L1 && | |
107 | git checkout -b R1 && | |
108 | git mv one three && | |
109 | echo more >>two && | |
110 | git add two && | |
111 | test_tick && git commit -m R1 && | |
112 | ||
113 | git checkout L1 && | |
114 | git mv two three && | |
115 | test_tick && git commit -m L1 && | |
116 | ||
117 | git checkout L1^0 && | |
118 | test_tick && git merge -s ours R1 && | |
119 | git tag L2 && | |
120 | ||
121 | git checkout R1^0 && | |
122 | test_tick && git merge -s ours L1 && | |
123 | git tag R2 | |
124 | ) | |
583942df EN |
125 | ' |
126 | ||
2a669c34 | 127 | test_expect_success 'merge criss-cross + rename merges with basic modification' ' |
2a4c19ef EN |
128 | ( |
129 | cd rename-modify && | |
130 | ||
131 | git checkout L2^0 && | |
583942df | 132 | |
2a4c19ef | 133 | test_must_fail git merge -s recursive R2^0 && |
583942df | 134 | |
0cdabc10 EN |
135 | git ls-files -s >out && |
136 | test_line_count = 2 out && | |
137 | git ls-files -u >out && | |
138 | test_line_count = 2 out && | |
139 | git ls-files -o >out && | |
bbafc9c4 | 140 | test_line_count = 1 out && |
583942df | 141 | |
6ac767e5 | 142 | git rev-parse >expect \ |
6ac767e5 EN |
143 | L2:three R2:three && |
144 | git rev-parse >actual \ | |
145 | :2:three :3:three && | |
6ac767e5 | 146 | test_cmp expect actual |
2a4c19ef | 147 | ) |
583942df EN |
148 | ' |
149 | ||
f63622c0 EN |
150 | # |
151 | # For the next test, we start with three commits in two lines of development | |
152 | # which setup a rename/add conflict: | |
153 | # Commit A: File 'a' exists | |
154 | # Commit B: Rename 'a' -> 'new_a' | |
155 | # Commit C: Modify 'a', create different 'new_a' | |
156 | # Later, two different people merge and resolve differently: | |
157 | # Commit D: Merge B & C, ignoring separately created 'new_a' | |
158 | # Commit E: Merge B & C making use of some piece of secondary 'new_a' | |
159 | # Finally, someone goes to merge D & E. Does git detect the conflict? | |
160 | # | |
161 | # B D | |
162 | # o---o | |
163 | # / \ / \ | |
164 | # A o X ? F | |
165 | # \ / \ / | |
166 | # o---o | |
167 | # C E | |
168 | # | |
169 | ||
170 | test_expect_success 'setup differently handled merges of rename/add conflict' ' | |
2a4c19ef EN |
171 | test_create_repo rename-add && |
172 | ( | |
173 | cd rename-add && | |
174 | ||
175 | printf "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n" >a && | |
176 | git add a && | |
177 | test_tick && git commit -m A && | |
178 | ||
179 | git branch B && | |
180 | git checkout -b C && | |
181 | echo 10 >>a && | |
7f867165 | 182 | test_write_lines 0 1 2 3 4 5 6 7 foobar >new_a && |
2a4c19ef EN |
183 | git add a new_a && |
184 | test_tick && git commit -m C && | |
185 | ||
186 | git checkout B && | |
187 | git mv a new_a && | |
188 | test_tick && git commit -m B && | |
189 | ||
190 | git checkout B^0 && | |
191 | test_must_fail git merge C && | |
7f867165 EN |
192 | git show :2:new_a >new_a && |
193 | git add new_a && | |
2a4c19ef EN |
194 | test_tick && git commit -m D && |
195 | git tag D && | |
196 | ||
197 | git checkout C^0 && | |
198 | test_must_fail git merge B && | |
7f867165 | 199 | test_write_lines 0 1 2 3 4 5 6 7 bad_merge >new_a && |
2a4c19ef EN |
200 | git add -u && |
201 | test_tick && git commit -m E && | |
202 | git tag E | |
203 | ) | |
f63622c0 EN |
204 | ' |
205 | ||
2a669c34 | 206 | test_expect_success 'git detects differently handled merges conflict' ' |
2a4c19ef EN |
207 | ( |
208 | cd rename-add && | |
209 | ||
210 | git checkout D^0 && | |
211 | ||
212 | test_must_fail git merge -s recursive E^0 && | |
213 | ||
0cdabc10 EN |
214 | git ls-files -s >out && |
215 | test_line_count = 3 out && | |
216 | git ls-files -u >out && | |
217 | test_line_count = 3 out && | |
218 | git ls-files -o >out && | |
219 | test_line_count = 1 out && | |
2a4c19ef | 220 | |
6ac767e5 | 221 | git rev-parse >expect \ |
7f867165 | 222 | C:new_a D:new_a E:new_a && |
6ac767e5 | 223 | git rev-parse >actual \ |
7f867165 | 224 | :1:new_a :2:new_a :3:new_a && |
c8ce3763 | 225 | test_cmp expect actual && |
2a4c19ef | 226 | |
7f867165 EN |
227 | # Test that the two-way merge in new_a is as expected |
228 | git cat-file -p D:new_a >ours && | |
229 | git cat-file -p E:new_a >theirs && | |
2a4c19ef EN |
230 | >empty && |
231 | test_must_fail git merge-file \ | |
7f867165 | 232 | -L "HEAD" \ |
4f445453 | 233 | -L "" \ |
7f867165 | 234 | -L "E^0" \ |
6ac767e5 EN |
235 | ours empty theirs && |
236 | sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect && | |
7f867165 EN |
237 | git hash-object new_a >actual && |
238 | git hash-object ours >expect && | |
6ac767e5 | 239 | test_cmp expect actual |
2a4c19ef | 240 | ) |
c94736a2 JH |
241 | ' |
242 | ||
b8cd1bb7 EN |
243 | # Repeat the above testcase with precisely the same setup, other than with |
244 | # the two merge bases having different orderings of commit timestamps so | |
245 | # that they are reversed in the order they are provided to merge-recursive, | |
246 | # so that we can improve code coverage. | |
247 | test_expect_success 'git detects differently handled merges conflict, swapped' ' | |
248 | ( | |
249 | cd rename-add && | |
250 | ||
251 | # Difference #1: Do cleanup from previous testrun | |
252 | git reset --hard && | |
253 | git clean -fdqx && | |
254 | ||
255 | # Difference #2: Change commit timestamps | |
256 | btime=$(git log --no-walk --date=raw --format=%cd B | awk "{print \$1}") && | |
257 | ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") && | |
258 | newctime=$(($btime+1)) && | |
259 | git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet && | |
260 | # End of differences; rest is copy-paste of last test | |
261 | ||
262 | git checkout D^0 && | |
263 | test_must_fail git merge -s recursive E^0 && | |
264 | ||
265 | git ls-files -s >out && | |
266 | test_line_count = 3 out && | |
267 | git ls-files -u >out && | |
268 | test_line_count = 3 out && | |
269 | git ls-files -o >out && | |
270 | test_line_count = 1 out && | |
271 | ||
272 | git rev-parse >expect \ | |
273 | C:new_a D:new_a E:new_a && | |
274 | git rev-parse >actual \ | |
275 | :1:new_a :2:new_a :3:new_a && | |
276 | test_cmp expect actual && | |
277 | ||
278 | # Test that the two-way merge in new_a is as expected | |
279 | git cat-file -p D:new_a >ours && | |
280 | git cat-file -p E:new_a >theirs && | |
281 | >empty && | |
282 | test_must_fail git merge-file \ | |
283 | -L "HEAD" \ | |
284 | -L "" \ | |
285 | -L "E^0" \ | |
286 | ours empty theirs && | |
287 | sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect && | |
288 | git hash-object new_a >actual && | |
289 | git hash-object ours >expect && | |
290 | test_cmp expect actual | |
291 | ) | |
292 | ' | |
293 | ||
fe7e9c23 EN |
294 | # |
295 | # criss-cross + modify/delete: | |
296 | # | |
297 | # B D | |
298 | # o---o | |
299 | # / \ / \ | |
300 | # A o X ? F | |
301 | # \ / \ / | |
302 | # o---o | |
303 | # C E | |
304 | # | |
305 | # Commit A: file with contents 'A\n' | |
306 | # Commit B: file with contents 'B\n' | |
307 | # Commit C: file not present | |
308 | # Commit D: file with contents 'B\n' | |
309 | # Commit E: file not present | |
310 | # | |
311 | # Merging commits D & E should result in modify/delete conflict. | |
312 | ||
313 | test_expect_success 'setup criss-cross + modify/delete resolved differently' ' | |
2a4c19ef EN |
314 | test_create_repo modify-delete && |
315 | ( | |
316 | cd modify-delete && | |
317 | ||
318 | echo A >file && | |
319 | git add file && | |
320 | test_tick && | |
321 | git commit -m A && | |
322 | ||
323 | git branch B && | |
324 | git checkout -b C && | |
325 | git rm file && | |
326 | test_tick && | |
327 | git commit -m C && | |
328 | ||
329 | git checkout B && | |
330 | echo B >file && | |
331 | git add file && | |
332 | test_tick && | |
333 | git commit -m B && | |
334 | ||
335 | git checkout B^0 && | |
336 | test_must_fail git merge C && | |
337 | echo B >file && | |
338 | git add file && | |
339 | test_tick && | |
340 | git commit -m D && | |
341 | git tag D && | |
342 | ||
343 | git checkout C^0 && | |
344 | test_must_fail git merge B && | |
345 | git rm file && | |
346 | test_tick && | |
347 | git commit -m E && | |
348 | git tag E | |
349 | ) | |
fe7e9c23 EN |
350 | ' |
351 | ||
ec61d149 | 352 | test_expect_success 'git detects conflict merging criss-cross+modify/delete' ' |
2a4c19ef EN |
353 | ( |
354 | cd modify-delete && | |
355 | ||
356 | git checkout D^0 && | |
fe7e9c23 | 357 | |
2a4c19ef | 358 | test_must_fail git merge -s recursive E^0 && |
fe7e9c23 | 359 | |
0cdabc10 EN |
360 | git ls-files -s >out && |
361 | test_line_count = 2 out && | |
362 | git ls-files -u >out && | |
363 | test_line_count = 2 out && | |
fe7e9c23 | 364 | |
6ac767e5 EN |
365 | git rev-parse >expect \ |
366 | master:file B:file && | |
367 | git rev-parse >actual \ | |
368 | :1:file :2:file && | |
369 | test_cmp expect actual | |
2a4c19ef | 370 | ) |
fe7e9c23 EN |
371 | ' |
372 | ||
ec61d149 | 373 | test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' ' |
2a4c19ef EN |
374 | ( |
375 | cd modify-delete && | |
376 | ||
377 | git reset --hard && | |
378 | git checkout E^0 && | |
fe7e9c23 | 379 | |
2a4c19ef | 380 | test_must_fail git merge -s recursive D^0 && |
fe7e9c23 | 381 | |
0cdabc10 EN |
382 | git ls-files -s >out && |
383 | test_line_count = 2 out && | |
384 | git ls-files -u >out && | |
385 | test_line_count = 2 out && | |
fe7e9c23 | 386 | |
6ac767e5 EN |
387 | git rev-parse >expect \ |
388 | master:file B:file && | |
389 | git rev-parse >actual \ | |
390 | :1:file :3:file && | |
391 | test_cmp expect actual | |
2a4c19ef | 392 | ) |
fe7e9c23 EN |
393 | ' |
394 | ||
327ac9cb | 395 | # SORRY FOR THE SUPER LONG DESCRIPTION, BUT THIS NEXT ONE IS HAIRY |
827f2b7d EN |
396 | # |
397 | # criss-cross + d/f conflict via add/add: | |
235e8d59 | 398 | # Commit A: Neither file 'a' nor directory 'a/' exists. |
827f2b7d EN |
399 | # Commit B: Introduce 'a' |
400 | # Commit C: Introduce 'a/file' | |
327ac9cb | 401 | # Commit D1: Merge B & C, keeping 'a' and deleting 'a/' |
827f2b7d | 402 | # Commit E1: Merge B & C, deleting 'a' but keeping 'a/file' |
827f2b7d | 403 | # |
327ac9cb | 404 | # B D1 or D2 |
827f2b7d EN |
405 | # o---o |
406 | # / \ / \ | |
407 | # A o X ? F | |
408 | # \ / \ / | |
409 | # o---o | |
327ac9cb EN |
410 | # C E1 or E2 or E3 |
411 | # | |
412 | # I'll describe D2, E2, & E3 (which are alternatives for D1 & E1) more below... | |
413 | # | |
414 | # Merging D1 & E1 requires we first create a virtual merge base X from | |
415 | # merging A & B in memory. There are several possibilities for the merge-base: | |
416 | # 1: Keep both 'a' and 'a/file' (assuming crazy filesystem allowing a tree | |
417 | # with a directory and file at same path): results in merge of D1 & E1 | |
418 | # being clean with both files deleted. Bad (no conflict detected). | |
419 | # 2: Keep 'a' but not 'a/file': Merging D1 & E1 is clean and matches E1. Bad. | |
420 | # 3: Keep 'a/file' but not 'a': Merging D1 & E1 is clean and matches D1. Bad. | |
421 | # 4: Keep neither file: Merging D1 & E1 reports the D/F add/add conflict. | |
422 | # | |
423 | # So 4 sounds good for this case, but if we were to merge D1 & E3, where E3 | |
424 | # is defined as: | |
425 | # Commit E3: Merge B & C, keeping modified a, and deleting a/ | |
426 | # then we'd get an add/add conflict for 'a', which seems suboptimal. A little | |
427 | # creativity leads us to an alternate choice: | |
428 | # 5: Keep 'a' as 'a~$UNIQUE' and a/file; results: | |
429 | # Merge D1 & E1: rename/delete conflict for 'a'; a/file silently deleted | |
430 | # Merge D1 & E3 is clean, as expected. | |
431 | # | |
432 | # So choice 5 at least provides some kind of conflict for the original case, | |
433 | # and can merge cleanly as expected with D1 and E3. It also made things just | |
434 | # slightly funny for merging D1 and e$, where E4 is defined as: | |
435 | # Commit E4: Merge B & C, modifying 'a' and renaming to 'a2', and deleting 'a/' | |
436 | # in this case, we'll get a rename/rename(1to2) conflict because a~$UNIQUE | |
437 | # gets renamed to 'a' in D1 and to 'a2' in E4. But that's better than having | |
438 | # two files (both 'a' and 'a2') sitting around without the user being notified | |
439 | # that we could detect they were related and need to be merged. Also, choice | |
440 | # 5 makes the handling of 'a/file' seem suboptimal. What if we were to merge | |
441 | # D2 and E4, where D2 is: | |
442 | # Commit D2: Merge B & C, renaming 'a'->'a2', keeping 'a/file' | |
443 | # This would result in a clean merge with 'a2' having three-way merged | |
444 | # contents (good), and deleting 'a/' (bad) -- it doesn't detect the | |
445 | # conflict in how the different sides treated a/file differently. | |
446 | # Continuing down the creative route: | |
447 | # 6: Keep 'a' as 'a~$UNIQUE1' and keep 'a/' as 'a~$UNIQUE2/'; results: | |
448 | # Merge D1 & E1: rename/delete conflict for 'a' and each path under 'a/'. | |
449 | # Merge D1 & E3: clean, as expected. | |
450 | # Merge D1 & E4: rename/rename(1to2) conflict on 'a' vs 'a2'. | |
451 | # Merge D2 & E4: clean for 'a2', rename/delete for a/file | |
827f2b7d | 452 | # |
327ac9cb EN |
453 | # Choice 6 could cause rename detection to take longer (providing more targets |
454 | # that need to be searched). Also, the conflict message for each path under | |
455 | # 'a/' might be annoying unless we can detect it at the directory level, print | |
456 | # it once, and then suppress it for individual filepaths underneath. | |
827f2b7d | 457 | # |
827f2b7d | 458 | # |
327ac9cb EN |
459 | # As of time of writing, git uses choice 5. Directory rename detection and |
460 | # rename detection performance improvements might make choice 6 a desirable | |
461 | # improvement. But we can at least document where we fall short for now... | |
462 | # | |
463 | # | |
464 | # Historically, this testcase also used: | |
465 | # Commit E2: Merge B & C, deleting 'a' but keeping slightly modified 'a/file' | |
466 | # The merge of D1 & E2 is very similar to D1 & E1 -- it has similar issues for | |
467 | # path 'a', but should always result in a modify/delete conflict for path | |
468 | # 'a/file'. These tests ran the two merges | |
469 | # D1 & E1 | |
470 | # D1 & E2 | |
471 | # in both directions, to check for directional issues with D/F conflict | |
472 | # handling. Later we added | |
473 | # D1 & E3 | |
474 | # D1 & E4 | |
475 | # D2 & E4 | |
476 | # for good measure, though we only ran those one way because we had pretty | |
477 | # good confidence in merge-recursive's directional handling of D/F issues. | |
478 | # | |
479 | # Just to summarize all the intermediate merge commits: | |
480 | # Commit D1: Merge B & C, keeping a and deleting a/ | |
481 | # Commit D2: Merge B & C, renaming a->a2, keeping a/file | |
482 | # Commit E1: Merge B & C, deleting a but keeping a/file | |
483 | # Commit E2: Merge B & C, deleting a but keeping slightly modified a/file | |
484 | # Commit E3: Merge B & C, keeping modified a, and deleting a/ | |
485 | # Commit E4: Merge B & C, modifying 'a' and renaming to 'a2', and deleting 'a/' | |
827f2b7d EN |
486 | # |
487 | ||
488 | test_expect_success 'setup differently handled merges of directory/file conflict' ' | |
2a4c19ef EN |
489 | test_create_repo directory-file && |
490 | ( | |
491 | cd directory-file && | |
492 | ||
493 | >ignore-me && | |
494 | git add ignore-me && | |
495 | test_tick && | |
496 | git commit -m A && | |
497 | git tag A && | |
498 | ||
499 | git branch B && | |
500 | git checkout -b C && | |
501 | mkdir a && | |
327ac9cb | 502 | test_write_lines a b c d e f g >a/file && |
2a4c19ef EN |
503 | git add a/file && |
504 | test_tick && | |
505 | git commit -m C && | |
506 | ||
507 | git checkout B && | |
327ac9cb | 508 | test_write_lines 1 2 3 4 5 6 7 >a && |
2a4c19ef EN |
509 | git add a && |
510 | test_tick && | |
511 | git commit -m B && | |
512 | ||
513 | git checkout B^0 && | |
327ac9cb EN |
514 | git merge -s ours -m D1 C^0 && |
515 | git tag D1 && | |
516 | ||
517 | git checkout B^0 && | |
518 | test_must_fail git merge C^0 && | |
519 | git clean -fd && | |
520 | git rm -rf a/ && | |
521 | git rm a && | |
522 | git cat-file -p B:a >a2 && | |
523 | git add a2 && | |
524 | git commit -m D2 && | |
525 | git tag D2 && | |
2a4c19ef EN |
526 | |
527 | git checkout C^0 && | |
327ac9cb | 528 | git merge -s ours -m E1 B^0 && |
2a4c19ef EN |
529 | git tag E1 && |
530 | ||
531 | git checkout C^0 && | |
327ac9cb EN |
532 | git merge -s ours -m E2 B^0 && |
533 | test_write_lines a b c d e f g h >a/file && | |
2a4c19ef | 534 | git add a/file && |
327ac9cb EN |
535 | git commit --amend -C HEAD && |
536 | git tag E2 && | |
537 | ||
538 | git checkout C^0 && | |
539 | test_must_fail git merge B^0 && | |
540 | git clean -fd && | |
541 | git rm -rf a/ && | |
542 | test_write_lines 1 2 3 4 5 6 7 8 >a && | |
543 | git add a && | |
544 | git commit -m E3 && | |
6b82db9b | 545 | git tag E3 && |
327ac9cb EN |
546 | |
547 | git checkout C^0 && | |
548 | test_must_fail git merge B^0 && | |
549 | git clean -fd && | |
550 | git rm -rf a/ && | |
551 | git rm a && | |
552 | test_write_lines 1 2 3 4 5 6 7 8 >a2 && | |
553 | git add a2 && | |
554 | git commit -m E4 && | |
555 | git tag E4 | |
2a4c19ef | 556 | ) |
827f2b7d EN |
557 | ' |
558 | ||
327ac9cb | 559 | test_expect_success 'merge of D1 & E1 fails but has appropriate contents' ' |
d43eba0a EN |
560 | test_when_finished "git -C directory-file reset --hard" && |
561 | test_when_finished "git -C directory-file clean -fdqx" && | |
2a4c19ef EN |
562 | ( |
563 | cd directory-file && | |
827f2b7d | 564 | |
327ac9cb | 565 | git checkout D1^0 && |
827f2b7d | 566 | |
2a4c19ef | 567 | test_must_fail git merge -s recursive E1^0 && |
827f2b7d | 568 | |
0cdabc10 EN |
569 | git ls-files -s >out && |
570 | test_line_count = 2 out && | |
571 | git ls-files -u >out && | |
572 | test_line_count = 1 out && | |
573 | git ls-files -o >out && | |
574 | test_line_count = 1 out && | |
2a4c19ef | 575 | |
6ac767e5 EN |
576 | git rev-parse >expect \ |
577 | A:ignore-me B:a && | |
578 | git rev-parse >actual \ | |
579 | :0:ignore-me :2:a && | |
580 | test_cmp expect actual | |
2a4c19ef | 581 | ) |
827f2b7d EN |
582 | ' |
583 | ||
327ac9cb | 584 | test_expect_success 'merge of E1 & D1 fails but has appropriate contents' ' |
d43eba0a EN |
585 | test_when_finished "git -C directory-file reset --hard" && |
586 | test_when_finished "git -C directory-file clean -fdqx" && | |
2a4c19ef EN |
587 | ( |
588 | cd directory-file && | |
589 | ||
d43eba0a | 590 | git checkout E1^0 && |
827f2b7d | 591 | |
327ac9cb | 592 | test_must_fail git merge -s recursive D1^0 && |
827f2b7d | 593 | |
0cdabc10 EN |
594 | git ls-files -s >out && |
595 | test_line_count = 2 out && | |
596 | git ls-files -u >out && | |
597 | test_line_count = 1 out && | |
598 | git ls-files -o >out && | |
599 | test_line_count = 1 out && | |
827f2b7d | 600 | |
6ac767e5 EN |
601 | git rev-parse >expect \ |
602 | A:ignore-me B:a && | |
603 | git rev-parse >actual \ | |
604 | :0:ignore-me :3:a && | |
605 | test_cmp expect actual | |
2a4c19ef | 606 | ) |
827f2b7d EN |
607 | ' |
608 | ||
327ac9cb | 609 | test_expect_success 'merge of D1 & E2 fails but has appropriate contents' ' |
d43eba0a EN |
610 | test_when_finished "git -C directory-file reset --hard" && |
611 | test_when_finished "git -C directory-file clean -fdqx" && | |
2a4c19ef EN |
612 | ( |
613 | cd directory-file && | |
614 | ||
327ac9cb | 615 | git checkout D1^0 && |
827f2b7d | 616 | |
2a4c19ef | 617 | test_must_fail git merge -s recursive E2^0 && |
827f2b7d | 618 | |
0cdabc10 EN |
619 | git ls-files -s >out && |
620 | test_line_count = 4 out && | |
621 | git ls-files -u >out && | |
622 | test_line_count = 3 out && | |
623 | git ls-files -o >out && | |
624 | test_line_count = 2 out && | |
827f2b7d | 625 | |
6ac767e5 | 626 | git rev-parse >expect \ |
f1e12398 | 627 | B:a E2:a/file C:a/file A:ignore-me && |
6ac767e5 EN |
628 | git rev-parse >actual \ |
629 | :2:a :3:a/file :1:a/file :0:ignore-me && | |
f1e12398 | 630 | test_cmp expect actual && |
827f2b7d | 631 | |
5b0b9712 | 632 | test_path_is_file a~HEAD |
2a4c19ef | 633 | ) |
827f2b7d EN |
634 | ' |
635 | ||
327ac9cb | 636 | test_expect_success 'merge of E2 & D1 fails but has appropriate contents' ' |
d43eba0a EN |
637 | test_when_finished "git -C directory-file reset --hard" && |
638 | test_when_finished "git -C directory-file clean -fdqx" && | |
2a4c19ef EN |
639 | ( |
640 | cd directory-file && | |
827f2b7d | 641 | |
d43eba0a | 642 | git checkout E2^0 && |
827f2b7d | 643 | |
327ac9cb | 644 | test_must_fail git merge -s recursive D1^0 && |
827f2b7d | 645 | |
0cdabc10 EN |
646 | git ls-files -s >out && |
647 | test_line_count = 4 out && | |
648 | git ls-files -u >out && | |
649 | test_line_count = 3 out && | |
650 | git ls-files -o >out && | |
651 | test_line_count = 2 out && | |
827f2b7d | 652 | |
6ac767e5 | 653 | git rev-parse >expect \ |
f1e12398 | 654 | B:a E2:a/file C:a/file A:ignore-me && |
6ac767e5 EN |
655 | git rev-parse >actual \ |
656 | :3:a :2:a/file :1:a/file :0:ignore-me && | |
f1e12398 | 657 | test_cmp expect actual && |
2a4c19ef | 658 | |
327ac9cb EN |
659 | test_path_is_file a~D1^0 |
660 | ) | |
661 | ' | |
662 | ||
663 | test_expect_success 'merge of D1 & E3 succeeds' ' | |
664 | test_when_finished "git -C directory-file reset --hard" && | |
665 | test_when_finished "git -C directory-file clean -fdqx" && | |
666 | ( | |
667 | cd directory-file && | |
668 | ||
669 | git checkout D1^0 && | |
670 | ||
671 | git merge -s recursive E3^0 && | |
672 | ||
673 | git ls-files -s >out && | |
674 | test_line_count = 2 out && | |
675 | git ls-files -u >out && | |
676 | test_line_count = 0 out && | |
677 | git ls-files -o >out && | |
678 | test_line_count = 1 out && | |
679 | ||
680 | git rev-parse >expect \ | |
681 | A:ignore-me E3:a && | |
682 | git rev-parse >actual \ | |
683 | :0:ignore-me :0:a && | |
684 | test_cmp expect actual | |
685 | ) | |
686 | ' | |
687 | ||
688 | test_expect_success 'merge of D1 & E4 notifies user a and a2 are related' ' | |
689 | test_when_finished "git -C directory-file reset --hard" && | |
690 | test_when_finished "git -C directory-file clean -fdqx" && | |
691 | ( | |
692 | cd directory-file && | |
693 | ||
694 | git checkout D1^0 && | |
695 | ||
696 | test_must_fail git merge -s recursive E4^0 && | |
697 | ||
698 | git ls-files -s >out && | |
699 | test_line_count = 4 out && | |
700 | git ls-files -u >out && | |
701 | test_line_count = 3 out && | |
702 | git ls-files -o >out && | |
703 | test_line_count = 1 out && | |
704 | ||
705 | git rev-parse >expect \ | |
706 | A:ignore-me B:a D1:a E4:a2 && | |
707 | git rev-parse >actual \ | |
708 | :0:ignore-me :1:a~Temporary\ merge\ branch\ 2 :2:a :3:a2 && | |
709 | test_cmp expect actual | |
710 | ) | |
711 | ' | |
712 | ||
713 | test_expect_failure 'merge of D2 & E4 merges a2s & reports conflict for a/file' ' | |
714 | test_when_finished "git -C directory-file reset --hard" && | |
715 | test_when_finished "git -C directory-file clean -fdqx" && | |
716 | ( | |
717 | cd directory-file && | |
718 | ||
719 | git checkout D2^0 && | |
720 | ||
721 | test_must_fail git merge -s recursive E4^0 && | |
722 | ||
723 | git ls-files -s >out && | |
724 | test_line_count = 3 out && | |
725 | git ls-files -u >out && | |
726 | test_line_count = 1 out && | |
727 | git ls-files -o >out && | |
728 | test_line_count = 1 out && | |
729 | ||
730 | git rev-parse >expect \ | |
731 | A:ignore-me E4:a2 D2:a/file && | |
732 | git rev-parse >actual \ | |
733 | :0:ignore-me :0:a2 :2:a/file && | |
734 | test_cmp expect actual | |
2a4c19ef | 735 | ) |
827f2b7d EN |
736 | ' |
737 | ||
a0d33116 EN |
738 | # |
739 | # criss-cross with rename/rename(1to2)/modify followed by | |
740 | # rename/rename(2to1)/modify: | |
741 | # | |
742 | # B D | |
743 | # o---o | |
744 | # / \ / \ | |
745 | # A o X ? F | |
746 | # \ / \ / | |
747 | # o---o | |
748 | # C E | |
749 | # | |
750 | # Commit A: new file: a | |
751 | # Commit B: rename a->b, modifying by adding a line | |
752 | # Commit C: rename a->c | |
753 | # Commit D: merge B&C, resolving conflict by keeping contents in newname | |
754 | # Commit E: merge B&C, resolving conflict similar to D but adding another line | |
755 | # | |
756 | # There is a conflict merging B & C, but one of filename not of file | |
757 | # content. Whoever created D and E chose specific resolutions for that | |
758 | # conflict resolution. Now, since: (1) there is no content conflict | |
759 | # merging B & C, (2) D does not modify that merged content further, and (3) | |
760 | # both D & E resolve the name conflict in the same way, the modification to | |
761 | # newname in E should not cause any conflicts when it is merged with D. | |
762 | # (Note that this can be accomplished by having the virtual merge base have | |
763 | # the merged contents of b and c stored in a file named a, which seems like | |
764 | # the most logical choice anyway.) | |
765 | # | |
766 | # Comment from Junio: I do not necessarily agree with the choice "a", but | |
767 | # it feels sound to say "B and C do not agree what the final pathname | |
768 | # should be, but we know this content was derived from the common A:a so we | |
769 | # use one path whose name is arbitrary in the virtual merge base X between | |
770 | # D and E" and then further let the rename detection to notice that that | |
771 | # arbitrary path gets renamed between X-D to "newname" and X-E also to | |
772 | # "newname" to resolve it as both sides renaming it to the same new | |
773 | # name. It is akin to what we do at the content level, i.e. "B and C do not | |
774 | # agree what the final contents should be, so we leave the conflict marker | |
775 | # but that may cancel out at the final merge stage". | |
776 | ||
777 | test_expect_success 'setup rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' ' | |
2a4c19ef EN |
778 | test_create_repo rename-squared-squared && |
779 | ( | |
780 | cd rename-squared-squared && | |
781 | ||
782 | printf "1\n2\n3\n4\n5\n6\n" >a && | |
783 | git add a && | |
784 | git commit -m A && | |
785 | git tag A && | |
786 | ||
787 | git checkout -b B A && | |
788 | git mv a b && | |
789 | echo 7 >>b && | |
790 | git add -u && | |
791 | git commit -m B && | |
792 | ||
793 | git checkout -b C A && | |
794 | git mv a c && | |
795 | git commit -m C && | |
796 | ||
797 | git checkout -q B^0 && | |
798 | git merge --no-commit -s ours C^0 && | |
799 | git mv b newname && | |
800 | git commit -m "Merge commit C^0 into HEAD" && | |
801 | git tag D && | |
802 | ||
803 | git checkout -q C^0 && | |
804 | git merge --no-commit -s ours B^0 && | |
805 | git mv c newname && | |
806 | printf "7\n8\n" >>newname && | |
807 | git add -u && | |
808 | git commit -m "Merge commit B^0 into HEAD" && | |
809 | git tag E | |
810 | ) | |
a0d33116 EN |
811 | ' |
812 | ||
c52ff85d | 813 | test_expect_success 'handle rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' ' |
2a4c19ef EN |
814 | ( |
815 | cd rename-squared-squared && | |
a0d33116 | 816 | |
2a4c19ef | 817 | git checkout D^0 && |
a0d33116 | 818 | |
2a4c19ef | 819 | git merge -s recursive E^0 && |
a0d33116 | 820 | |
0cdabc10 EN |
821 | git ls-files -s >out && |
822 | test_line_count = 1 out && | |
823 | git ls-files -u >out && | |
824 | test_line_count = 0 out && | |
825 | git ls-files -o >out && | |
826 | test_line_count = 1 out && | |
2a4c19ef EN |
827 | |
828 | test $(git rev-parse HEAD:newname) = $(git rev-parse E:newname) | |
829 | ) | |
a0d33116 EN |
830 | ' |
831 | ||
0b35deb3 EN |
832 | # |
833 | # criss-cross with rename/rename(1to2)/add-source + resolvable modify/modify: | |
834 | # | |
835 | # B D | |
836 | # o---o | |
837 | # / \ / \ | |
838 | # A o X ? F | |
839 | # \ / \ / | |
840 | # o---o | |
841 | # C E | |
842 | # | |
843 | # Commit A: new file: a | |
844 | # Commit B: rename a->b | |
845 | # Commit C: rename a->c, add different a | |
846 | # Commit D: merge B&C, keeping b&c and (new) a modified at beginning | |
847 | # Commit E: merge B&C, keeping b&c and (new) a modified at end | |
848 | # | |
849 | # Merging commits D & E should result in no conflict; doing so correctly | |
850 | # requires getting the virtual merge base (from merging B&C) right, handling | |
851 | # renaming carefully (both in the virtual merge base and later), and getting | |
852 | # content merge handled. | |
853 | ||
2a4c19ef EN |
854 | test_expect_success 'setup criss-cross + rename/rename/add-source + modify/modify' ' |
855 | test_create_repo rename-rename-add-source && | |
856 | ( | |
857 | cd rename-rename-add-source && | |
858 | ||
859 | printf "lots\nof\nwords\nand\ncontent\n" >a && | |
860 | git add a && | |
861 | git commit -m A && | |
862 | git tag A && | |
863 | ||
864 | git checkout -b B A && | |
865 | git mv a b && | |
866 | git commit -m B && | |
867 | ||
868 | git checkout -b C A && | |
869 | git mv a c && | |
870 | printf "2\n3\n4\n5\n6\n7\n" >a && | |
871 | git add a && | |
872 | git commit -m C && | |
873 | ||
874 | git checkout B^0 && | |
875 | git merge --no-commit -s ours C^0 && | |
876 | git checkout C -- a c && | |
877 | mv a old_a && | |
878 | echo 1 >a && | |
879 | cat old_a >>a && | |
880 | rm old_a && | |
881 | git add -u && | |
882 | git commit -m "Merge commit C^0 into HEAD" && | |
883 | git tag D && | |
884 | ||
885 | git checkout C^0 && | |
886 | git merge --no-commit -s ours B^0 && | |
887 | git checkout B -- b && | |
888 | echo 8 >>a && | |
889 | git add -u && | |
890 | git commit -m "Merge commit B^0 into HEAD" && | |
891 | git tag E | |
892 | ) | |
0b35deb3 EN |
893 | ' |
894 | ||
895 | test_expect_failure 'detect rename/rename/add-source for virtual merge-base' ' | |
2a4c19ef EN |
896 | ( |
897 | cd rename-rename-add-source && | |
898 | ||
899 | git checkout D^0 && | |
0b35deb3 | 900 | |
2a4c19ef | 901 | git merge -s recursive E^0 && |
0b35deb3 | 902 | |
0cdabc10 EN |
903 | git ls-files -s >out && |
904 | test_line_count = 3 out && | |
905 | git ls-files -u >out && | |
906 | test_line_count = 0 out && | |
907 | git ls-files -o >out && | |
908 | test_line_count = 1 out && | |
0b35deb3 | 909 | |
6ac767e5 EN |
910 | printf "1\n2\n3\n4\n5\n6\n7\n8\n" >correct && |
911 | git rev-parse >expect \ | |
912 | A:a A:a \ | |
913 | correct && | |
914 | git rev-parse >actual \ | |
915 | :0:b :0:c && | |
916 | git hash-object >>actual \ | |
917 | a && | |
918 | test_cmp expect actual | |
2a4c19ef | 919 | ) |
0b35deb3 EN |
920 | ' |
921 | ||
b630b814 EN |
922 | # |
923 | # criss-cross with rename/rename(1to2)/add-dest + simple modify: | |
924 | # | |
925 | # B D | |
926 | # o---o | |
927 | # / \ / \ | |
928 | # A o X ? F | |
929 | # \ / \ / | |
930 | # o---o | |
931 | # C E | |
932 | # | |
933 | # Commit A: new file: a | |
934 | # Commit B: rename a->b, add c | |
935 | # Commit C: rename a->c | |
936 | # Commit D: merge B&C, keeping A:a and B:c | |
937 | # Commit E: merge B&C, keeping A:a and slightly modified c from B | |
938 | # | |
939 | # Merging commits D & E should result in no conflict. The virtual merge | |
940 | # base of B & C needs to not delete B:c for that to work, though... | |
941 | ||
942 | test_expect_success 'setup criss-cross+rename/rename/add-dest + simple modify' ' | |
2a4c19ef EN |
943 | test_create_repo rename-rename-add-dest && |
944 | ( | |
945 | cd rename-rename-add-dest && | |
946 | ||
947 | >a && | |
948 | git add a && | |
949 | git commit -m A && | |
950 | git tag A && | |
951 | ||
952 | git checkout -b B A && | |
953 | git mv a b && | |
954 | printf "1\n2\n3\n4\n5\n6\n7\n" >c && | |
955 | git add c && | |
956 | git commit -m B && | |
957 | ||
958 | git checkout -b C A && | |
959 | git mv a c && | |
960 | git commit -m C && | |
961 | ||
962 | git checkout B^0 && | |
963 | git merge --no-commit -s ours C^0 && | |
964 | git mv b a && | |
965 | git commit -m "D is like B but renames b back to a" && | |
966 | git tag D && | |
967 | ||
968 | git checkout B^0 && | |
969 | git merge --no-commit -s ours C^0 && | |
970 | git mv b a && | |
971 | echo 8 >>c && | |
972 | git add c && | |
973 | git commit -m "E like D but has mod in c" && | |
974 | git tag E | |
975 | ) | |
b630b814 EN |
976 | ' |
977 | ||
6d63070c | 978 | test_expect_success 'virtual merge base handles rename/rename(1to2)/add-dest' ' |
2a4c19ef EN |
979 | ( |
980 | cd rename-rename-add-dest && | |
981 | ||
982 | git checkout D^0 && | |
b630b814 | 983 | |
2a4c19ef | 984 | git merge -s recursive E^0 && |
b630b814 | 985 | |
0cdabc10 EN |
986 | git ls-files -s >out && |
987 | test_line_count = 2 out && | |
988 | git ls-files -u >out && | |
989 | test_line_count = 0 out && | |
990 | git ls-files -o >out && | |
991 | test_line_count = 1 out && | |
b630b814 | 992 | |
6ac767e5 EN |
993 | git rev-parse >expect \ |
994 | A:a E:c && | |
995 | git rev-parse >actual \ | |
996 | :0:a :0:c && | |
997 | test_cmp expect actual | |
2a4c19ef | 998 | ) |
b630b814 EN |
999 | ' |
1000 | ||
c6d3dd5d EN |
1001 | # |
1002 | # criss-cross with modify/modify on a symlink: | |
1003 | # | |
1004 | # B D | |
1005 | # o---o | |
1006 | # / \ / \ | |
1007 | # A o X ? F | |
1008 | # \ / \ / | |
1009 | # o---o | |
1010 | # C E | |
1011 | # | |
1012 | # Commit A: simple simlink fickle->lagoon | |
1013 | # Commit B: redirect fickle->disneyland | |
1014 | # Commit C: redirect fickle->home | |
1015 | # Commit D: merge B&C, resolving in favor of B | |
1016 | # Commit E: merge B&C, resolving in favor of C | |
1017 | # | |
1018 | # This is an obvious modify/modify conflict for the symlink 'fickle'. Can | |
1019 | # git detect it? | |
1020 | ||
1021 | test_expect_success 'setup symlink modify/modify' ' | |
1022 | test_create_repo symlink-modify-modify && | |
1023 | ( | |
1024 | cd symlink-modify-modify && | |
1025 | ||
1026 | test_ln_s_add lagoon fickle && | |
1027 | git commit -m A && | |
1028 | git tag A && | |
1029 | ||
1030 | git checkout -b B A && | |
1031 | git rm fickle && | |
1032 | test_ln_s_add disneyland fickle && | |
1033 | git commit -m B && | |
1034 | ||
1035 | git checkout -b C A && | |
1036 | git rm fickle && | |
1037 | test_ln_s_add home fickle && | |
1038 | git add fickle && | |
1039 | git commit -m C && | |
1040 | ||
1041 | git checkout -q B^0 && | |
1042 | git merge -s ours -m D C^0 && | |
1043 | git tag D && | |
1044 | ||
1045 | git checkout -q C^0 && | |
1046 | git merge -s ours -m E B^0 && | |
1047 | git tag E | |
1048 | ) | |
1049 | ' | |
1050 | ||
1051 | test_expect_failure 'check symlink modify/modify' ' | |
1052 | ( | |
1053 | cd symlink-modify-modify && | |
1054 | ||
1055 | git checkout D^0 && | |
1056 | ||
1057 | test_must_fail git merge -s recursive E^0 && | |
1058 | ||
1059 | git ls-files -s >out && | |
1060 | test_line_count = 3 out && | |
1061 | git ls-files -u >out && | |
1062 | test_line_count = 3 out && | |
1063 | git ls-files -o >out && | |
1064 | test_line_count = 1 out | |
1065 | ) | |
1066 | ' | |
1067 | ||
81f5a2ce EN |
1068 | # |
1069 | # criss-cross with add/add of a symlink: | |
1070 | # | |
1071 | # B D | |
1072 | # o---o | |
1073 | # / \ / \ | |
1074 | # A o X ? F | |
1075 | # \ / \ / | |
1076 | # o---o | |
1077 | # C E | |
1078 | # | |
1079 | # Commit A: No symlink or path exists yet | |
1080 | # Commit B: set up symlink: fickle->disneyland | |
1081 | # Commit C: set up symlink: fickle->home | |
1082 | # Commit D: merge B&C, resolving in favor of B | |
1083 | # Commit E: merge B&C, resolving in favor of C | |
1084 | # | |
1085 | # This is an obvious add/add conflict for the symlink 'fickle'. Can | |
1086 | # git detect it? | |
1087 | ||
1088 | test_expect_success 'setup symlink add/add' ' | |
1089 | test_create_repo symlink-add-add && | |
1090 | ( | |
1091 | cd symlink-add-add && | |
1092 | ||
1093 | touch ignoreme && | |
1094 | git add ignoreme && | |
1095 | git commit -m A && | |
1096 | git tag A && | |
1097 | ||
1098 | git checkout -b B A && | |
1099 | test_ln_s_add disneyland fickle && | |
1100 | git commit -m B && | |
1101 | ||
1102 | git checkout -b C A && | |
1103 | test_ln_s_add home fickle && | |
1104 | git add fickle && | |
1105 | git commit -m C && | |
1106 | ||
1107 | git checkout -q B^0 && | |
1108 | git merge -s ours -m D C^0 && | |
1109 | git tag D && | |
1110 | ||
1111 | git checkout -q C^0 && | |
1112 | git merge -s ours -m E B^0 && | |
1113 | git tag E | |
1114 | ) | |
1115 | ' | |
1116 | ||
1117 | test_expect_failure 'check symlink add/add' ' | |
1118 | ( | |
1119 | cd symlink-add-add && | |
1120 | ||
1121 | git checkout D^0 && | |
1122 | ||
1123 | test_must_fail git merge -s recursive E^0 && | |
1124 | ||
1125 | git ls-files -s >out && | |
1126 | test_line_count = 2 out && | |
1127 | git ls-files -u >out && | |
1128 | test_line_count = 2 out && | |
1129 | git ls-files -o >out && | |
1130 | test_line_count = 1 out | |
1131 | ) | |
1132 | ' | |
1133 | ||
d4d17180 EN |
1134 | # |
1135 | # criss-cross with modify/modify on a submodule: | |
1136 | # | |
1137 | # B D | |
1138 | # o---o | |
1139 | # / \ / \ | |
1140 | # A o X ? F | |
1141 | # \ / \ / | |
1142 | # o---o | |
1143 | # C E | |
1144 | # | |
1145 | # Commit A: simple submodule repo | |
1146 | # Commit B: update repo | |
1147 | # Commit C: update repo differently | |
1148 | # Commit D: merge B&C, resolving in favor of B | |
1149 | # Commit E: merge B&C, resolving in favor of C | |
1150 | # | |
1151 | # This is an obvious modify/modify conflict for the submodule 'repo'. Can | |
1152 | # git detect it? | |
1153 | ||
1154 | test_expect_success 'setup submodule modify/modify' ' | |
1155 | test_create_repo submodule-modify-modify && | |
1156 | ( | |
1157 | cd submodule-modify-modify && | |
1158 | ||
1159 | test_create_repo submod && | |
1160 | ( | |
1161 | cd submod && | |
1162 | touch file-A && | |
1163 | git add file-A && | |
1164 | git commit -m A && | |
1165 | git tag A && | |
1166 | ||
1167 | git checkout -b B A && | |
1168 | touch file-B && | |
1169 | git add file-B && | |
1170 | git commit -m B && | |
1171 | git tag B && | |
1172 | ||
1173 | git checkout -b C A && | |
1174 | touch file-C && | |
1175 | git add file-C && | |
1176 | git commit -m C && | |
1177 | git tag C | |
1178 | ) && | |
1179 | ||
1180 | git -C submod reset --hard A && | |
1181 | git add submod && | |
1182 | git commit -m A && | |
1183 | git tag A && | |
1184 | ||
1185 | git checkout -b B A && | |
1186 | git -C submod reset --hard B && | |
1187 | git add submod && | |
1188 | git commit -m B && | |
1189 | ||
1190 | git checkout -b C A && | |
1191 | git -C submod reset --hard C && | |
1192 | git add submod && | |
1193 | git commit -m C && | |
1194 | ||
1195 | git checkout -q B^0 && | |
1196 | git merge -s ours -m D C^0 && | |
1197 | git tag D && | |
1198 | ||
1199 | git checkout -q C^0 && | |
1200 | git merge -s ours -m E B^0 && | |
1201 | git tag E | |
1202 | ) | |
1203 | ' | |
1204 | ||
1205 | test_expect_failure 'check submodule modify/modify' ' | |
1206 | ( | |
1207 | cd submodule-modify-modify && | |
1208 | ||
1209 | git checkout D^0 && | |
1210 | ||
1211 | test_must_fail git merge -s recursive E^0 && | |
1212 | ||
1213 | git ls-files -s >out && | |
1214 | test_line_count = 3 out && | |
1215 | git ls-files -u >out && | |
1216 | test_line_count = 3 out && | |
1217 | git ls-files -o >out && | |
1218 | test_line_count = 1 out | |
1219 | ) | |
1220 | ' | |
1221 | ||
a79968be EN |
1222 | # |
1223 | # criss-cross with add/add on a submodule: | |
1224 | # | |
1225 | # B D | |
1226 | # o---o | |
1227 | # / \ / \ | |
1228 | # A o X ? F | |
1229 | # \ / \ / | |
1230 | # o---o | |
1231 | # C E | |
1232 | # | |
1233 | # Commit A: nothing of note | |
1234 | # Commit B: introduce submodule repo | |
1235 | # Commit C: introduce submodule repo at different commit | |
1236 | # Commit D: merge B&C, resolving in favor of B | |
1237 | # Commit E: merge B&C, resolving in favor of C | |
1238 | # | |
1239 | # This is an obvious add/add conflict for the submodule 'repo'. Can | |
1240 | # git detect it? | |
1241 | ||
1242 | test_expect_success 'setup submodule add/add' ' | |
1243 | test_create_repo submodule-add-add && | |
1244 | ( | |
1245 | cd submodule-add-add && | |
1246 | ||
1247 | test_create_repo submod && | |
1248 | ( | |
1249 | cd submod && | |
1250 | touch file-A && | |
1251 | git add file-A && | |
1252 | git commit -m A && | |
1253 | git tag A && | |
1254 | ||
1255 | git checkout -b B A && | |
1256 | touch file-B && | |
1257 | git add file-B && | |
1258 | git commit -m B && | |
1259 | git tag B && | |
1260 | ||
1261 | git checkout -b C A && | |
1262 | touch file-C && | |
1263 | git add file-C && | |
1264 | git commit -m C && | |
1265 | git tag C | |
1266 | ) && | |
1267 | ||
1268 | touch irrelevant-file && | |
1269 | git add irrelevant-file && | |
1270 | git commit -m A && | |
1271 | git tag A && | |
1272 | ||
1273 | git checkout -b B A && | |
1274 | git -C submod reset --hard B && | |
1275 | git add submod && | |
1276 | git commit -m B && | |
1277 | ||
1278 | git checkout -b C A && | |
1279 | git -C submod reset --hard C && | |
1280 | git add submod && | |
1281 | git commit -m C && | |
1282 | ||
1283 | git checkout -q B^0 && | |
1284 | git merge -s ours -m D C^0 && | |
1285 | git tag D && | |
1286 | ||
1287 | git checkout -q C^0 && | |
1288 | git merge -s ours -m E B^0 && | |
1289 | git tag E | |
1290 | ) | |
1291 | ' | |
1292 | ||
1293 | test_expect_failure 'check submodule add/add' ' | |
1294 | ( | |
1295 | cd submodule-add-add && | |
1296 | ||
1297 | git checkout D^0 && | |
1298 | ||
1299 | test_must_fail git merge -s recursive E^0 && | |
1300 | ||
1301 | git ls-files -s >out && | |
1302 | test_line_count = 3 out && | |
1303 | git ls-files -u >out && | |
1304 | test_line_count = 2 out && | |
1305 | git ls-files -o >out && | |
1306 | test_line_count = 1 out | |
1307 | ) | |
1308 | ' | |
1309 | ||
451a3abc EN |
1310 | # |
1311 | # criss-cross with conflicting entry types: | |
1312 | # | |
1313 | # B D | |
1314 | # o---o | |
1315 | # / \ / \ | |
1316 | # A o X ? F | |
1317 | # \ / \ / | |
1318 | # o---o | |
1319 | # C E | |
1320 | # | |
1321 | # Commit A: nothing of note | |
1322 | # Commit B: introduce submodule 'path' | |
1323 | # Commit C: introduce symlink 'path' | |
1324 | # Commit D: merge B&C, resolving in favor of B | |
1325 | # Commit E: merge B&C, resolving in favor of C | |
1326 | # | |
1327 | # This is an obvious add/add conflict for 'path'. Can git detect it? | |
1328 | ||
1329 | test_expect_success 'setup conflicting entry types (submodule vs symlink)' ' | |
1330 | test_create_repo submodule-symlink-add-add && | |
1331 | ( | |
1332 | cd submodule-symlink-add-add && | |
1333 | ||
1334 | test_create_repo path && | |
1335 | ( | |
1336 | cd path && | |
1337 | touch file-B && | |
1338 | git add file-B && | |
1339 | git commit -m B && | |
1340 | git tag B | |
1341 | ) && | |
1342 | ||
1343 | touch irrelevant-file && | |
1344 | git add irrelevant-file && | |
1345 | git commit -m A && | |
1346 | git tag A && | |
1347 | ||
1348 | git checkout -b B A && | |
1349 | git -C path reset --hard B && | |
1350 | git add path && | |
1351 | git commit -m B && | |
1352 | ||
1353 | git checkout -b C A && | |
1354 | rm -rf path/ && | |
1355 | test_ln_s_add irrelevant-file path && | |
1356 | git commit -m C && | |
1357 | ||
1358 | git checkout -q B^0 && | |
1359 | git merge -s ours -m D C^0 && | |
1360 | git tag D && | |
1361 | ||
1362 | git checkout -q C^0 && | |
1363 | git merge -s ours -m E B^0 && | |
1364 | git tag E | |
1365 | ) | |
1366 | ' | |
1367 | ||
1368 | test_expect_failure 'check conflicting entry types (submodule vs symlink)' ' | |
1369 | ( | |
1370 | cd submodule-symlink-add-add && | |
1371 | ||
1372 | git checkout D^0 && | |
1373 | ||
1374 | test_must_fail git merge -s recursive E^0 && | |
1375 | ||
1376 | git ls-files -s >out && | |
1377 | test_line_count = 3 out && | |
1378 | git ls-files -u >out && | |
1379 | test_line_count = 2 out && | |
1380 | git ls-files -o >out && | |
1381 | test_line_count = 1 out | |
1382 | ) | |
1383 | ' | |
1384 | ||
5d1daf30 EN |
1385 | # |
1386 | # criss-cross with regular files that have conflicting modes: | |
1387 | # | |
1388 | # B D | |
1389 | # o---o | |
1390 | # / \ / \ | |
1391 | # A o X ? F | |
1392 | # \ / \ / | |
1393 | # o---o | |
1394 | # C E | |
1395 | # | |
1396 | # Commit A: nothing of note | |
1397 | # Commit B: introduce file source_me.bash, not executable | |
1398 | # Commit C: introduce file source_me.bash, executable | |
1399 | # Commit D: merge B&C, resolving in favor of B | |
1400 | # Commit E: merge B&C, resolving in favor of C | |
1401 | # | |
1402 | # This is an obvious add/add mode conflict. Can git detect it? | |
1403 | ||
1404 | test_expect_success 'setup conflicting modes for regular file' ' | |
1405 | test_create_repo regular-file-mode-conflict && | |
1406 | ( | |
1407 | cd regular-file-mode-conflict && | |
1408 | ||
1409 | touch irrelevant-file && | |
1410 | git add irrelevant-file && | |
1411 | git commit -m A && | |
1412 | git tag A && | |
1413 | ||
1414 | git checkout -b B A && | |
1415 | echo "command_to_run" >source_me.bash && | |
1416 | git add source_me.bash && | |
1417 | git commit -m B && | |
1418 | ||
1419 | git checkout -b C A && | |
1420 | echo "command_to_run" >source_me.bash && | |
1421 | git add source_me.bash && | |
1422 | test_chmod +x source_me.bash && | |
1423 | git commit -m C && | |
1424 | ||
1425 | git checkout -q B^0 && | |
1426 | git merge -s ours -m D C^0 && | |
1427 | git tag D && | |
1428 | ||
1429 | git checkout -q C^0 && | |
1430 | git merge -s ours -m E B^0 && | |
1431 | git tag E | |
1432 | ) | |
1433 | ' | |
1434 | ||
1435 | test_expect_failure 'check conflicting modes for regular file' ' | |
1436 | ( | |
1437 | cd regular-file-mode-conflict && | |
1438 | ||
1439 | git checkout D^0 && | |
1440 | ||
1441 | test_must_fail git merge -s recursive E^0 && | |
1442 | ||
1443 | git ls-files -s >out && | |
1444 | test_line_count = 3 out && | |
1445 | git ls-files -u >out && | |
1446 | test_line_count = 2 out && | |
1447 | git ls-files -o >out && | |
1448 | test_line_count = 1 out | |
1449 | ) | |
1450 | ' | |
1451 | ||
b28eeb30 EN |
1452 | # Setup: |
1453 | # L1---L2 | |
1454 | # / \ / \ | |
1455 | # master X ? | |
1456 | # \ / \ / | |
1457 | # R1---R2 | |
1458 | # | |
1459 | # Where: | |
1460 | # master has two files, named 'b' and 'a' | |
1461 | # branches L1 and R1 both modify each of the two files in conflicting ways | |
1462 | # | |
1463 | # L2 is a merge of R1 into L1; more on it later. | |
1464 | # R2 is a merge of L1 into R1; more on it later. | |
1465 | # | |
1466 | # X is an auto-generated merge-base used when merging L2 and R2. | |
1467 | # since X is a merge of L1 and R1, it has conflicting versions of each file | |
1468 | # | |
1469 | # More about L2 and R2: | |
1470 | # - both resolve the conflicts in 'b' and 'a' differently | |
1471 | # - L2 renames 'b' to 'm' | |
1472 | # - R2 renames 'a' to 'm' | |
1473 | # | |
1474 | # In the end, in file 'm' we have four different conflicting files (from | |
1475 | # two versions of 'b' and two of 'a'). In addition, if | |
1476 | # merge.conflictstyle is diff3, then the base version also has | |
1477 | # conflict markers of its own, leading to a total of three levels of | |
1478 | # conflict markers. This is a pretty weird corner case, but we just want | |
1479 | # to ensure that we handle it as well as practical. | |
1480 | ||
1481 | test_expect_success 'setup nested conflicts' ' | |
1482 | test_create_repo nested_conflicts && | |
1483 | ( | |
1484 | cd nested_conflicts && | |
1485 | ||
1486 | # Create some related files now | |
1487 | for i in $(test_seq 1 10) | |
1488 | do | |
1489 | echo Random base content line $i | |
1490 | done >initial && | |
1491 | ||
1492 | cp initial b_L1 && | |
1493 | cp initial b_R1 && | |
1494 | cp initial b_L2 && | |
1495 | cp initial b_R2 && | |
1496 | cp initial a_L1 && | |
1497 | cp initial a_R1 && | |
1498 | cp initial a_L2 && | |
1499 | cp initial a_R2 && | |
1500 | ||
1501 | test_write_lines b b_L1 >>b_L1 && | |
1502 | test_write_lines b b_R1 >>b_R1 && | |
1503 | test_write_lines b b_L2 >>b_L2 && | |
1504 | test_write_lines b b_R2 >>b_R2 && | |
1505 | test_write_lines a a_L1 >>a_L1 && | |
1506 | test_write_lines a a_R1 >>a_R1 && | |
1507 | test_write_lines a a_L2 >>a_L2 && | |
1508 | test_write_lines a a_R2 >>a_R2 && | |
1509 | ||
1510 | # Setup original commit (or merge-base), consisting of | |
1511 | # files named "b" and "a" | |
1512 | cp initial b && | |
1513 | cp initial a && | |
1514 | echo b >>b && | |
1515 | echo a >>a && | |
1516 | git add b a && | |
1517 | test_tick && git commit -m initial && | |
1518 | ||
1519 | git branch L && | |
1520 | git branch R && | |
1521 | ||
1522 | # Handle the left side | |
1523 | git checkout L && | |
1524 | mv -f b_L1 b && | |
1525 | mv -f a_L1 a && | |
1526 | git add b a && | |
1527 | test_tick && git commit -m "version L1 of files" && | |
1528 | git tag L1 && | |
1529 | ||
1530 | # Handle the right side | |
1531 | git checkout R && | |
1532 | mv -f b_R1 b && | |
1533 | mv -f a_R1 a && | |
1534 | git add b a && | |
1535 | test_tick && git commit -m "verson R1 of files" && | |
1536 | git tag R1 && | |
1537 | ||
1538 | # Create first merge on left side | |
1539 | git checkout L && | |
1540 | test_must_fail git merge R1 && | |
1541 | mv -f b_L2 b && | |
1542 | mv -f a_L2 a && | |
1543 | git add b a && | |
1544 | git mv b m && | |
1545 | test_tick && git commit -m "left merge, rename b->m" && | |
1546 | git tag L2 && | |
1547 | ||
1548 | # Create first merge on right side | |
1549 | git checkout R && | |
1550 | test_must_fail git merge L1 && | |
1551 | mv -f b_R2 b && | |
1552 | mv -f a_R2 a && | |
1553 | git add b a && | |
1554 | git mv a m && | |
1555 | test_tick && git commit -m "right merge, rename a->m" && | |
1556 | git tag R2 | |
1557 | ) | |
1558 | ' | |
1559 | ||
bbafc9c4 | 1560 | test_expect_success 'check nested conflicts' ' |
b28eeb30 EN |
1561 | ( |
1562 | cd nested_conflicts && | |
1563 | ||
1564 | git clean -f && | |
1565 | git checkout L2^0 && | |
1566 | ||
1567 | # Merge must fail; there is a conflict | |
1568 | test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R2^0 && | |
1569 | ||
1570 | # Make sure the index has the right number of entries | |
1571 | git ls-files -s >out && | |
1572 | test_line_count = 2 out && | |
1573 | git ls-files -u >out && | |
1574 | test_line_count = 2 out && | |
1575 | # Ensure we have the correct number of untracked files | |
1576 | git ls-files -o >out && | |
1577 | test_line_count = 1 out && | |
1578 | ||
1579 | # Create a and b from virtual merge base X | |
1580 | git cat-file -p master:a >base && | |
1581 | git cat-file -p L1:a >ours && | |
1582 | git cat-file -p R1:a >theirs && | |
1583 | test_must_fail git merge-file --diff3 \ | |
1584 | -L "Temporary merge branch 1" \ | |
1585 | -L "merged common ancestors" \ | |
1586 | -L "Temporary merge branch 2" \ | |
1587 | ours \ | |
1588 | base \ | |
1589 | theirs && | |
1590 | sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_a && | |
1591 | ||
1592 | git cat-file -p master:b >base && | |
1593 | git cat-file -p L1:b >ours && | |
1594 | git cat-file -p R1:b >theirs && | |
1595 | test_must_fail git merge-file --diff3 \ | |
1596 | -L "Temporary merge branch 1" \ | |
1597 | -L "merged common ancestors" \ | |
1598 | -L "Temporary merge branch 2" \ | |
1599 | ours \ | |
1600 | base \ | |
1601 | theirs && | |
1602 | sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_b && | |
1603 | ||
1604 | # Compare :2:m to expected values | |
1605 | git cat-file -p L2:m >ours && | |
1606 | git cat-file -p R2:b >theirs && | |
1607 | test_must_fail git merge-file --diff3 \ | |
1608 | -L "HEAD:m" \ | |
1609 | -L "merged common ancestors:b" \ | |
1610 | -L "R2^0:b" \ | |
1611 | ours \ | |
1612 | vmb_b \ | |
1613 | theirs && | |
1614 | sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_2 && | |
1615 | git cat-file -p :2:m >actual && | |
1616 | test_cmp m_stage_2 actual && | |
1617 | ||
1618 | # Compare :3:m to expected values | |
1619 | git cat-file -p L2:a >ours && | |
1620 | git cat-file -p R2:m >theirs && | |
1621 | test_must_fail git merge-file --diff3 \ | |
1622 | -L "HEAD:a" \ | |
1623 | -L "merged common ancestors:a" \ | |
1624 | -L "R2^0:m" \ | |
1625 | ours \ | |
1626 | vmb_a \ | |
1627 | theirs && | |
1628 | sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_3 && | |
1629 | git cat-file -p :3:m >actual && | |
1630 | test_cmp m_stage_3 actual && | |
1631 | ||
1632 | # Compare m to expected contents | |
1633 | >empty && | |
cc4cb090 | 1634 | cp m_stage_2 expected_final_m && |
b28eeb30 EN |
1635 | test_must_fail git merge-file --diff3 \ |
1636 | -L "HEAD" \ | |
1637 | -L "merged common ancestors" \ | |
1638 | -L "R2^0" \ | |
1639 | expected_final_m \ | |
1640 | empty \ | |
1641 | m_stage_3 && | |
1642 | test_cmp expected_final_m m | |
1643 | ) | |
1644 | ' | |
1645 | ||
b2a7942b EN |
1646 | # Setup: |
1647 | # L1---L2---L3 | |
1648 | # / \ / \ / \ | |
1649 | # master X1 X2 ? | |
1650 | # \ / \ / \ / | |
1651 | # R1---R2---R3 | |
1652 | # | |
1653 | # Where: | |
1654 | # master has one file named 'content' | |
1655 | # branches L1 and R1 both modify each of the two files in conflicting ways | |
1656 | # | |
1657 | # L<n> (n>1) is a merge of R<n-1> into L<n-1> | |
1658 | # R<n> (n>1) is a merge of L<n-1> into R<n-1> | |
1659 | # L<n> and R<n> resolve the conflicts differently. | |
1660 | # | |
1661 | # X<n> is an auto-generated merge-base used when merging L<n+1> and R<n+1>. | |
1662 | # By construction, X1 has conflict markers due to conflicting versions. | |
1663 | # X2, due to using merge.conflictstyle=3, has nested conflict markers. | |
1664 | # | |
1665 | # So, merging R3 into L3 using merge.conflictstyle=3 should show the | |
1666 | # nested conflict markers from X2 in the base version -- that means we | |
1667 | # have three levels of conflict markers. Can we distinguish all three? | |
1668 | ||
1669 | test_expect_success 'setup virtual merge base with nested conflicts' ' | |
1670 | test_create_repo virtual_merge_base_has_nested_conflicts && | |
1671 | ( | |
1672 | cd virtual_merge_base_has_nested_conflicts && | |
1673 | ||
1674 | # Create some related files now | |
1675 | for i in $(test_seq 1 10) | |
1676 | do | |
1677 | echo Random base content line $i | |
1678 | done >content && | |
1679 | ||
1680 | # Setup original commit | |
1681 | git add content && | |
1682 | test_tick && git commit -m initial && | |
1683 | ||
1684 | git branch L && | |
1685 | git branch R && | |
1686 | ||
1687 | # Create L1 | |
1688 | git checkout L && | |
1689 | echo left >>content && | |
1690 | git add content && | |
1691 | test_tick && git commit -m "version L1 of content" && | |
1692 | git tag L1 && | |
1693 | ||
1694 | # Create R1 | |
1695 | git checkout R && | |
1696 | echo right >>content && | |
1697 | git add content && | |
1698 | test_tick && git commit -m "verson R1 of content" && | |
1699 | git tag R1 && | |
1700 | ||
1701 | # Create L2 | |
1702 | git checkout L && | |
1703 | test_must_fail git -c merge.conflictstyle=diff3 merge R1 && | |
1704 | git checkout L1 content && | |
1705 | test_tick && git commit -m "version L2 of content" && | |
1706 | git tag L2 && | |
1707 | ||
1708 | # Create R2 | |
1709 | git checkout R && | |
1710 | test_must_fail git -c merge.conflictstyle=diff3 merge L1 && | |
1711 | git checkout R1 content && | |
1712 | test_tick && git commit -m "version R2 of content" && | |
1713 | git tag R2 && | |
1714 | ||
1715 | # Create L3 | |
1716 | git checkout L && | |
1717 | test_must_fail git -c merge.conflictstyle=diff3 merge R2 && | |
1718 | git checkout L1 content && | |
1719 | test_tick && git commit -m "version L3 of content" && | |
1720 | git tag L3 && | |
1721 | ||
1722 | # Create R3 | |
1723 | git checkout R && | |
1724 | test_must_fail git -c merge.conflictstyle=diff3 merge L2 && | |
1725 | git checkout R1 content && | |
1726 | test_tick && git commit -m "version R3 of content" && | |
1727 | git tag R3 | |
1728 | ) | |
1729 | ' | |
1730 | ||
1731 | test_expect_success 'check virtual merge base with nested conflicts' ' | |
1732 | ( | |
1733 | cd virtual_merge_base_has_nested_conflicts && | |
1734 | ||
1735 | git checkout L3^0 && | |
1736 | ||
1737 | # Merge must fail; there is a conflict | |
1738 | test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R3^0 && | |
1739 | ||
1740 | # Make sure the index has the right number of entries | |
1741 | git ls-files -s >out && | |
1742 | test_line_count = 3 out && | |
1743 | git ls-files -u >out && | |
1744 | test_line_count = 3 out && | |
1745 | # Ensure we have the correct number of untracked files | |
1746 | git ls-files -o >out && | |
1747 | test_line_count = 1 out && | |
1748 | ||
1749 | # Compare :[23]:content to expected values | |
1750 | git rev-parse L1:content R1:content >expect && | |
1751 | git rev-parse :2:content :3:content >actual && | |
1752 | test_cmp expect actual && | |
1753 | ||
1754 | # Imitate X1 merge base, except without long enough conflict | |
1755 | # markers because a subsequent sed will modify them. Put | |
1756 | # result into vmb. | |
1757 | git cat-file -p master:content >base && | |
1758 | git cat-file -p L:content >left && | |
1759 | git cat-file -p R:content >right && | |
1760 | cp left merged-once && | |
1761 | test_must_fail git merge-file --diff3 \ | |
1762 | -L "Temporary merge branch 1" \ | |
1763 | -L "merged common ancestors" \ | |
1764 | -L "Temporary merge branch 2" \ | |
1765 | merged-once \ | |
1766 | base \ | |
1767 | right && | |
1768 | sed -e "s/^\([<|=>]\)/\1\1\1/" merged-once >vmb && | |
1769 | ||
1770 | # Imitate X2 merge base, overwriting vmb. Note that we | |
1771 | # extend both sets of conflict markers to make them longer | |
1772 | # with the sed command. | |
1773 | cp left merged-twice && | |
1774 | test_must_fail git merge-file --diff3 \ | |
1775 | -L "Temporary merge branch 1" \ | |
1776 | -L "merged common ancestors" \ | |
1777 | -L "Temporary merge branch 2" \ | |
1778 | merged-twice \ | |
1779 | vmb \ | |
1780 | right && | |
1781 | sed -e "s/^\([<|=>]\)/\1\1\1/" merged-twice >vmb && | |
1782 | ||
1783 | # Compare :1:content to expected value | |
1784 | git cat-file -p :1:content >actual && | |
1785 | test_cmp vmb actual && | |
1786 | ||
1787 | # Determine expected content in final outer merge, compare to | |
1788 | # what the merge generated. | |
1789 | cp -f left expect && | |
1790 | test_must_fail git merge-file --diff3 \ | |
1791 | -L "HEAD" -L "merged common ancestors" -L "R3^0" \ | |
1792 | expect vmb right && | |
1793 | test_cmp expect content | |
1794 | ) | |
1795 | ' | |
1796 | ||
c94736a2 | 1797 | test_done |