1#!/bin/sh 2 3test_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 41test_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 72test_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 106test_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 139test_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 167test_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 197test_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 229test_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 266test_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 313test_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 344test_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 371test_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 410test_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 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 459test_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 491test_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 520test_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 553test_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 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 601test_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 634test_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. 664test_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 699test_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 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 786test_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 820test_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 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 874test_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 909test_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 948test_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 983test_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 &&10041005 test_must_fail git rev-parse :1:y/d &&1006 test_path_is_file y/d1007 )1008'10091010# Testcase 5c, Transitive rename would cause rename/rename/rename/add/add/add1011# (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_11016# Commit A: y/{b,c,d_2}, w/d_11017# Commit B: z/{b,c,d_1,e}, w/d_3, y/d_41018# Expected: A mess, but only a rename/rename(1to2)/add/add mess. Use the1019# presence of y/d_4 in B to avoid doing transitive rename of1020# x/d_1 -> z/d_1 -> y/d_1, so that the only paths we have at1021# 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.10231024test_expect_success '5c-setup: Transitive rename would cause rename/rename/rename/add/add/add''1025 test_create_repo 5c &&1026 (1027 cd 5c &&10281029 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" &&10371038 git branch O &&1039 git branch A &&1040 git branch B &&10411042 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" &&10491050 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'10621063test_expect_failure '5c-check: Transitive rename would cause rename/rename/rename/add/add/add''1064 (1065 cd 5c &&10661067 git checkout A^0 &&10681069 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 &&10721073 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 &&10791080 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 &&10851086 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 &&10921093 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 present1101 )1102'11031104# Testcase 5d, Directory/file/file conflict due to directory rename1105# Commit O: z/{b,c}1106# Commit A: y/{b,c,d_1}1107# Commit B: z/{b,c,d_2,f}, y/d/e1108# Expected: y/{b,c,d/e,f}, z/d_2, CONFLICT(file/directory), y/d_1~HEAD1109# Note: The fact that y/d/ exists in B makes us bail on directory rename1110# detection for z/d_2, but that doesn't prevent us from applying the1111# directory rename detection for z/f -> y/f.11121113test_expect_success '5d-setup: Directory/file/file conflict due to directory rename''1114 test_create_repo 5d &&1115 (1116 cd 5d &&11171118 mkdir z &&1119 echo b >z/b &&1120 echo c >z/c &&1121 git add z &&1122 test_tick &&1123 git commit -m "O" &&11241125 git branch O &&1126 git branch A &&1127 git branch B &&11281129 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" &&11351136 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'11461147test_expect_failure '5d-check: Directory/file/file conflict due to directory rename''1148 (1149 cd 5d &&11501151 git checkout A^0 &&11521153 test_must_fail git merge -s recursive B^0 >out &&1154 test_i18ngrep "CONFLICT (file/directory).*y/d" out &&11551156 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 &&11621163 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 &&11681169 git hash-object y/d~HEAD >actual &&1170 git rev-parse A:y/d >expect &&1171 test_cmp expect actual1172 )1173'11741175###########################################################################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, falling1180# back to old handling. But, sadly, see testcases 8a and 8b.1181###########################################################################118211831184###########################################################################1185# SECTION 6: Same side of the merge was the one that did the rename1186#1187# It may sound obvious that you only want to apply implicit directory1188# renames to directories if the _other_ side of history did the renaming.1189# If you did make an implementation that didn't explicitly enforce this1190# rule, the majority of cases that would fall under this section would1191# also be solved by following the rules from the above sections. But1192# there are still a few that stick out, so this section covers them just1193# to make sure we also get them right.1194###########################################################################11951196# Testcase 6a, Tricky rename/delete1197# Commit O: z/{b,c,d}1198# Commit A: z/b1199# Commit B: y/{b,c}, z/d1200# Expected: y/b, CONFLICT(rename/delete, z/c -> y/c vs. NULL)1201# Note: We're just checking here that the rename of z/b and z/c to put1202# them under y/ doesn't accidentally catch z/d and make it look like1203# it is also involved in a rename/delete conflict.12041205test_expect_success '6a-setup: Tricky rename/delete''1206 test_create_repo 6a &&1207 (1208 cd 6a &&12091210 mkdir z &&1211 echo b >z/b &&1212 echo c >z/c &&1213 echo d >z/d &&1214 git add z &&1215 test_tick &&1216 git commit -m "O" &&12171218 git branch O &&1219 git branch A &&1220 git branch B &&12211222 git checkout A &&1223 git rm z/c &&1224 git rm z/d &&1225 test_tick &&1226 git commit -m "A" &&12271228 git checkout B &&1229 mkdir y &&1230 git mv z/b y/ &&1231 git mv z/c y/ &&1232 test_tick &&1233 git commit -m "B"1234 )1235'12361237test_expect_success '6a-check: Tricky rename/delete''1238 (1239 cd 6a &&12401241 git checkout A^0 &&12421243 test_must_fail git merge -s recursive B^0 >out &&1244 test_i18ngrep "CONFLICT (rename/delete).*z/c.*y/c" out &&12451246 git ls-files -s >out &&1247 test_line_count = 2 out &&1248 git ls-files -u >out &&1249 test_line_count = 1 out &&1250 git ls-files -o >out &&1251 test_line_count = 1 out &&12521253 git rev-parse >actual \1254 :0:y/b :3:y/c &&1255 git rev-parse >expect \1256 O:z/b O:z/c &&1257 test_cmp expect actual1258 )1259'12601261# Testcase 6b, Same rename done on both sides1262# (Related to testcases 6c and 8e)1263# Commit O: z/{b,c}1264# Commit A: y/{b,c}1265# Commit B: y/{b,c}, z/d1266# Expected: y/{b,c}, z/d1267# Note: If we did directory rename detection here, we'd move z/d into y/,1268# but B did that rename and still decided to put the file into z/,1269# so we probably shouldn't apply directory rename detection for it.12701271test_expect_success '6b-setup: Same rename done on both sides''1272 test_create_repo 6b &&1273 (1274 cd 6b &&12751276 mkdir z &&1277 echo b >z/b &&1278 echo c >z/c &&1279 git add z &&1280 test_tick &&1281 git commit -m "O" &&12821283 git branch O &&1284 git branch A &&1285 git branch B &&12861287 git checkout A &&1288 git mv z y &&1289 test_tick &&1290 git commit -m "A" &&12911292 git checkout B &&1293 git mv z y &&1294 mkdir z &&1295 echo d >z/d &&1296 git add z/d &&1297 test_tick &&1298 git commit -m "B"1299 )1300'13011302test_expect_success '6b-check: Same rename done on both sides''1303 (1304 cd 6b &&13051306 git checkout A^0 &&13071308 git merge -s recursive B^0 &&13091310 git ls-files -s >out &&1311 test_line_count = 3 out &&1312 git ls-files -u >out &&1313 test_line_count = 0 out &&1314 git ls-files -o >out &&1315 test_line_count = 1 out &&13161317 git rev-parse >actual \1318 HEAD:y/b HEAD:y/c HEAD:z/d &&1319 git rev-parse >expect \1320 O:z/b O:z/c B:z/d &&1321 test_cmp expect actual1322 )1323'13241325# Testcase 6c, Rename only done on same side1326# (Related to testcases 6b and 8e)1327# Commit O: z/{b,c}1328# Commit A: z/{b,c} (no change)1329# Commit B: y/{b,c}, z/d1330# Expected: y/{b,c}, z/d1331# NOTE: Seems obvious, but just checking that the implementation doesn't1332# "accidentally detect a rename" and give us y/{b,c,d}.13331334test_expect_success '6c-setup: Rename only done on same side''1335 test_create_repo 6c &&1336 (1337 cd 6c &&13381339 mkdir z &&1340 echo b >z/b &&1341 echo c >z/c &&1342 git add z &&1343 test_tick &&1344 git commit -m "O" &&13451346 git branch O &&1347 git branch A &&1348 git branch B &&13491350 git checkout A &&1351 test_tick &&1352 git commit --allow-empty -m "A" &&13531354 git checkout B &&1355 git mv z y &&1356 mkdir z &&1357 echo d >z/d &&1358 git add z/d &&1359 test_tick &&1360 git commit -m "B"1361 )1362'13631364test_expect_success '6c-check: Rename only done on same side''1365 (1366 cd 6c &&13671368 git checkout A^0 &&13691370 git merge -s recursive B^0 &&13711372 git ls-files -s >out &&1373 test_line_count = 3 out &&1374 git ls-files -u >out &&1375 test_line_count = 0 out &&1376 git ls-files -o >out &&1377 test_line_count = 1 out &&13781379 git rev-parse >actual \1380 HEAD:y/b HEAD:y/c HEAD:z/d &&1381 git rev-parse >expect \1382 O:z/b O:z/c B:z/d &&1383 test_cmp expect actual1384 )1385'13861387# Testcase 6d, We don't always want transitive renaming1388# (Related to testcase 1c)1389# Commit O: z/{b,c}, x/d1390# Commit A: z/{b,c}, x/d (no change)1391# Commit B: y/{b,c}, z/d1392# Expected: y/{b,c}, z/d1393# NOTE: Again, this seems obvious but just checking that the implementation1394# doesn't "accidentally detect a rename" and give us y/{b,c,d}.13951396test_expect_success '6d-setup: We do not always want transitive renaming''1397 test_create_repo 6d &&1398 (1399 cd 6d &&14001401 mkdir z &&1402 echo b >z/b &&1403 echo c >z/c &&1404 mkdir x &&1405 echo d >x/d &&1406 git add z x &&1407 test_tick &&1408 git commit -m "O" &&14091410 git branch O &&1411 git branch A &&1412 git branch B &&14131414 git checkout A &&1415 test_tick &&1416 git commit --allow-empty -m "A" &&14171418 git checkout B &&1419 git mv z y &&1420 git mv x z &&1421 test_tick &&1422 git commit -m "B"1423 )1424'14251426test_expect_success '6d-check: We do not always want transitive renaming''1427 (1428 cd 6d &&14291430 git checkout A^0 &&14311432 git merge -s recursive B^0 &&14331434 git ls-files -s >out &&1435 test_line_count = 3 out &&1436 git ls-files -u >out &&1437 test_line_count = 0 out &&1438 git ls-files -o >out &&1439 test_line_count = 1 out &&14401441 git rev-parse >actual \1442 HEAD:y/b HEAD:y/c HEAD:z/d &&1443 git rev-parse >expect \1444 O:z/b O:z/c O:x/d &&1445 test_cmp expect actual1446 )1447'14481449# Testcase 6e, Add/add from one-side1450# Commit O: z/{b,c}1451# Commit A: z/{b,c} (no change)1452# Commit B: y/{b,c,d_1}, z/d_21453# Expected: y/{b,c,d_1}, z/d_21454# NOTE: Again, this seems obvious but just checking that the implementation1455# doesn't "accidentally detect a rename" and give us y/{b,c} +1456# add/add conflict on y/d_1 vs y/d_2.14571458test_expect_success '6e-setup: Add/add from one side''1459 test_create_repo 6e &&1460 (1461 cd 6e &&14621463 mkdir z &&1464 echo b >z/b &&1465 echo c >z/c &&1466 git add z &&1467 test_tick &&1468 git commit -m "O" &&14691470 git branch O &&1471 git branch A &&1472 git branch B &&14731474 git checkout A &&1475 test_tick &&1476 git commit --allow-empty -m "A" &&14771478 git checkout B &&1479 git mv z y &&1480 echo d1 > y/d &&1481 mkdir z &&1482 echo d2 > z/d &&1483 git add y/d z/d &&1484 test_tick &&1485 git commit -m "B"1486 )1487'14881489test_expect_success '6e-check: Add/add from one side''1490 (1491 cd 6e &&14921493 git checkout A^0 &&14941495 git merge -s recursive B^0 &&14961497 git ls-files -s >out &&1498 test_line_count = 4 out &&1499 git ls-files -u >out &&1500 test_line_count = 0 out &&1501 git ls-files -o >out &&1502 test_line_count = 1 out &&15031504 git rev-parse >actual \1505 HEAD:y/b HEAD:y/c HEAD:y/d HEAD:z/d &&1506 git rev-parse >expect \1507 O:z/b O:z/c B:y/d B:z/d &&1508 test_cmp expect actual1509 )1510'15111512###########################################################################1513# Rules suggested by section 6:1514#1515# Only apply implicit directory renames to directories if the other1516# side of history is the one doing the renaming.1517###########################################################################151815191520###########################################################################1521# SECTION 7: More involved Edge/Corner cases1522#1523# The ruleset we have generated in the above sections seems to provide1524# well-defined merges. But can we find edge/corner cases that either (a)1525# are harder for users to understand, or (b) have a resolution that is1526# non-intuitive or suboptimal?1527#1528# The testcases in this section dive into cases that I've tried to craft in1529# a way to find some that might be surprising to users or difficult for1530# them to understand (the next section will look at non-intuitive or1531# suboptimal merge results). Some of the testcases are similar to ones1532# from past sections, but have been simplified to try to highlight error1533# messages using a "modified" path (due to the directory rename). Are1534# users okay with these?1535#1536# In my opinion, testcases that are difficult to understand from this1537# section is due to difficulty in the testcase rather than the directory1538# renaming (similar to how t6042 and t6036 have difficult resolutions due1539# to the problem setup itself being complex). And I don't think the1540# error messages are a problem.1541#1542# On the other hand, the testcases in section 8 worry me slightly more...1543###########################################################################15441545# Testcase 7a, rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file1546# Commit O: z/{b,c}1547# Commit A: y/{b,c}1548# Commit B: w/b, x/c, z/d1549# Expected: y/d, CONFLICT(rename/rename for both z/b and z/c)1550# NOTE: There's a rename of z/ here, y/ has more renames, so z/d -> y/d.15511552test_expect_success '7a-setup: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file''1553 test_create_repo 7a &&1554 (1555 cd 7a &&15561557 mkdir z &&1558 echo b >z/b &&1559 echo c >z/c &&1560 git add z &&1561 test_tick &&1562 git commit -m "O" &&15631564 git branch O &&1565 git branch A &&1566 git branch B &&15671568 git checkout A &&1569 git mv z y &&1570 test_tick &&1571 git commit -m "A" &&15721573 git checkout B &&1574 mkdir w &&1575 mkdir x &&1576 git mv z/b w/ &&1577 git mv z/c x/ &&1578 echo d > z/d &&1579 git add z/d &&1580 test_tick &&1581 git commit -m "B"1582 )1583'15841585test_expect_failure '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file''1586 (1587 cd 7a &&15881589 git checkout A^0 &&15901591 test_must_fail git merge -s recursive B^0 >out &&1592 test_i18ngrep "CONFLICT (rename/rename).*z/b.*y/b.*w/b" out &&1593 test_i18ngrep "CONFLICT (rename/rename).*z/c.*y/c.*x/c" out &&15941595 git ls-files -s >out &&1596 test_line_count = 7 out &&1597 git ls-files -u >out &&1598 test_line_count = 6 out &&1599 git ls-files -o >out &&1600 test_line_count = 1 out &&16011602 git rev-parse >actual \1603 :1:z/b :2:y/b :3:w/b :1:z/c :2:y/c :3:x/c :0:y/d &&1604 git rev-parse >expect \1605 O:z/b O:z/b O:z/b O:z/c O:z/c O:z/c B:z/d &&1606 test_cmp expect actual &&16071608 git hash-object >actual \1609 y/b w/b y/c x/c &&1610 git rev-parse >expect \1611 O:z/b O:z/b O:z/c O:z/c &&1612 test_cmp expect actual1613 )1614'16151616# Testcase 7b, rename/rename(2to1), but only due to transitive rename1617# (Related to testcase 1d)1618# Commit O: z/{b,c}, x/d_1, w/d_21619# Commit A: y/{b,c,d_2}, x/d_11620# Commit B: z/{b,c,d_1}, w/d_21621# Expected: y/{b,c}, CONFLICT(rename/rename(2to1): x/d_1, w/d_2 -> y_d)16221623test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive rename''1624 test_create_repo 7b &&1625 (1626 cd 7b &&16271628 mkdir z &&1629 mkdir x &&1630 mkdir w &&1631 echo b >z/b &&1632 echo c >z/c &&1633 echo d1 > x/d &&1634 echo d2 > w/d &&1635 git add z x w &&1636 test_tick &&1637 git commit -m "O" &&16381639 git branch O &&1640 git branch A &&1641 git branch B &&16421643 git checkout A &&1644 git mv z y &&1645 git mv w/d y/ &&1646 test_tick &&1647 git commit -m "A" &&16481649 git checkout B &&1650 git mv x/d z/ &&1651 rmdir x &&1652 test_tick &&1653 git commit -m "B"1654 )1655'16561657test_expect_failure '7b-check: rename/rename(2to1), but only due to transitive rename''1658 (1659 cd 7b &&16601661 git checkout A^0 &&16621663 test_must_fail git merge -s recursive B^0 >out &&1664 test_i18ngrep "CONFLICT (rename/rename)" out &&16651666 git ls-files -s >out &&1667 test_line_count = 4 out &&1668 git ls-files -u >out &&1669 test_line_count = 2 out &&1670 git ls-files -o >out &&1671 test_line_count = 3 out &&16721673 git rev-parse >actual \1674 :0:y/b :0:y/c :2:y/d :3:y/d &&1675 git rev-parse >expect \1676 O:z/b O:z/c O:w/d O:x/d &&1677 test_cmp expect actual &&16781679 test_path_is_missing y/d &&1680 test_path_is_file y/d~HEAD &&1681 test_path_is_file y/d~B^0 &&16821683 git hash-object >actual \1684 y/d~HEAD y/d~B^0 &&1685 git rev-parse >expect \1686 O:w/d O:x/d &&1687 test_cmp expect actual1688 )1689'16901691# Testcase 7c, rename/rename(1to...2or3); transitive rename may add complexity1692# (Related to testcases 3b and 5c)1693# Commit O: z/{b,c}, x/d1694# Commit A: y/{b,c}, w/d1695# Commit B: z/{b,c,d}1696# Expected: y/{b,c}, CONFLICT(x/d -> w/d vs. y/d)1697# NOTE: z/ was renamed to y/ so we do want to report1698# neither CONFLICT(x/d -> w/d vs. z/d)1699# nor CONFLiCT x/d -> w/d vs. y/d vs. z/d)17001701test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may add complexity''1702 test_create_repo 7c &&1703 (1704 cd 7c &&17051706 mkdir z &&1707 echo b >z/b &&1708 echo c >z/c &&1709 mkdir x &&1710 echo d >x/d &&1711 git add z x &&1712 test_tick &&1713 git commit -m "O" &&17141715 git branch O &&1716 git branch A &&1717 git branch B &&17181719 git checkout A &&1720 git mv z y &&1721 git mv x w &&1722 test_tick &&1723 git commit -m "A" &&17241725 git checkout B &&1726 git mv x/d z/ &&1727 rmdir x &&1728 test_tick &&1729 git commit -m "B"1730 )1731'17321733test_expect_failure '7c-check: rename/rename(1to...2or3); transitive rename may add complexity''1734 (1735 cd 7c &&17361737 git checkout A^0 &&17381739 test_must_fail git merge -s recursive B^0 >out &&1740 test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out &&17411742 git ls-files -s >out &&1743 test_line_count = 5 out &&1744 git ls-files -u >out &&1745 test_line_count = 3 out &&1746 git ls-files -o >out &&1747 test_line_count = 1 out &&17481749 git rev-parse >actual \1750 :0:y/b :0:y/c :1:x/d :2:w/d :3:y/d &&1751 git rev-parse >expect \1752 O:z/b O:z/c O:x/d O:x/d O:x/d &&1753 test_cmp expect actual1754 )1755'17561757# Testcase 7d, transitive rename involved in rename/delete; how is it reported?1758# (Related somewhat to testcases 5b and 8d)1759# Commit O: z/{b,c}, x/d1760# Commit A: y/{b,c}1761# Commit B: z/{b,c,d}1762# Expected: y/{b,c}, CONFLICT(delete x/d vs rename to y/d)1763# NOTE: z->y so NOT CONFLICT(delete x/d vs rename to z/d)17641765test_expect_success '7d-setup: transitive rename involved in rename/delete; how is it reported?''1766 test_create_repo 7d &&1767 (1768 cd 7d &&17691770 mkdir z &&1771 echo b >z/b &&1772 echo c >z/c &&1773 mkdir x &&1774 echo d >x/d &&1775 git add z x &&1776 test_tick &&1777 git commit -m "O" &&17781779 git branch O &&1780 git branch A &&1781 git branch B &&17821783 git checkout A &&1784 git mv z y &&1785 git rm -rf x &&1786 test_tick &&1787 git commit -m "A" &&17881789 git checkout B &&1790 git mv x/d z/ &&1791 rmdir x &&1792 test_tick &&1793 git commit -m "B"1794 )1795'17961797test_expect_failure '7d-check: transitive rename involved in rename/delete; how is it reported?''1798 (1799 cd 7d &&18001801 git checkout A^0 &&18021803 test_must_fail git merge -s recursive B^0 >out &&1804 test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&18051806 git ls-files -s >out &&1807 test_line_count = 3 out &&1808 git ls-files -u >out &&1809 test_line_count = 1 out &&1810 git ls-files -o >out &&1811 test_line_count = 1 out &&18121813 git rev-parse >actual \1814 :0:y/b :0:y/c :3:y/d &&1815 git rev-parse >expect \1816 O:z/b O:z/c O:x/d &&1817 test_cmp expect actual1818 )1819'18201821# Testcase 7e, transitive rename in rename/delete AND dirs in the way1822# (Very similar to 'both rename source and destination involved in D/F conflict' from t6022-merge-rename.sh)1823# (Also related to testcases 9c and 9d)1824# Commit O: z/{b,c}, x/d_11825# Commit A: y/{b,c,d/g}, x/d/f1826# Commit B: z/{b,c,d_1}1827# Expected: rename/delete(x/d_1->y/d_1 vs. None) + D/F conflict on y/d1828# y/{b,c,d/g}, y/d_1~B^0, x/d/f18291830# NOTE: The main path of interest here is d_1 and where it ends up, but1831# this is actually a case that has two potential directory renames1832# involved and D/F conflict(s), so it makes sense to walk through1833# each step.1834#1835# Commit A renames z/ -> y/. Thus everything that B adds to z/1836# should be instead moved to y/. This gives us the D/F conflict on1837# y/d because x/d_1 -> z/d_1 -> y/d_1 conflicts with y/d/g.1838#1839# Further, commit B renames x/ -> z/, thus everything A adds to x/1840# should instead be moved to z/...BUT we removed z/ and renamed it1841# to y/, so maybe everything should move not from x/ to z/, but1842# from x/ to z/ to y/. Doing so might make sense from the logic so1843# far, but note that commit A had both an x/ and a y/; it did the1844# renaming of z/ to y/ and created x/d/f and it clearly made these1845# things separate, so it doesn't make much sense to push these1846# together. Doing so is what I'd call a doubly transitive rename;1847# see testcases 9c and 9d for further discussion of this issue and1848# how it's resolved.18491850test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in the way''1851 test_create_repo 7e &&1852 (1853 cd 7e &&18541855 mkdir z &&1856 echo b >z/b &&1857 echo c >z/c &&1858 mkdir x &&1859 echo d1 >x/d &&1860 git add z x &&1861 test_tick &&1862 git commit -m "O" &&18631864 git branch O &&1865 git branch A &&1866 git branch B &&18671868 git checkout A &&1869 git mv z y &&1870 git rm x/d &&1871 mkdir -p x/d &&1872 mkdir -p y/d &&1873 echo f >x/d/f &&1874 echo g >y/d/g &&1875 git add x/d/f y/d/g &&1876 test_tick &&1877 git commit -m "A" &&18781879 git checkout B &&1880 git mv x/d z/ &&1881 rmdir x &&1882 test_tick &&1883 git commit -m "B"1884 )1885'18861887test_expect_failure '7e-check: transitive rename in rename/delete AND dirs in the way''1888 (1889 cd 7e &&18901891 git checkout A^0 &&18921893 test_must_fail git merge -s recursive B^0 >out &&1894 test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&18951896 git ls-files -s >out &&1897 test_line_count = 5 out &&1898 git ls-files -u >out &&1899 test_line_count = 1 out &&1900 git ls-files -o >out &&1901 test_line_count = 2 out &&19021903 git rev-parse >actual \1904 :0:x/d/f :0:y/d/g :0:y/b :0:y/c :3:y/d &&1905 git rev-parse >expect \1906 A:x/d/f A:y/d/g O:z/b O:z/c O:x/d &&1907 test_cmp expect actual &&19081909 git hash-object y/d~B^0 >actual &&1910 git rev-parse O:x/d >expect &&1911 test_cmp expect actual1912 )1913'19141915test_done