]>
Commit | Line | Data |
---|---|---|
04550ab5 EN |
1 | #!/bin/sh |
2 | ||
3 | test_description="recursive merge with directory renames" | |
4 | # includes checking of many corner cases, with a similar methodology to: | |
5 | # t6042: corner cases with renames but not criss-cross merges | |
6 | # t6036: corner cases with both renames and criss-cross merges | |
7 | # | |
8 | # The setup for all of them, pictorially, is: | |
9 | # | |
10 | # A | |
11 | # o | |
12 | # / \ | |
13 | # O o ? | |
14 | # \ / | |
15 | # o | |
16 | # B | |
17 | # | |
18 | # To help make it easier to follow the flow of tests, they have been | |
19 | # divided into sections and each test will start with a quick explanation | |
20 | # of what commits O, A, and B contain. | |
21 | # | |
22 | # Notation: | |
23 | # z/{b,c} means files z/b and z/c both exist | |
24 | # x/d_1 means file x/d exists with content d1. (Purpose of the | |
25 | # underscore notation is to differentiate different | |
26 | # files that might be renamed into each other's paths.) | |
27 | ||
28 | . ./test-lib.sh | |
29 | ||
30 | ||
31 | ########################################################################### | |
32 | # SECTION 1: Basic cases we should be able to handle | |
33 | ########################################################################### | |
34 | ||
35 | # Testcase 1a, Basic directory rename. | |
36 | # Commit O: z/{b,c} | |
37 | # Commit A: y/{b,c} | |
38 | # Commit B: z/{b,c,d,e/f} | |
39 | # Expected: y/{b,c,d,e/f} | |
40 | ||
41 | test_expect_success '1a-setup: Simple directory rename detection' ' | |
42 | test_create_repo 1a && | |
43 | ( | |
44 | cd 1a && | |
45 | ||
46 | mkdir z && | |
47 | echo b >z/b && | |
48 | echo c >z/c && | |
49 | git add z && | |
50 | test_tick && | |
51 | git commit -m "O" && | |
52 | ||
53 | git branch O && | |
54 | git branch A && | |
55 | git branch B && | |
56 | ||
57 | git checkout A && | |
58 | git mv z y && | |
59 | test_tick && | |
60 | git commit -m "A" && | |
61 | ||
62 | git checkout B && | |
63 | echo d >z/d && | |
64 | mkdir z/e && | |
65 | echo f >z/e/f && | |
66 | git add z/d z/e/f && | |
67 | test_tick && | |
68 | git commit -m "B" | |
69 | ) | |
70 | ' | |
71 | ||
72 | test_expect_failure '1a-check: Simple directory rename detection' ' | |
73 | ( | |
74 | cd 1a && | |
75 | ||
76 | git checkout A^0 && | |
77 | ||
78 | git merge -s recursive B^0 && | |
79 | ||
80 | git ls-files -s >out && | |
81 | test_line_count = 4 out && | |
82 | ||
83 | git rev-parse >actual \ | |
84 | HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e/f && | |
85 | git rev-parse >expect \ | |
86 | O:z/b O:z/c B:z/d B:z/e/f && | |
87 | test_cmp expect actual && | |
88 | ||
89 | git hash-object y/d >actual && | |
90 | git rev-parse B:z/d >expect && | |
91 | test_cmp expect actual && | |
92 | ||
93 | test_must_fail git rev-parse HEAD:z/d && | |
94 | test_must_fail git rev-parse HEAD:z/e/f && | |
95 | test_path_is_missing z/d && | |
96 | test_path_is_missing z/e/f | |
97 | ) | |
98 | ' | |
99 | ||
100 | # Testcase 1b, Merge a directory with another | |
101 | # Commit O: z/{b,c}, y/d | |
102 | # Commit A: z/{b,c,e}, y/d | |
103 | # Commit B: y/{b,c,d} | |
104 | # Expected: y/{b,c,d,e} | |
105 | ||
106 | test_expect_success '1b-setup: Merge a directory with another' ' | |
107 | test_create_repo 1b && | |
108 | ( | |
109 | cd 1b && | |
110 | ||
111 | mkdir z && | |
112 | echo b >z/b && | |
113 | echo c >z/c && | |
114 | mkdir y && | |
115 | echo d >y/d && | |
116 | git add z y && | |
117 | test_tick && | |
118 | git commit -m "O" && | |
119 | ||
120 | git branch O && | |
121 | git branch A && | |
122 | git branch B && | |
123 | ||
124 | git checkout A && | |
125 | echo e >z/e && | |
126 | git add z/e && | |
127 | test_tick && | |
128 | git commit -m "A" && | |
129 | ||
130 | git checkout B && | |
131 | git mv z/b y && | |
132 | git mv z/c y && | |
133 | rmdir z && | |
134 | test_tick && | |
135 | git commit -m "B" | |
136 | ) | |
137 | ' | |
138 | ||
139 | test_expect_failure '1b-check: Merge a directory with another' ' | |
140 | ( | |
141 | cd 1b && | |
142 | ||
143 | git checkout A^0 && | |
144 | ||
145 | git merge -s recursive B^0 && | |
146 | ||
147 | git ls-files -s >out && | |
148 | test_line_count = 4 out && | |
149 | ||
150 | git rev-parse >actual \ | |
151 | HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e && | |
152 | git rev-parse >expect \ | |
153 | O:z/b O:z/c O:y/d A:z/e && | |
154 | test_cmp expect actual && | |
155 | test_must_fail git rev-parse HEAD:z/e | |
156 | ) | |
157 | ' | |
158 | ||
159 | # Testcase 1c, Transitive renaming | |
160 | # (Related to testcases 3a and 6d -- when should a transitive rename apply?) | |
161 | # (Related to testcases 9c and 9d -- can transitivity repeat?) | |
162 | # Commit O: z/{b,c}, x/d | |
163 | # Commit A: y/{b,c}, x/d | |
164 | # Commit B: z/{b,c,d} | |
165 | # Expected: y/{b,c,d} (because x/d -> z/d -> y/d) | |
166 | ||
167 | test_expect_success '1c-setup: Transitive renaming' ' | |
168 | test_create_repo 1c && | |
169 | ( | |
170 | cd 1c && | |
171 | ||
172 | mkdir z && | |
173 | echo b >z/b && | |
174 | echo c >z/c && | |
175 | mkdir x && | |
176 | echo d >x/d && | |
177 | git add z x && | |
178 | test_tick && | |
179 | git commit -m "O" && | |
180 | ||
181 | git branch O && | |
182 | git branch A && | |
183 | git branch B && | |
184 | ||
185 | git checkout A && | |
186 | git mv z y && | |
187 | test_tick && | |
188 | git commit -m "A" && | |
189 | ||
190 | git checkout B && | |
191 | git mv x/d z/d && | |
192 | test_tick && | |
193 | git commit -m "B" | |
194 | ) | |
195 | ' | |
196 | ||
197 | test_expect_failure '1c-check: Transitive renaming' ' | |
198 | ( | |
199 | cd 1c && | |
200 | ||
201 | git checkout A^0 && | |
202 | ||
203 | git merge -s recursive B^0 && | |
204 | ||
205 | git ls-files -s >out && | |
206 | test_line_count = 3 out && | |
207 | ||
208 | git rev-parse >actual \ | |
209 | HEAD:y/b HEAD:y/c HEAD:y/d && | |
210 | git rev-parse >expect \ | |
211 | O:z/b O:z/c O:x/d && | |
212 | test_cmp expect actual && | |
213 | test_must_fail git rev-parse HEAD:x/d && | |
214 | test_must_fail git rev-parse HEAD:z/d && | |
215 | test_path_is_missing z/d | |
216 | ) | |
217 | ' | |
218 | ||
219 | # Testcase 1d, Directory renames (merging two directories into one new one) | |
220 | # cause a rename/rename(2to1) conflict | |
221 | # (Related to testcases 1c and 7b) | |
222 | # Commit O. z/{b,c}, y/{d,e} | |
223 | # Commit A. x/{b,c}, y/{d,e,m,wham_1} | |
224 | # Commit B. z/{b,c,n,wham_2}, x/{d,e} | |
225 | # Expected: x/{b,c,d,e,m,n}, CONFLICT:(y/wham_1 & z/wham_2 -> x/wham) | |
226 | # Note: y/m & z/n should definitely move into x. By the same token, both | |
227 | # y/wham_1 & z/wham_2 should too...giving us a conflict. | |
228 | ||
229 | test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) conflict' ' | |
230 | test_create_repo 1d && | |
231 | ( | |
232 | cd 1d && | |
233 | ||
234 | mkdir z && | |
235 | echo b >z/b && | |
236 | echo c >z/c && | |
237 | mkdir y && | |
238 | echo d >y/d && | |
239 | echo e >y/e && | |
240 | git add z y && | |
241 | test_tick && | |
242 | git commit -m "O" && | |
243 | ||
244 | git branch O && | |
245 | git branch A && | |
246 | git branch B && | |
247 | ||
248 | git checkout A && | |
249 | git mv z x && | |
250 | echo m >y/m && | |
251 | echo wham1 >y/wham && | |
252 | git add y && | |
253 | test_tick && | |
254 | git commit -m "A" && | |
255 | ||
256 | git checkout B && | |
257 | git mv y x && | |
258 | echo n >z/n && | |
259 | echo wham2 >z/wham && | |
260 | git add z && | |
261 | test_tick && | |
262 | git commit -m "B" | |
263 | ) | |
264 | ' | |
265 | ||
266 | test_expect_failure '1d-check: Directory renames cause a rename/rename(2to1) conflict' ' | |
267 | ( | |
268 | cd 1d && | |
269 | ||
270 | git checkout A^0 && | |
271 | ||
272 | test_must_fail git merge -s recursive B^0 >out && | |
273 | test_i18ngrep "CONFLICT (rename/rename)" out && | |
274 | ||
275 | git ls-files -s >out && | |
276 | test_line_count = 8 out && | |
277 | git ls-files -u >out && | |
278 | test_line_count = 2 out && | |
279 | git ls-files -o >out && | |
280 | test_line_count = 3 out && | |
281 | ||
282 | git rev-parse >actual \ | |
283 | :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n && | |
284 | git rev-parse >expect \ | |
285 | O:z/b O:z/c O:y/d O:y/e A:y/m B:z/n && | |
286 | test_cmp expect actual && | |
287 | ||
288 | test_must_fail git rev-parse :0:x/wham && | |
289 | git rev-parse >actual \ | |
290 | :2:x/wham :3:x/wham && | |
291 | git rev-parse >expect \ | |
292 | A:y/wham B:z/wham && | |
293 | test_cmp expect actual && | |
294 | ||
295 | test_path_is_missing x/wham && | |
296 | test_path_is_file x/wham~HEAD && | |
297 | test_path_is_file x/wham~B^0 && | |
298 | ||
299 | git hash-object >actual \ | |
300 | x/wham~HEAD x/wham~B^0 && | |
301 | git rev-parse >expect \ | |
302 | A:y/wham B:z/wham && | |
303 | test_cmp expect actual | |
304 | ) | |
305 | ' | |
306 | ||
307 | # Testcase 1e, Renamed directory, with all filenames being renamed too | |
308 | # Commit O: z/{oldb,oldc} | |
309 | # Commit A: y/{newb,newc} | |
310 | # Commit B: z/{oldb,oldc,d} | |
311 | # Expected: y/{newb,newc,d} | |
312 | ||
313 | test_expect_success '1e-setup: Renamed directory, with all files being renamed too' ' | |
314 | test_create_repo 1e && | |
315 | ( | |
316 | cd 1e && | |
317 | ||
318 | mkdir z && | |
319 | echo b >z/oldb && | |
320 | echo c >z/oldc && | |
321 | git add z && | |
322 | test_tick && | |
323 | git commit -m "O" && | |
324 | ||
325 | git branch O && | |
326 | git branch A && | |
327 | git branch B && | |
328 | ||
329 | git checkout A && | |
330 | mkdir y && | |
331 | git mv z/oldb y/newb && | |
332 | git mv z/oldc y/newc && | |
333 | test_tick && | |
334 | git commit -m "A" && | |
335 | ||
336 | git checkout B && | |
337 | echo d >z/d && | |
338 | git add z/d && | |
339 | test_tick && | |
340 | git commit -m "B" | |
341 | ) | |
342 | ' | |
343 | ||
344 | test_expect_failure '1e-check: Renamed directory, with all files being renamed too' ' | |
345 | ( | |
346 | cd 1e && | |
347 | ||
348 | git checkout A^0 && | |
349 | ||
350 | git merge -s recursive B^0 && | |
351 | ||
352 | git ls-files -s >out && | |
353 | test_line_count = 3 out && | |
354 | ||
355 | git rev-parse >actual \ | |
356 | HEAD:y/newb HEAD:y/newc HEAD:y/d && | |
357 | git rev-parse >expect \ | |
358 | O:z/oldb O:z/oldc B:z/d && | |
359 | test_cmp expect actual && | |
360 | test_must_fail git rev-parse HEAD:z/d | |
361 | ) | |
362 | ' | |
363 | ||
364 | # Testcase 1f, Split a directory into two other directories | |
365 | # (Related to testcases 3a, all of section 2, and all of section 4) | |
366 | # Commit O: z/{b,c,d,e,f} | |
367 | # Commit A: z/{b,c,d,e,f,g} | |
368 | # Commit B: y/{b,c}, x/{d,e,f} | |
369 | # Expected: y/{b,c}, x/{d,e,f,g} | |
370 | ||
371 | test_expect_success '1f-setup: Split a directory into two other directories' ' | |
372 | test_create_repo 1f && | |
373 | ( | |
374 | cd 1f && | |
375 | ||
376 | mkdir z && | |
377 | echo b >z/b && | |
378 | echo c >z/c && | |
379 | echo d >z/d && | |
380 | echo e >z/e && | |
381 | echo f >z/f && | |
382 | git add z && | |
383 | test_tick && | |
384 | git commit -m "O" && | |
385 | ||
386 | git branch O && | |
387 | git branch A && | |
388 | git branch B && | |
389 | ||
390 | git checkout A && | |
391 | echo g >z/g && | |
392 | git add z/g && | |
393 | test_tick && | |
394 | git commit -m "A" && | |
395 | ||
396 | git checkout B && | |
397 | mkdir y && | |
398 | mkdir x && | |
399 | git mv z/b y/ && | |
400 | git mv z/c y/ && | |
401 | git mv z/d x/ && | |
402 | git mv z/e x/ && | |
403 | git mv z/f x/ && | |
404 | rmdir z && | |
405 | test_tick && | |
406 | git commit -m "B" | |
407 | ) | |
408 | ' | |
409 | ||
410 | test_expect_failure '1f-check: Split a directory into two other directories' ' | |
411 | ( | |
412 | cd 1f && | |
413 | ||
414 | git checkout A^0 && | |
415 | ||
416 | git merge -s recursive B^0 && | |
417 | ||
418 | git ls-files -s >out && | |
419 | test_line_count = 6 out && | |
420 | ||
421 | git rev-parse >actual \ | |
422 | HEAD:y/b HEAD:y/c HEAD:x/d HEAD:x/e HEAD:x/f HEAD:x/g && | |
423 | git rev-parse >expect \ | |
424 | O:z/b O:z/c O:z/d O:z/e O:z/f A:z/g && | |
425 | test_cmp expect actual && | |
426 | test_path_is_missing z/g && | |
427 | test_must_fail git rev-parse HEAD:z/g | |
428 | ) | |
429 | ' | |
430 | ||
431 | ########################################################################### | |
432 | # Rules suggested by testcases in section 1: | |
433 | # | |
434 | # We should still detect the directory rename even if it wasn't just | |
435 | # the directory renamed, but the files within it. (see 1b) | |
436 | # | |
437 | # If renames split a directory into two or more others, the directory | |
438 | # with the most renames, "wins" (see 1c). However, see the testcases | |
439 | # in section 2, plus testcases 3a and 4a. | |
440 | ########################################################################### | |
441 | ||
509555d8 EN |
442 | |
443 | ########################################################################### | |
444 | # SECTION 2: Split into multiple directories, with equal number of paths | |
445 | # | |
446 | # Explore the splitting-a-directory rules a bit; what happens in the | |
447 | # edge cases? | |
448 | # | |
449 | # Note that there is a closely related case of a directory not being | |
450 | # split on either side of history, but being renamed differently on | |
451 | # each side. See testcase 8e for that. | |
452 | ########################################################################### | |
453 | ||
454 | # Testcase 2a, Directory split into two on one side, with equal numbers of paths | |
455 | # Commit O: z/{b,c} | |
456 | # Commit A: y/b, w/c | |
457 | # Commit B: z/{b,c,d} | |
458 | # Expected: y/b, w/c, z/d, with warning about z/ -> (y/ vs. w/) conflict | |
459 | test_expect_success '2a-setup: Directory split into two on one side, with equal numbers of paths' ' | |
460 | test_create_repo 2a && | |
461 | ( | |
462 | cd 2a && | |
463 | ||
464 | mkdir z && | |
465 | echo b >z/b && | |
466 | echo c >z/c && | |
467 | git add z && | |
468 | test_tick && | |
469 | git commit -m "O" && | |
470 | ||
471 | git branch O && | |
472 | git branch A && | |
473 | git branch B && | |
474 | ||
475 | git checkout A && | |
476 | mkdir y && | |
477 | mkdir w && | |
478 | git mv z/b y/ && | |
479 | git mv z/c w/ && | |
480 | test_tick && | |
481 | git commit -m "A" && | |
482 | ||
483 | git checkout B && | |
484 | echo d >z/d && | |
485 | git add z/d && | |
486 | test_tick && | |
487 | git commit -m "B" | |
488 | ) | |
489 | ' | |
490 | ||
491 | test_expect_failure '2a-check: Directory split into two on one side, with equal numbers of paths' ' | |
492 | ( | |
493 | cd 2a && | |
494 | ||
495 | git checkout A^0 && | |
496 | ||
497 | test_must_fail git merge -s recursive B^0 >out && | |
498 | test_i18ngrep "CONFLICT.*directory rename split" out && | |
499 | ||
500 | git ls-files -s >out && | |
501 | test_line_count = 3 out && | |
502 | git ls-files -u >out && | |
503 | test_line_count = 0 out && | |
504 | git ls-files -o >out && | |
505 | test_line_count = 1 out && | |
506 | ||
507 | git rev-parse >actual \ | |
508 | :0:y/b :0:w/c :0:z/d && | |
509 | git rev-parse >expect \ | |
510 | O:z/b O:z/c B:z/d && | |
511 | test_cmp expect actual | |
512 | ) | |
513 | ' | |
514 | ||
515 | # Testcase 2b, Directory split into two on one side, with equal numbers of paths | |
516 | # Commit O: z/{b,c} | |
517 | # Commit A: y/b, w/c | |
518 | # Commit B: z/{b,c}, x/d | |
519 | # Expected: y/b, w/c, x/d; No warning about z/ -> (y/ vs. w/) conflict | |
520 | test_expect_success '2b-setup: Directory split into two on one side, with equal numbers of paths' ' | |
521 | test_create_repo 2b && | |
522 | ( | |
523 | cd 2b && | |
524 | ||
525 | mkdir z && | |
526 | echo b >z/b && | |
527 | echo c >z/c && | |
528 | git add z && | |
529 | test_tick && | |
530 | git commit -m "O" && | |
531 | ||
532 | git branch O && | |
533 | git branch A && | |
534 | git branch B && | |
535 | ||
536 | git checkout A && | |
537 | mkdir y && | |
538 | mkdir w && | |
539 | git mv z/b y/ && | |
540 | git mv z/c w/ && | |
541 | test_tick && | |
542 | git commit -m "A" && | |
543 | ||
544 | git checkout B && | |
545 | mkdir x && | |
546 | echo d >x/d && | |
547 | git add x/d && | |
548 | test_tick && | |
549 | git commit -m "B" | |
550 | ) | |
551 | ' | |
552 | ||
553 | test_expect_success '2b-check: Directory split into two on one side, with equal numbers of paths' ' | |
554 | ( | |
555 | cd 2b && | |
556 | ||
557 | git checkout A^0 && | |
558 | ||
559 | git merge -s recursive B^0 >out && | |
560 | ||
561 | git ls-files -s >out && | |
562 | test_line_count = 3 out && | |
563 | git ls-files -u >out && | |
564 | test_line_count = 0 out && | |
565 | git ls-files -o >out && | |
566 | test_line_count = 1 out && | |
567 | ||
568 | git rev-parse >actual \ | |
569 | :0:y/b :0:w/c :0:x/d && | |
570 | git rev-parse >expect \ | |
571 | O:z/b O:z/c B:x/d && | |
572 | test_cmp expect actual && | |
573 | test_i18ngrep ! "CONFLICT.*directory rename split" out | |
574 | ) | |
575 | ' | |
576 | ||
577 | ########################################################################### | |
578 | # Rules suggested by section 2: | |
579 | # | |
580 | # None; the rule was already covered in section 1. These testcases are | |
581 | # here just to make sure the conflict resolution and necessary warning | |
582 | # messages are handled correctly. | |
583 | ########################################################################### | |
584 | ||
21b53733 EN |
585 | |
586 | ########################################################################### | |
587 | # SECTION 3: Path in question is the source path for some rename already | |
588 | # | |
589 | # Combining cases from Section 1 and trying to handle them could lead to | |
590 | # directory renaming detection being over-applied. So, this section | |
591 | # provides some good testcases to check that the implementation doesn't go | |
592 | # too far. | |
593 | ########################################################################### | |
594 | ||
595 | # Testcase 3a, Avoid implicit rename if involved as source on other side | |
596 | # (Related to testcases 1c and 1f) | |
597 | # Commit O: z/{b,c,d} | |
598 | # Commit A: z/{b,c,d} (no change) | |
599 | # Commit B: y/{b,c}, x/d | |
600 | # Expected: y/{b,c}, x/d | |
601 | test_expect_success '3a-setup: Avoid implicit rename if involved as source on other side' ' | |
602 | test_create_repo 3a && | |
603 | ( | |
604 | cd 3a && | |
605 | ||
606 | mkdir z && | |
607 | echo b >z/b && | |
608 | echo c >z/c && | |
609 | echo d >z/d && | |
610 | git add z && | |
611 | test_tick && | |
612 | git commit -m "O" && | |
613 | ||
614 | git branch O && | |
615 | git branch A && | |
616 | git branch B && | |
617 | ||
618 | git checkout A && | |
619 | test_tick && | |
620 | git commit --allow-empty -m "A" && | |
621 | ||
622 | git checkout B && | |
623 | mkdir y && | |
624 | mkdir x && | |
625 | git mv z/b y/ && | |
626 | git mv z/c y/ && | |
627 | git mv z/d x/ && | |
628 | rmdir z && | |
629 | test_tick && | |
630 | git commit -m "B" | |
631 | ) | |
632 | ' | |
633 | ||
634 | test_expect_success '3a-check: Avoid implicit rename if involved as source on other side' ' | |
635 | ( | |
636 | cd 3a && | |
637 | ||
638 | git checkout A^0 && | |
639 | ||
640 | git merge -s recursive B^0 && | |
641 | ||
642 | git ls-files -s >out && | |
643 | test_line_count = 3 out && | |
644 | ||
645 | git rev-parse >actual \ | |
646 | HEAD:y/b HEAD:y/c HEAD:x/d && | |
647 | git rev-parse >expect \ | |
648 | O:z/b O:z/c O:z/d && | |
649 | test_cmp expect actual | |
650 | ) | |
651 | ' | |
652 | ||
653 | # Testcase 3b, Avoid implicit rename if involved as source on other side | |
654 | # (Related to testcases 5c and 7c, also kind of 1e and 1f) | |
655 | # Commit O: z/{b,c,d} | |
656 | # Commit A: y/{b,c}, x/d | |
657 | # Commit B: z/{b,c}, w/d | |
658 | # Expected: y/{b,c}, CONFLICT:(z/d -> x/d vs. w/d) | |
659 | # NOTE: We're particularly checking that since z/d is already involved as | |
660 | # a source in a file rename on the same side of history, that we don't | |
661 | # get it involved in directory rename detection. If it were, we might | |
662 | # end up with CONFLICT:(z/d -> y/d vs. x/d vs. w/d), i.e. a | |
663 | # rename/rename/rename(1to3) conflict, which is just weird. | |
664 | test_expect_success '3b-setup: Avoid implicit rename if involved as source on current side' ' | |
665 | test_create_repo 3b && | |
666 | ( | |
667 | cd 3b && | |
668 | ||
669 | mkdir z && | |
670 | echo b >z/b && | |
671 | echo c >z/c && | |
672 | echo d >z/d && | |
673 | git add z && | |
674 | test_tick && | |
675 | git commit -m "O" && | |
676 | ||
677 | git branch O && | |
678 | git branch A && | |
679 | git branch B && | |
680 | ||
681 | git checkout A && | |
682 | mkdir y && | |
683 | mkdir x && | |
684 | git mv z/b y/ && | |
685 | git mv z/c y/ && | |
686 | git mv z/d x/ && | |
687 | rmdir z && | |
688 | test_tick && | |
689 | git commit -m "A" && | |
690 | ||
691 | git checkout B && | |
692 | mkdir w && | |
693 | git mv z/d w/ && | |
694 | test_tick && | |
695 | git commit -m "B" | |
696 | ) | |
697 | ' | |
698 | ||
699 | test_expect_success '3b-check: Avoid implicit rename if involved as source on current side' ' | |
700 | ( | |
701 | cd 3b && | |
702 | ||
703 | git checkout A^0 && | |
704 | ||
705 | test_must_fail git merge -s recursive B^0 >out && | |
706 | test_i18ngrep CONFLICT.*rename/rename.*z/d.*x/d.*w/d out && | |
707 | test_i18ngrep ! CONFLICT.*rename/rename.*y/d out && | |
708 | ||
709 | git ls-files -s >out && | |
710 | test_line_count = 5 out && | |
711 | git ls-files -u >out && | |
712 | test_line_count = 3 out && | |
713 | git ls-files -o >out && | |
714 | test_line_count = 1 out && | |
715 | ||
716 | git rev-parse >actual \ | |
717 | :0:y/b :0:y/c :1:z/d :2:x/d :3:w/d && | |
718 | git rev-parse >expect \ | |
719 | O:z/b O:z/c O:z/d O:z/d O:z/d && | |
720 | test_cmp expect actual && | |
721 | ||
722 | test_path_is_missing z/d && | |
723 | git hash-object >actual \ | |
724 | x/d w/d && | |
725 | git rev-parse >expect \ | |
726 | O:z/d O:z/d && | |
727 | test_cmp expect actual | |
728 | ) | |
729 | ' | |
730 | ||
731 | ########################################################################### | |
732 | # Rules suggested by section 3: | |
733 | # | |
734 | # Avoid directory-rename-detection for a path, if that path is the source | |
735 | # of a rename on either side of a merge. | |
736 | ########################################################################### | |
737 | ||
de632e4e EN |
738 | |
739 | ########################################################################### | |
740 | # SECTION 4: Partially renamed directory; still exists on both sides of merge | |
741 | # | |
742 | # What if we were to attempt to do directory rename detection when someone | |
743 | # "mostly" moved a directory but still left some files around, or, | |
744 | # equivalently, fully renamed a directory in one commmit and then recreated | |
745 | # that directory in a later commit adding some new files and then tried to | |
746 | # merge? | |
747 | # | |
748 | # It's hard to divine user intent in these cases, because you can make an | |
749 | # argument that, depending on the intermediate history of the side being | |
750 | # merged, that some users will want files in that directory to | |
751 | # automatically be detected and renamed, while users with a different | |
752 | # intermediate history wouldn't want that rename to happen. | |
753 | # | |
754 | # I think that it is best to simply not have directory rename detection | |
755 | # apply to such cases. My reasoning for this is four-fold: (1) it's | |
756 | # easiest for users in general to figure out what happened if we don't | |
757 | # apply directory rename detection in any such case, (2) it's an easy rule | |
758 | # to explain ["We don't do directory rename detection if the directory | |
759 | # still exists on both sides of the merge"], (3) we can get some hairy | |
760 | # edge/corner cases that would be really confusing and possibly not even | |
761 | # representable in the index if we were to even try, and [related to 3] (4) | |
762 | # attempting to resolve this issue of divining user intent by examining | |
763 | # intermediate history goes against the spirit of three-way merges and is a | |
764 | # path towards crazy corner cases that are far more complex than what we're | |
765 | # already dealing with. | |
766 | # | |
767 | # Note that the wording of the rule ("We don't do directory rename | |
768 | # detection if the directory still exists on both sides of the merge.") | |
769 | # also excludes "renaming" of a directory into a subdirectory of itself | |
770 | # (e.g. /some/dir/* -> /some/dir/subdir/*). It may be possible to carve | |
771 | # out an exception for "renaming"-beneath-itself cases without opening | |
772 | # weird edge/corner cases for other partial directory renames, but for now | |
773 | # we are keeping the rule simple. | |
774 | # | |
775 | # This section contains a test for a partially-renamed-directory case. | |
776 | ########################################################################### | |
777 | ||
778 | # Testcase 4a, Directory split, with original directory still present | |
779 | # (Related to testcase 1f) | |
780 | # Commit O: z/{b,c,d,e} | |
781 | # Commit A: y/{b,c,d}, z/e | |
782 | # Commit B: z/{b,c,d,e,f} | |
783 | # Expected: y/{b,c,d}, z/{e,f} | |
784 | # NOTE: Even though most files from z moved to y, we don't want f to follow. | |
785 | ||
786 | test_expect_success '4a-setup: Directory split, with original directory still present' ' | |
787 | test_create_repo 4a && | |
788 | ( | |
789 | cd 4a && | |
790 | ||
791 | mkdir z && | |
792 | echo b >z/b && | |
793 | echo c >z/c && | |
794 | echo d >z/d && | |
795 | echo e >z/e && | |
796 | git add z && | |
797 | test_tick && | |
798 | git commit -m "O" && | |
799 | ||
800 | git branch O && | |
801 | git branch A && | |
802 | git branch B && | |
803 | ||
804 | git checkout A && | |
805 | mkdir y && | |
806 | git mv z/b y/ && | |
807 | git mv z/c y/ && | |
808 | git mv z/d y/ && | |
809 | test_tick && | |
810 | git commit -m "A" && | |
811 | ||
812 | git checkout B && | |
813 | echo f >z/f && | |
814 | git add z/f && | |
815 | test_tick && | |
816 | git commit -m "B" | |
817 | ) | |
818 | ' | |
819 | ||
820 | test_expect_success '4a-check: Directory split, with original directory still present' ' | |
821 | ( | |
822 | cd 4a && | |
823 | ||
824 | git checkout A^0 && | |
825 | ||
826 | git merge -s recursive B^0 && | |
827 | ||
828 | git ls-files -s >out && | |
829 | test_line_count = 5 out && | |
830 | git ls-files -u >out && | |
831 | test_line_count = 0 out && | |
832 | git ls-files -o >out && | |
833 | test_line_count = 1 out && | |
834 | ||
835 | git rev-parse >actual \ | |
836 | HEAD:y/b HEAD:y/c HEAD:y/d HEAD:z/e HEAD:z/f && | |
837 | git rev-parse >expect \ | |
838 | O:z/b O:z/c O:z/d O:z/e B:z/f && | |
839 | test_cmp expect actual | |
840 | ) | |
841 | ' | |
842 | ||
843 | ########################################################################### | |
844 | # Rules suggested by section 4: | |
845 | # | |
846 | # Directory-rename-detection should be turned off for any directories (as | |
847 | # a source for renames) that exist on both sides of the merge. (The "as | |
848 | # a source for renames" clarification is due to cases like 1c where | |
849 | # the target directory exists on both sides and we do want the rename | |
850 | # detection.) But, sadly, see testcase 8b. | |
851 | ########################################################################### | |
852 | ||
c449947a EN |
853 | |
854 | ########################################################################### | |
855 | # SECTION 5: Files/directories in the way of subset of to-be-renamed paths | |
856 | # | |
857 | # Implicitly renaming files due to a detected directory rename could run | |
858 | # into problems if there are files or directories in the way of the paths | |
859 | # we want to rename. Explore such cases in this section. | |
860 | ########################################################################### | |
861 | ||
862 | # Testcase 5a, Merge directories, other side adds files to original and target | |
863 | # Commit O: z/{b,c}, y/d | |
864 | # Commit A: z/{b,c,e_1,f}, y/{d,e_2} | |
865 | # Commit B: y/{b,c,d} | |
866 | # Expected: z/e_1, y/{b,c,d,e_2,f} + CONFLICT warning | |
867 | # NOTE: While directory rename detection is active here causing z/f to | |
868 | # become y/f, we did not apply this for z/e_1 because that would | |
869 | # give us an add/add conflict for y/e_1 vs y/e_2. This problem with | |
870 | # this add/add, is that both versions of y/e are from the same side | |
871 | # of history, giving us no way to represent this conflict in the | |
872 | # index. | |
873 | ||
874 | test_expect_success '5a-setup: Merge directories, other side adds files to original and target' ' | |
875 | test_create_repo 5a && | |
876 | ( | |
877 | cd 5a && | |
878 | ||
879 | mkdir z && | |
880 | echo b >z/b && | |
881 | echo c >z/c && | |
882 | mkdir y && | |
883 | echo d >y/d && | |
884 | git add z y && | |
885 | test_tick && | |
886 | git commit -m "O" && | |
887 | ||
888 | git branch O && | |
889 | git branch A && | |
890 | git branch B && | |
891 | ||
892 | git checkout A && | |
893 | echo e1 >z/e && | |
894 | echo f >z/f && | |
895 | echo e2 >y/e && | |
896 | git add z/e z/f y/e && | |
897 | test_tick && | |
898 | git commit -m "A" && | |
899 | ||
900 | git checkout B && | |
901 | git mv z/b y/ && | |
902 | git mv z/c y/ && | |
903 | rmdir z && | |
904 | test_tick && | |
905 | git commit -m "B" | |
906 | ) | |
907 | ' | |
908 | ||
909 | test_expect_failure '5a-check: Merge directories, other side adds files to original and target' ' | |
910 | ( | |
911 | cd 5a && | |
912 | ||
913 | git checkout A^0 && | |
914 | ||
915 | test_must_fail git merge -s recursive B^0 >out && | |
916 | test_i18ngrep "CONFLICT.*implicit dir rename" out && | |
917 | ||
918 | git ls-files -s >out && | |
919 | test_line_count = 6 out && | |
920 | git ls-files -u >out && | |
921 | test_line_count = 0 out && | |
922 | git ls-files -o >out && | |
923 | test_line_count = 1 out && | |
924 | ||
925 | git rev-parse >actual \ | |
926 | :0:y/b :0:y/c :0:y/d :0:y/e :0:z/e :0:y/f && | |
927 | git rev-parse >expect \ | |
928 | O:z/b O:z/c O:y/d A:y/e A:z/e A:z/f && | |
929 | test_cmp expect actual | |
930 | ) | |
931 | ' | |
932 | ||
933 | # Testcase 5b, Rename/delete in order to get add/add/add conflict | |
934 | # (Related to testcase 8d; these may appear slightly inconsistent to users; | |
935 | # Also related to testcases 7d and 7e) | |
936 | # Commit O: z/{b,c,d_1} | |
937 | # Commit A: y/{b,c,d_2} | |
938 | # Commit B: z/{b,c,d_1,e}, y/d_3 | |
939 | # Expected: y/{b,c,e}, CONFLICT(add/add: y/d_2 vs. y/d_3) | |
940 | # NOTE: If z/d_1 in commit B were to be involved in dir rename detection, as | |
941 | # we normaly would since z/ is being renamed to y/, then this would be | |
942 | # a rename/delete (z/d_1 -> y/d_1 vs. deleted) AND an add/add/add | |
943 | # conflict of y/d_1 vs. y/d_2 vs. y/d_3. Add/add/add is not | |
944 | # representable in the index, so the existence of y/d_3 needs to | |
945 | # cause us to bail on directory rename detection for that path, falling | |
946 | # back to git behavior without the directory rename detection. | |
947 | ||
948 | test_expect_success '5b-setup: Rename/delete in order to get add/add/add conflict' ' | |
949 | test_create_repo 5b && | |
950 | ( | |
951 | cd 5b && | |
952 | ||
953 | mkdir z && | |
954 | echo b >z/b && | |
955 | echo c >z/c && | |
956 | echo d1 >z/d && | |
957 | git add z && | |
958 | test_tick && | |
959 | git commit -m "O" && | |
960 | ||
961 | git branch O && | |
962 | git branch A && | |
963 | git branch B && | |
964 | ||
965 | git checkout A && | |
966 | git rm z/d && | |
967 | git mv z y && | |
968 | echo d2 >y/d && | |
969 | git add y/d && | |
970 | test_tick && | |
971 | git commit -m "A" && | |
972 | ||
973 | git checkout B && | |
974 | mkdir y && | |
975 | echo d3 >y/d && | |
976 | echo e >z/e && | |
977 | git add y/d z/e && | |
978 | test_tick && | |
979 | git commit -m "B" | |
980 | ) | |
981 | ' | |
982 | ||
983 | test_expect_failure '5b-check: Rename/delete in order to get add/add/add conflict' ' | |
984 | ( | |
985 | cd 5b && | |
986 | ||
987 | git checkout A^0 && | |
988 | ||
989 | test_must_fail git merge -s recursive B^0 >out && | |
990 | test_i18ngrep "CONFLICT (add/add).* y/d" out && | |
991 | ||
992 | git ls-files -s >out && | |
993 | test_line_count = 5 out && | |
994 | git ls-files -u >out && | |
995 | test_line_count = 2 out && | |
996 | git ls-files -o >out && | |
997 | test_line_count = 1 out && | |
998 | ||
999 | git rev-parse >actual \ | |
1000 | :0:y/b :0:y/c :0:y/e :2:y/d :3:y/d && | |
1001 | git rev-parse >expect \ | |
1002 | O:z/b O:z/c B:z/e A:y/d B:y/d && | |
1003 | test_cmp expect actual && | |
1004 | ||
1005 | test_must_fail git rev-parse :1:y/d && | |
1006 | test_path_is_file y/d | |
1007 | ) | |
1008 | ' | |
1009 | ||
1010 | # Testcase 5c, Transitive rename would cause rename/rename/rename/add/add/add | |
1011 | # (Directory rename detection would result in transitive rename vs. | |
1012 | # rename/rename(1to2) and turn it into a rename/rename(1to3). Further, | |
1013 | # rename paths conflict with separate adds on the other side) | |
1014 | # (Related to testcases 3b and 7c) | |
1015 | # Commit O: z/{b,c}, x/d_1 | |
1016 | # Commit A: y/{b,c,d_2}, w/d_1 | |
1017 | # Commit B: z/{b,c,d_1,e}, w/d_3, y/d_4 | |
1018 | # Expected: A mess, but only a rename/rename(1to2)/add/add mess. Use the | |
1019 | # presence of y/d_4 in B to avoid doing transitive rename of | |
1020 | # x/d_1 -> z/d_1 -> y/d_1, so that the only paths we have at | |
1021 | # y/d are y/d_2 and y/d_4. We still do the move from z/e to y/e, | |
1022 | # though, because it doesn't have anything in the way. | |
1023 | ||
1024 | test_expect_success '5c-setup: Transitive rename would cause rename/rename/rename/add/add/add' ' | |
1025 | test_create_repo 5c && | |
1026 | ( | |
1027 | cd 5c && | |
1028 | ||
1029 | mkdir z && | |
1030 | echo b >z/b && | |
1031 | echo c >z/c && | |
1032 | mkdir x && | |
1033 | echo d1 >x/d && | |
1034 | git add z x && | |
1035 | test_tick && | |
1036 | git commit -m "O" && | |
1037 | ||
1038 | git branch O && | |
1039 | git branch A && | |
1040 | git branch B && | |
1041 | ||
1042 | git checkout A && | |
1043 | git mv z y && | |
1044 | echo d2 >y/d && | |
1045 | git add y/d && | |
1046 | git mv x w && | |
1047 | test_tick && | |
1048 | git commit -m "A" && | |
1049 | ||
1050 | git checkout B && | |
1051 | git mv x/d z/ && | |
1052 | mkdir w && | |
1053 | mkdir y && | |
1054 | echo d3 >w/d && | |
1055 | echo d4 >y/d && | |
1056 | echo e >z/e && | |
1057 | git add w/ y/ z/e && | |
1058 | test_tick && | |
1059 | git commit -m "B" | |
1060 | ) | |
1061 | ' | |
1062 | ||
1063 | test_expect_failure '5c-check: Transitive rename would cause rename/rename/rename/add/add/add' ' | |
1064 | ( | |
1065 | cd 5c && | |
1066 | ||
1067 | git checkout A^0 && | |
1068 | ||
1069 | test_must_fail git merge -s recursive B^0 >out && | |
1070 | test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*z/d" out && | |
1071 | test_i18ngrep "CONFLICT (add/add).* y/d" out && | |
1072 | ||
1073 | git ls-files -s >out && | |
1074 | test_line_count = 9 out && | |
1075 | git ls-files -u >out && | |
1076 | test_line_count = 6 out && | |
1077 | git ls-files -o >out && | |
1078 | test_line_count = 3 out && | |
1079 | ||
1080 | git rev-parse >actual \ | |
1081 | :0:y/b :0:y/c :0:y/e && | |
1082 | git rev-parse >expect \ | |
1083 | O:z/b O:z/c B:z/e && | |
1084 | test_cmp expect actual && | |
1085 | ||
1086 | test_must_fail git rev-parse :1:y/d && | |
1087 | git rev-parse >actual \ | |
1088 | :2:w/d :3:w/d :1:x/d :2:y/d :3:y/d :3:z/d && | |
1089 | git rev-parse >expect \ | |
1090 | O:x/d B:w/d O:x/d A:y/d B:y/d O:x/d && | |
1091 | test_cmp expect actual && | |
1092 | ||
1093 | git hash-object >actual \ | |
1094 | w/d~HEAD w/d~B^0 z/d && | |
1095 | git rev-parse >expect \ | |
1096 | O:x/d B:w/d O:x/d && | |
1097 | test_cmp expect actual && | |
1098 | test_path_is_missing x/d && | |
1099 | test_path_is_file y/d && | |
1100 | grep -q "<<<<" y/d # conflict markers should be present | |
1101 | ) | |
1102 | ' | |
1103 | ||
1104 | # Testcase 5d, Directory/file/file conflict due to directory rename | |
1105 | # Commit O: z/{b,c} | |
1106 | # Commit A: y/{b,c,d_1} | |
1107 | # Commit B: z/{b,c,d_2,f}, y/d/e | |
1108 | # Expected: y/{b,c,d/e,f}, z/d_2, CONFLICT(file/directory), y/d_1~HEAD | |
1109 | # Note: The fact that y/d/ exists in B makes us bail on directory rename | |
1110 | # detection for z/d_2, but that doesn't prevent us from applying the | |
1111 | # directory rename detection for z/f -> y/f. | |
1112 | ||
1113 | test_expect_success '5d-setup: Directory/file/file conflict due to directory rename' ' | |
1114 | test_create_repo 5d && | |
1115 | ( | |
1116 | cd 5d && | |
1117 | ||
1118 | mkdir z && | |
1119 | echo b >z/b && | |
1120 | echo c >z/c && | |
1121 | git add z && | |
1122 | test_tick && | |
1123 | git commit -m "O" && | |
1124 | ||
1125 | git branch O && | |
1126 | git branch A && | |
1127 | git branch B && | |
1128 | ||
1129 | git checkout A && | |
1130 | git mv z y && | |
1131 | echo d1 >y/d && | |
1132 | git add y/d && | |
1133 | test_tick && | |
1134 | git commit -m "A" && | |
1135 | ||
1136 | git checkout B && | |
1137 | mkdir -p y/d && | |
1138 | echo e >y/d/e && | |
1139 | echo d2 >z/d && | |
1140 | echo f >z/f && | |
1141 | git add y/d/e z/d z/f && | |
1142 | test_tick && | |
1143 | git commit -m "B" | |
1144 | ) | |
1145 | ' | |
1146 | ||
1147 | test_expect_failure '5d-check: Directory/file/file conflict due to directory rename' ' | |
1148 | ( | |
1149 | cd 5d && | |
1150 | ||
1151 | git checkout A^0 && | |
1152 | ||
1153 | test_must_fail git merge -s recursive B^0 >out && | |
1154 | test_i18ngrep "CONFLICT (file/directory).*y/d" out && | |
1155 | ||
1156 | git ls-files -s >out && | |
1157 | test_line_count = 6 out && | |
1158 | git ls-files -u >out && | |
1159 | test_line_count = 1 out && | |
1160 | git ls-files -o >out && | |
1161 | test_line_count = 2 out && | |
1162 | ||
1163 | git rev-parse >actual \ | |
1164 | :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d :0:y/d/e && | |
1165 | git rev-parse >expect \ | |
1166 | O:z/b O:z/c B:z/d B:z/f A:y/d B:y/d/e && | |
1167 | test_cmp expect actual && | |
1168 | ||
1169 | git hash-object y/d~HEAD >actual && | |
1170 | git rev-parse A:y/d >expect && | |
1171 | test_cmp expect actual | |
1172 | ) | |
1173 | ' | |
1174 | ||
1175 | ########################################################################### | |
1176 | # Rules suggested by section 5: | |
1177 | # | |
1178 | # If a subset of to-be-renamed files have a file or directory in the way, | |
1179 | # "turn off" the directory rename for those specific sub-paths, falling | |
1180 | # back to old handling. But, sadly, see testcases 8a and 8b. | |
1181 | ########################################################################### | |
1182 | ||
04550ab5 | 1183 | test_done |