directory rename detection: more involved edge/corner testcases
Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Apr 19, 2018 at 10:57 UTC
f95de9602b409b1385a1133d9be0d5e6ec8e498f
1 file changed
+396
t/t6043-merge-rename-directories.sh
+396
@@ -1516,4 +1516,400 @@ test_expect_success '6e-check: Add/add from one side' '
1516
# side of history is the one doing the renaming.
1517
###########################################################################
1518
1519
+
1520
+###########################################################################
1521
+# SECTION 7: More involved Edge/Corner cases
1522
+#
1523
+# The ruleset we have generated in the above sections seems to provide
1524
+# 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 is
1526
+# non-intuitive or suboptimal?
1527
+#
1528
+# The testcases in this section dive into cases that I've tried to craft in
1529
+# a way to find some that might be surprising to users or difficult for
1530
+# them to understand (the next section will look at non-intuitive or
1531
+# suboptimal merge results). Some of the testcases are similar to ones
1532
+# from past sections, but have been simplified to try to highlight error
1533
+# messages using a "modified" path (due to the directory rename). Are
1534
+# users okay with these?
1535
+#
1536
+# In my opinion, testcases that are difficult to understand from this
1537
+# section is due to difficulty in the testcase rather than the directory
1538
+# renaming (similar to how t6042 and t6036 have difficult resolutions due
1539
+# to the problem setup itself being complex). And I don't think the
1540
+# error messages are a problem.
1541
+#
1542
+# On the other hand, the testcases in section 8 worry me slightly more...
1543
+###########################################################################
1544
+
1545
+# Testcase 7a, rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file
1546
+# Commit O: z/{b,c}
1547
+# Commit A: y/{b,c}
1548
+# Commit B: w/b, x/c, z/d
1549
+# 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.
1551
+
1552
+test_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 &&
1556
+
1557
+ mkdir z &&
1558
+ echo b >z/b &&
1559
+ echo c >z/c &&
1560
+ git add z &&
1561
+ test_tick &&
1562
+ git commit -m "O" &&
1563
+
1564
+ git branch O &&
1565
+ git branch A &&
1566
+ git branch B &&
1567
+
1568
+ git checkout A &&
1569
+ git mv z y &&
1570
+ test_tick &&
1571
+ git commit -m "A" &&
1572
+
1573
+ 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
+'
1584
+
1585
+test_expect_failure '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' '
1586
+ (
1587
+ cd 7a &&
1588
+
1589
+ git checkout A^0 &&
1590
+
1591
+ 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 &&
1594
+
1595
+ 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 &&
1601
+
1602
+ 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 &&
1607
+
1608
+ 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 actual
1613
+ )
1614
+'
1615
+
1616
+# Testcase 7b, rename/rename(2to1), but only due to transitive rename
1617
+# (Related to testcase 1d)
1618
+# Commit O: z/{b,c}, x/d_1, w/d_2
1619
+# Commit A: y/{b,c,d_2}, x/d_1
1620
+# Commit B: z/{b,c,d_1}, w/d_2
1621
+# Expected: y/{b,c}, CONFLICT(rename/rename(2to1): x/d_1, w/d_2 -> y_d)
1622
+
1623
+test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive rename' '
1624
+ test_create_repo 7b &&
1625
+ (
1626
+ cd 7b &&
1627
+
1628
+ 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" &&
1638
+
1639
+ git branch O &&
1640
+ git branch A &&
1641
+ git branch B &&
1642
+
1643
+ git checkout A &&
1644
+ git mv z y &&
1645
+ git mv w/d y/ &&
1646
+ test_tick &&
1647
+ git commit -m "A" &&
1648
+
1649
+ git checkout B &&
1650
+ git mv x/d z/ &&
1651
+ rmdir x &&
1652
+ test_tick &&
1653
+ git commit -m "B"
1654
+ )
1655
+'
1656
+
1657
+test_expect_failure '7b-check: rename/rename(2to1), but only due to transitive rename' '
1658
+ (
1659
+ cd 7b &&
1660
+
1661
+ git checkout A^0 &&
1662
+
1663
+ test_must_fail git merge -s recursive B^0 >out &&
1664
+ test_i18ngrep "CONFLICT (rename/rename)" out &&
1665
+
1666
+ 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 &&
1672
+
1673
+ 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 &&
1678
+
1679
+ test_path_is_missing y/d &&
1680
+ test_path_is_file y/d~HEAD &&
1681
+ test_path_is_file y/d~B^0 &&
1682
+
1683
+ 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 actual
1688
+ )
1689
+'
1690
+
1691
+# Testcase 7c, rename/rename(1to...2or3); transitive rename may add complexity
1692
+# (Related to testcases 3b and 5c)
1693
+# Commit O: z/{b,c}, x/d
1694
+# Commit A: y/{b,c}, w/d
1695
+# 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 report
1698
+# neither CONFLICT(x/d -> w/d vs. z/d)
1699
+# nor CONFLiCT x/d -> w/d vs. y/d vs. z/d)
1700
+
1701
+test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may add complexity' '
1702
+ test_create_repo 7c &&
1703
+ (
1704
+ cd 7c &&
1705
+
1706
+ 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" &&
1714
+
1715
+ git branch O &&
1716
+ git branch A &&
1717
+ git branch B &&
1718
+
1719
+ git checkout A &&
1720
+ git mv z y &&
1721
+ git mv x w &&
1722
+ test_tick &&
1723
+ git commit -m "A" &&
1724
+
1725
+ git checkout B &&
1726
+ git mv x/d z/ &&
1727
+ rmdir x &&
1728
+ test_tick &&
1729
+ git commit -m "B"
1730
+ )
1731
+'
1732
+
1733
+test_expect_failure '7c-check: rename/rename(1to...2or3); transitive rename may add complexity' '
1734
+ (
1735
+ cd 7c &&
1736
+
1737
+ git checkout A^0 &&
1738
+
1739
+ test_must_fail git merge -s recursive B^0 >out &&
1740
+ test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out &&
1741
+
1742
+ 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 &&
1748
+
1749
+ 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 actual
1754
+ )
1755
+'
1756
+
1757
+# 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/d
1760
+# 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)
1764
+
1765
+test_expect_success '7d-setup: transitive rename involved in rename/delete; how is it reported?' '
1766
+ test_create_repo 7d &&
1767
+ (
1768
+ cd 7d &&
1769
+
1770
+ 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" &&
1778
+
1779
+ git branch O &&
1780
+ git branch A &&
1781
+ git branch B &&
1782
+
1783
+ git checkout A &&
1784
+ git mv z y &&
1785
+ git rm -rf x &&
1786
+ test_tick &&
1787
+ git commit -m "A" &&
1788
+
1789
+ git checkout B &&
1790
+ git mv x/d z/ &&
1791
+ rmdir x &&
1792
+ test_tick &&
1793
+ git commit -m "B"
1794
+ )
1795
+'
1796
+
1797
+test_expect_failure '7d-check: transitive rename involved in rename/delete; how is it reported?' '
1798
+ (
1799
+ cd 7d &&
1800
+
1801
+ git checkout A^0 &&
1802
+
1803
+ test_must_fail git merge -s recursive B^0 >out &&
1804
+ test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
1805
+
1806
+ 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 &&
1812
+
1813
+ 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 actual
1818
+ )
1819
+'
1820
+
1821
+# Testcase 7e, transitive rename in rename/delete AND dirs in the way
1822
+# (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_1
1825
+# Commit A: y/{b,c,d/g}, x/d/f
1826
+# Commit B: z/{b,c,d_1}
1827
+# Expected: rename/delete(x/d_1->y/d_1 vs. None) + D/F conflict on y/d
1828
+# y/{b,c,d/g}, y/d_1~B^0, x/d/f
1829
+
1830
+# NOTE: The main path of interest here is d_1 and where it ends up, but
1831
+# this is actually a case that has two potential directory renames
1832
+# involved and D/F conflict(s), so it makes sense to walk through
1833
+# 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 on
1837
+# 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 it
1841
+# to y/, so maybe everything should move not from x/ to z/, but
1842
+# from x/ to z/ to y/. Doing so might make sense from the logic so
1843
+# far, but note that commit A had both an x/ and a y/; it did the
1844
+# renaming of z/ to y/ and created x/d/f and it clearly made these
1845
+# things separate, so it doesn't make much sense to push these
1846
+# together. Doing so is what I'd call a doubly transitive rename;
1847
+# see testcases 9c and 9d for further discussion of this issue and
1848
+# how it's resolved.
1849
+
1850
+test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in the way' '
1851
+ test_create_repo 7e &&
1852
+ (
1853
+ cd 7e &&
1854
+
1855
+ 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" &&
1863
+
1864
+ git branch O &&
1865
+ git branch A &&
1866
+ git branch B &&
1867
+
1868
+ 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" &&
1878
+
1879
+ git checkout B &&
1880
+ git mv x/d z/ &&
1881
+ rmdir x &&
1882
+ test_tick &&
1883
+ git commit -m "B"
1884
+ )
1885
+'
1886
+
1887
+test_expect_failure '7e-check: transitive rename in rename/delete AND dirs in the way' '
1888
+ (
1889
+ cd 7e &&
1890
+
1891
+ git checkout A^0 &&
1892
+
1893
+ test_must_fail git merge -s recursive B^0 >out &&
1894
+ test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
1895
+
1896
+ 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 &&
1902
+
1903
+ 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 &&
1908
+
1909
+ git hash-object y/d~B^0 >actual &&
1910
+ git rev-parse O:x/d >expect &&
1911
+ test_cmp expect actual
1912
+ )
1913
+'
1914
+
1915
test_done