Show More
@@ -962,6 +962,26 impl<'on_disk> DirstateMap<'on_disk> { | |||
|
962 | 962 | } |
|
963 | 963 | } |
|
964 | 964 | |
|
965 | /// Sets the parameters for resetting a dirstate entry | |
|
966 | pub struct DirstateEntryReset<'a> { | |
|
967 | /// Which entry are we resetting | |
|
968 | pub filename: &'a HgPath, | |
|
969 | /// Whether the entry is tracked in the working copy | |
|
970 | pub wc_tracked: bool, | |
|
971 | /// Whether the entry is tracked in p1 | |
|
972 | pub p1_tracked: bool, | |
|
973 | /// Whether the entry has merge information | |
|
974 | pub p2_info: bool, | |
|
975 | /// Whether the entry's mtime should be trusted | |
|
976 | pub has_meaningful_mtime: bool, | |
|
977 | /// Information from the parent file data (from the manifest) | |
|
978 | pub parent_file_data_opt: Option<ParentFileData>, | |
|
979 | /// Set this to `true` if you are *certain* that there is no old entry for | |
|
980 | /// this filename. Yield better performance in cases where we do a lot | |
|
981 | /// of additions to the dirstate. | |
|
982 | pub from_empty: bool, | |
|
983 | } | |
|
984 | ||
|
965 | 985 | type DebugDirstateTuple<'a> = (&'a HgPath, (u8, i32, i32, i32)); |
|
966 | 986 | |
|
967 | 987 | impl OwningDirstateMap { |
@@ -1048,28 +1068,31 impl OwningDirstateMap { | |||
|
1048 | 1068 | |
|
1049 | 1069 | pub fn reset_state( |
|
1050 | 1070 | &mut self, |
|
1051 | filename: &HgPath, | |
|
1052 | wc_tracked: bool, | |
|
1053 | p1_tracked: bool, | |
|
1054 | p2_info: bool, | |
|
1055 | has_meaningful_mtime: bool, | |
|
1056 | parent_file_data_opt: Option<ParentFileData>, | |
|
1071 | reset: DirstateEntryReset, | |
|
1057 | 1072 | ) -> Result<(), DirstateError> { |
|
1058 | if !(p1_tracked || p2_info || wc_tracked) { | |
|
1059 | self.drop_entry_and_copy_source(filename)?; | |
|
1073 | if !(reset.p1_tracked || reset.p2_info || reset.wc_tracked) { | |
|
1074 | self.drop_entry_and_copy_source(reset.filename)?; | |
|
1060 | 1075 | return Ok(()); |
|
1061 | 1076 | } |
|
1062 | self.copy_map_remove(filename)?; | |
|
1063 | let old_entry_opt = self.get(filename)?; | |
|
1077 | if !reset.from_empty { | |
|
1078 | self.copy_map_remove(reset.filename)?; | |
|
1079 | } | |
|
1080 | ||
|
1081 | let old_entry_opt = if reset.from_empty { | |
|
1082 | None | |
|
1083 | } else { | |
|
1084 | self.get(reset.filename)? | |
|
1085 | }; | |
|
1086 | ||
|
1064 | 1087 | self.with_dmap_mut(|map| { |
|
1065 | 1088 | map.reset_state( |
|
1066 | filename, | |
|
1089 | reset.filename, | |
|
1067 | 1090 | old_entry_opt, |
|
1068 | wc_tracked, | |
|
1069 | p1_tracked, | |
|
1070 | p2_info, | |
|
1071 | has_meaningful_mtime, | |
|
1072 | parent_file_data_opt, | |
|
1091 | reset.wc_tracked, | |
|
1092 | reset.p1_tracked, | |
|
1093 | reset.p2_info, | |
|
1094 | reset.has_meaningful_mtime, | |
|
1095 | reset.parent_file_data_opt, | |
|
1073 | 1096 | ) |
|
1074 | 1097 | }) |
|
1075 | 1098 | } |
@@ -1643,39 +1666,79 mod tests { | |||
|
1643 | 1666 | // A file that was just added |
|
1644 | 1667 | map.set_tracked(p(b"some/nested/path"))?; |
|
1645 | 1668 | // This has no information, the dirstate should ignore it |
|
1646 | map.reset_state(p(b"some/file"), false, false, false, false, None)?; | |
|
1669 | let reset = DirstateEntryReset { | |
|
1670 | filename: p(b"some/file"), | |
|
1671 | wc_tracked: false, | |
|
1672 | p1_tracked: false, | |
|
1673 | p2_info: false, | |
|
1674 | has_meaningful_mtime: false, | |
|
1675 | parent_file_data_opt: None, | |
|
1676 | from_empty: false, | |
|
1677 | }; | |
|
1678 | map.reset_state(reset)?; | |
|
1647 | 1679 | assert_does_not_exist(&map, b"some/file"); |
|
1648 | 1680 | |
|
1649 | 1681 | // A file that was removed |
|
1650 | map.reset_state( | |
|
1651 | p(b"some/nested/file"), | |
|
1652 | false, | |
|
1653 | true, | |
|
1654 | false, | |
|
1655 | false, | |
|
1656 | None, | |
|
1657 | )?; | |
|
1682 | let reset = DirstateEntryReset { | |
|
1683 | filename: p(b"some/nested/file"), | |
|
1684 | wc_tracked: false, | |
|
1685 | p1_tracked: true, | |
|
1686 | p2_info: false, | |
|
1687 | has_meaningful_mtime: false, | |
|
1688 | parent_file_data_opt: None, | |
|
1689 | from_empty: false, | |
|
1690 | }; | |
|
1691 | map.reset_state(reset)?; | |
|
1658 | 1692 | assert!(!map.get(p(b"some/nested/file"))?.unwrap().tracked()); |
|
1659 | 1693 | // Only present in p2 |
|
1660 | map.reset_state(p(b"some/file3"), false, false, true, false, None)?; | |
|
1694 | let reset = DirstateEntryReset { | |
|
1695 | filename: p(b"some/file3"), | |
|
1696 | wc_tracked: false, | |
|
1697 | p1_tracked: false, | |
|
1698 | p2_info: true, | |
|
1699 | has_meaningful_mtime: false, | |
|
1700 | parent_file_data_opt: None, | |
|
1701 | from_empty: false, | |
|
1702 | }; | |
|
1703 | map.reset_state(reset)?; | |
|
1661 | 1704 | assert!(!map.get(p(b"some/file3"))?.unwrap().tracked()); |
|
1662 | 1705 | // A file that was merged |
|
1663 | map.reset_state(p(b"root_file"), true, true, true, false, None)?; | |
|
1706 | let reset = DirstateEntryReset { | |
|
1707 | filename: p(b"root_file"), | |
|
1708 | wc_tracked: true, | |
|
1709 | p1_tracked: true, | |
|
1710 | p2_info: true, | |
|
1711 | has_meaningful_mtime: false, | |
|
1712 | parent_file_data_opt: None, | |
|
1713 | from_empty: false, | |
|
1714 | }; | |
|
1715 | map.reset_state(reset)?; | |
|
1664 | 1716 | assert!(map.get(p(b"root_file"))?.unwrap().tracked()); |
|
1665 | 1717 | // A file that is added, with info from p2 |
|
1666 | 1718 | // XXX is that actually possible? |
|
1667 | map.reset_state(p(b"some/file2"), true, false, true, false, None)?; | |
|
1719 | let reset = DirstateEntryReset { | |
|
1720 | filename: p(b"some/file2"), | |
|
1721 | wc_tracked: true, | |
|
1722 | p1_tracked: false, | |
|
1723 | p2_info: true, | |
|
1724 | has_meaningful_mtime: false, | |
|
1725 | parent_file_data_opt: None, | |
|
1726 | from_empty: false, | |
|
1727 | }; | |
|
1728 | map.reset_state(reset)?; | |
|
1668 | 1729 | assert!(map.get(p(b"some/file2"))?.unwrap().tracked()); |
|
1669 | 1730 | // A clean file |
|
1670 | 1731 | // One layer without any files to test deletion cascade |
|
1671 | map.reset_state( | |
|
1672 | p(b"some/other/nested/path"), | |
|
1673 | true, | |
|
1674 | true, | |
|
1675 | false, | |
|
1676 | false, | |
|
1677 | None, | |
|
1678 | )?; | |
|
1732 | let reset = DirstateEntryReset { | |
|
1733 | filename: p(b"some/other/nested/path"), | |
|
1734 | wc_tracked: true, | |
|
1735 | p1_tracked: true, | |
|
1736 | p2_info: false, | |
|
1737 | has_meaningful_mtime: false, | |
|
1738 | parent_file_data_opt: None, | |
|
1739 | from_empty: false, | |
|
1740 | }; | |
|
1741 | map.reset_state(reset)?; | |
|
1679 | 1742 | assert!(map.get(p(b"some/other/nested/path"))?.unwrap().tracked()); |
|
1680 | 1743 | |
|
1681 | 1744 | assert_eq!(map.len(), 6); |
@@ -1738,13 +1801,49 mod tests { | |||
|
1738 | 1801 | let mut map = OwningDirstateMap::new_empty(vec![], None); |
|
1739 | 1802 | |
|
1740 | 1803 | // Clean file |
|
1741 | map.reset_state(p(b"files/clean"), true, true, false, false, None)?; | |
|
1804 | let reset = DirstateEntryReset { | |
|
1805 | filename: p(b"files/clean"), | |
|
1806 | wc_tracked: true, | |
|
1807 | p1_tracked: true, | |
|
1808 | p2_info: false, | |
|
1809 | has_meaningful_mtime: false, | |
|
1810 | parent_file_data_opt: None, | |
|
1811 | from_empty: false, | |
|
1812 | }; | |
|
1813 | map.reset_state(reset)?; | |
|
1742 | 1814 | // Merged file |
|
1743 | map.reset_state(p(b"files/from_p2"), true, true, true, false, None)?; | |
|
1815 | let reset = DirstateEntryReset { | |
|
1816 | filename: p(b"files/from_p2"), | |
|
1817 | wc_tracked: true, | |
|
1818 | p1_tracked: true, | |
|
1819 | p2_info: true, | |
|
1820 | has_meaningful_mtime: false, | |
|
1821 | parent_file_data_opt: None, | |
|
1822 | from_empty: false, | |
|
1823 | }; | |
|
1824 | map.reset_state(reset)?; | |
|
1744 | 1825 | // Removed file |
|
1745 | map.reset_state(p(b"removed"), false, true, false, false, None)?; | |
|
1826 | let reset = DirstateEntryReset { | |
|
1827 | filename: p(b"removed"), | |
|
1828 | wc_tracked: false, | |
|
1829 | p1_tracked: true, | |
|
1830 | p2_info: false, | |
|
1831 | has_meaningful_mtime: false, | |
|
1832 | parent_file_data_opt: None, | |
|
1833 | from_empty: false, | |
|
1834 | }; | |
|
1835 | map.reset_state(reset)?; | |
|
1746 | 1836 | // Added file |
|
1747 | map.reset_state(p(b"files/added"), true, false, false, false, None)?; | |
|
1837 | let reset = DirstateEntryReset { | |
|
1838 | filename: p(b"files/added"), | |
|
1839 | wc_tracked: true, | |
|
1840 | p1_tracked: false, | |
|
1841 | p2_info: false, | |
|
1842 | has_meaningful_mtime: false, | |
|
1843 | parent_file_data_opt: None, | |
|
1844 | from_empty: false, | |
|
1845 | }; | |
|
1846 | map.reset_state(reset)?; | |
|
1748 | 1847 | // Add copy |
|
1749 | 1848 | map.copy_map_insert(p(b"files/clean"), p(b"clean_copy_source"))?; |
|
1750 | 1849 | assert_eq!(map.copy_map_len(), 1); |
@@ -1799,49 +1898,66 mod tests { | |||
|
1799 | 1898 | map.copy_map_insert(p(b"some/nested/added"), p(b"added_copy_source"))?; |
|
1800 | 1899 | |
|
1801 | 1900 | // A file that was removed |
|
1802 | map.reset_state( | |
|
1803 | p(b"some/nested/removed"), | |
|
1804 | false, | |
|
1805 | true, | |
|
1806 | false, | |
|
1807 | false, | |
|
1808 | None, | |
|
1809 | )?; | |
|
1901 | let reset = DirstateEntryReset { | |
|
1902 | filename: p(b"some/nested/removed"), | |
|
1903 | wc_tracked: false, | |
|
1904 | p1_tracked: true, | |
|
1905 | p2_info: false, | |
|
1906 | has_meaningful_mtime: false, | |
|
1907 | parent_file_data_opt: None, | |
|
1908 | from_empty: false, | |
|
1909 | }; | |
|
1910 | map.reset_state(reset)?; | |
|
1810 | 1911 | // Only present in p2 |
|
1811 | map.reset_state( | |
|
1812 | p(b"other/p2_info_only"), | |
|
1813 | false, | |
|
1814 | false, | |
|
1815 | true, | |
|
1816 | false, | |
|
1817 | None, | |
|
1818 | )?; | |
|
1912 | let reset = DirstateEntryReset { | |
|
1913 | filename: p(b"other/p2_info_only"), | |
|
1914 | wc_tracked: false, | |
|
1915 | p1_tracked: false, | |
|
1916 | p2_info: true, | |
|
1917 | has_meaningful_mtime: false, | |
|
1918 | parent_file_data_opt: None, | |
|
1919 | from_empty: false, | |
|
1920 | }; | |
|
1921 | map.reset_state(reset)?; | |
|
1819 | 1922 | map.copy_map_insert( |
|
1820 | 1923 | p(b"other/p2_info_only"), |
|
1821 | 1924 | p(b"other/p2_info_copy_source"), |
|
1822 | 1925 | )?; |
|
1823 | 1926 | // A file that was merged |
|
1824 | map.reset_state(p(b"merged"), true, true, true, false, None)?; | |
|
1927 | let reset = DirstateEntryReset { | |
|
1928 | filename: p(b"merged"), | |
|
1929 | wc_tracked: true, | |
|
1930 | p1_tracked: true, | |
|
1931 | p2_info: true, | |
|
1932 | has_meaningful_mtime: false, | |
|
1933 | parent_file_data_opt: None, | |
|
1934 | from_empty: false, | |
|
1935 | }; | |
|
1936 | map.reset_state(reset)?; | |
|
1825 | 1937 | // A file that is added, with info from p2 |
|
1826 | 1938 | // XXX is that actually possible? |
|
1827 | map.reset_state( | |
|
1828 | p(b"other/added_with_p2"), | |
|
1829 | true, | |
|
1830 | false, | |
|
1831 | true, | |
|
1832 | false, | |
|
1833 | None, | |
|
1834 | )?; | |
|
1939 | let reset = DirstateEntryReset { | |
|
1940 | filename: p(b"other/added_with_p2"), | |
|
1941 | wc_tracked: true, | |
|
1942 | p1_tracked: false, | |
|
1943 | p2_info: true, | |
|
1944 | has_meaningful_mtime: false, | |
|
1945 | parent_file_data_opt: None, | |
|
1946 | from_empty: false, | |
|
1947 | }; | |
|
1948 | map.reset_state(reset)?; | |
|
1835 | 1949 | // One layer without any files to test deletion cascade |
|
1836 | 1950 | // A clean file |
|
1837 | map.reset_state( | |
|
1838 | p(b"some/other/nested/clean"), | |
|
1839 | true, | |
|
1840 | true, | |
|
1841 | false, | |
|
1842 | false, | |
|
1843 | None, | |
|
1844 | )?; | |
|
1951 | let reset = DirstateEntryReset { | |
|
1952 | filename: p(b"some/other/nested/clean"), | |
|
1953 | wc_tracked: true, | |
|
1954 | p1_tracked: true, | |
|
1955 | p2_info: false, | |
|
1956 | has_meaningful_mtime: false, | |
|
1957 | parent_file_data_opt: None, | |
|
1958 | from_empty: false, | |
|
1959 | }; | |
|
1960 | map.reset_state(reset)?; | |
|
1845 | 1961 | |
|
1846 | 1962 | let (packed, metadata, _should_append, _old_data_size) = |
|
1847 | 1963 | map.pack_v2(DirstateMapWriteMode::ForceNewDataFile)?; |
@@ -14,7 +14,10 use cpython::{ | |||
|
14 | 14 | exc, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList, PyNone, PyObject, |
|
15 | 15 | PyResult, Python, PythonObject, ToPyObject, UnsafePyLeaked, |
|
16 | 16 | }; |
|
17 | use hg::dirstate::{ParentFileData, TruncatedTimestamp}; | |
|
17 | use hg::{ | |
|
18 | dirstate::{ParentFileData, TruncatedTimestamp}, | |
|
19 | dirstate_tree::dirstate_map::DirstateEntryReset, | |
|
20 | }; | |
|
18 | 21 | |
|
19 | 22 | use crate::{ |
|
20 | 23 | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, |
@@ -196,14 +199,16 py_class!(pub class DirstateMap |py| { | |||
|
196 | 199 | }; |
|
197 | 200 | let bytes = f.extract::<PyBytes>(py)?; |
|
198 | 201 | let path = HgPath::new(bytes.data(py)); |
|
199 | let res = self.inner(py).borrow_mut().reset_state( | |
|
200 | path, | |
|
202 | let reset = DirstateEntryReset { | |
|
203 | filename: path, | |
|
201 | 204 | wc_tracked, |
|
202 | 205 | p1_tracked, |
|
203 | 206 | p2_info, |
|
204 | 207 | has_meaningful_mtime, |
|
205 | parent_file_data, | |
|
206 | ); | |
|
208 | parent_file_data_opt: parent_file_data, | |
|
209 | from_empty: false | |
|
210 | }; | |
|
211 | let res = self.inner(py).borrow_mut().reset_state(reset); | |
|
207 | 212 | res.map_err(|_| PyErr::new::<exc::OSError, _>(py, "Dirstate error".to_string()))?; |
|
208 | 213 | Ok(PyNone) |
|
209 | 214 | } |
General Comments 0
You need to be logged in to leave comments.
Login now