1666
1666
self.st_mode = mode
1669
class TestUpdateEntry(TestCaseWithDirState):
1670
"""Test the DirState.update_entry functions"""
1672
def get_state_with_a(self):
1673
"""Create a DirState tracking a single object named 'a'"""
1674
state = InstrumentedDirState.initialize('dirstate')
1675
self.addCleanup(state.unlock)
1676
state.add('a', 'a-id', 'file', None, '')
1677
entry = state._get_entry(0, path_utf8='a')
1680
def test_update_entry(self):
1681
state, entry = self.get_state_with_a()
1682
self.build_tree(['a'])
1683
# Add one where we don't provide the stat or sha already
1684
self.assertEqual(('', 'a', 'a-id'), entry[0])
1685
self.assertEqual([('f', '', 0, False, dirstate.DirState.NULLSTAT)],
1687
# Flush the buffers to disk
1689
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1690
state._dirblock_state)
1692
stat_value = os.lstat('a')
1693
packed_stat = dirstate.pack_stat(stat_value)
1694
link_or_sha1 = state.update_entry(entry, abspath='a',
1695
stat_value=stat_value)
1696
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1699
# The dirblock entry should not cache the file's sha1
1700
self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1702
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1703
state._dirblock_state)
1704
mode = stat_value.st_mode
1705
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False)], state._log)
1708
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1709
state._dirblock_state)
1711
# If we do it again right away, we don't know if the file has changed
1712
# so we will re-read the file. Roll the clock back so the file is
1713
# guaranteed to look too new.
1714
state.adjust_time(-10)
1716
link_or_sha1 = state.update_entry(entry, abspath='a',
1717
stat_value=stat_value)
1718
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1719
('sha1', 'a'), ('is_exec', mode, False),
1721
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1723
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1724
state._dirblock_state)
1725
self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1729
# However, if we move the clock forward so the file is considered
1730
# "stable", it should just cache the value.
1731
state.adjust_time(+20)
1732
link_or_sha1 = state.update_entry(entry, abspath='a',
1733
stat_value=stat_value)
1734
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1736
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1737
('sha1', 'a'), ('is_exec', mode, False),
1738
('sha1', 'a'), ('is_exec', mode, False),
1740
self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1743
# Subsequent calls will just return the cached value
1744
link_or_sha1 = state.update_entry(entry, abspath='a',
1745
stat_value=stat_value)
1746
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1748
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1749
('sha1', 'a'), ('is_exec', mode, False),
1750
('sha1', 'a'), ('is_exec', mode, False),
1752
self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1755
def test_update_entry_symlink(self):
1756
"""Update entry should read symlinks."""
1757
self.requireFeature(SymlinkFeature)
1758
state, entry = self.get_state_with_a()
1760
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1761
state._dirblock_state)
1762
os.symlink('target', 'a')
1764
state.adjust_time(-10) # Make the symlink look new
1765
stat_value = os.lstat('a')
1766
packed_stat = dirstate.pack_stat(stat_value)
1767
link_or_sha1 = state.update_entry(entry, abspath='a',
1768
stat_value=stat_value)
1769
self.assertEqual('target', link_or_sha1)
1770
self.assertEqual([('read_link', 'a', '')], state._log)
1771
# Dirblock is not updated (the link is too new)
1772
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
1774
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1775
state._dirblock_state)
1777
# Because the stat_value looks new, we should re-read the target
1778
link_or_sha1 = state.update_entry(entry, abspath='a',
1779
stat_value=stat_value)
1780
self.assertEqual('target', link_or_sha1)
1781
self.assertEqual([('read_link', 'a', ''),
1782
('read_link', 'a', ''),
1784
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
1786
state.adjust_time(+20) # Skip into the future, all files look old
1787
link_or_sha1 = state.update_entry(entry, abspath='a',
1788
stat_value=stat_value)
1789
self.assertEqual('target', link_or_sha1)
1790
# We need to re-read the link because only now can we cache it
1791
self.assertEqual([('read_link', 'a', ''),
1792
('read_link', 'a', ''),
1793
('read_link', 'a', ''),
1795
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1798
# Another call won't re-read the link
1799
self.assertEqual([('read_link', 'a', ''),
1800
('read_link', 'a', ''),
1801
('read_link', 'a', ''),
1803
link_or_sha1 = state.update_entry(entry, abspath='a',
1804
stat_value=stat_value)
1805
self.assertEqual('target', link_or_sha1)
1806
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1809
def do_update_entry(self, state, entry, abspath):
1810
stat_value = os.lstat(abspath)
1811
return state.update_entry(entry, abspath, stat_value)
1813
def test_update_entry_dir(self):
1814
state, entry = self.get_state_with_a()
1815
self.build_tree(['a/'])
1816
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1818
def test_update_entry_dir_unchanged(self):
1819
state, entry = self.get_state_with_a()
1820
self.build_tree(['a/'])
1821
state.adjust_time(+20)
1822
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1823
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1824
state._dirblock_state)
1826
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1827
state._dirblock_state)
1828
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1829
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1830
state._dirblock_state)
1832
def test_update_entry_file_unchanged(self):
1833
state, entry = self.get_state_with_a()
1834
self.build_tree(['a'])
1835
sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1836
state.adjust_time(+20)
1837
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1838
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1839
state._dirblock_state)
1841
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1842
state._dirblock_state)
1843
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1844
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1845
state._dirblock_state)
1847
def create_and_test_file(self, state, entry):
1848
"""Create a file at 'a' and verify the state finds it.
1850
The state should already be versioning *something* at 'a'. This makes
1851
sure that state.update_entry recognizes it as a file.
1853
self.build_tree(['a'])
1854
stat_value = os.lstat('a')
1855
packed_stat = dirstate.pack_stat(stat_value)
1857
link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1858
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1860
self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1864
def create_and_test_dir(self, state, entry):
1865
"""Create a directory at 'a' and verify the state finds it.
1867
The state should already be versioning *something* at 'a'. This makes
1868
sure that state.update_entry recognizes it as a directory.
1870
self.build_tree(['a/'])
1871
stat_value = os.lstat('a')
1872
packed_stat = dirstate.pack_stat(stat_value)
1874
link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1875
self.assertIs(None, link_or_sha1)
1876
self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1880
def create_and_test_symlink(self, state, entry):
1881
"""Create a symlink at 'a' and verify the state finds it.
1883
The state should already be versioning *something* at 'a'. This makes
1884
sure that state.update_entry recognizes it as a symlink.
1886
This should not be called if this platform does not have symlink
1889
# caller should care about skipping test on platforms without symlinks
1890
os.symlink('path/to/foo', 'a')
1892
stat_value = os.lstat('a')
1893
packed_stat = dirstate.pack_stat(stat_value)
1895
link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1896
self.assertEqual('path/to/foo', link_or_sha1)
1897
self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1901
def test_update_file_to_dir(self):
1902
"""If a file changes to a directory we return None for the sha.
1903
We also update the inventory record.
1905
state, entry = self.get_state_with_a()
1906
# The file sha1 won't be cached unless the file is old
1907
state.adjust_time(+10)
1908
self.create_and_test_file(state, entry)
1910
self.create_and_test_dir(state, entry)
1912
def test_update_file_to_symlink(self):
1913
"""File becomes a symlink"""
1914
self.requireFeature(SymlinkFeature)
1915
state, entry = self.get_state_with_a()
1916
# The file sha1 won't be cached unless the file is old
1917
state.adjust_time(+10)
1918
self.create_and_test_file(state, entry)
1920
self.create_and_test_symlink(state, entry)
1922
def test_update_dir_to_file(self):
1923
"""Directory becoming a file updates the entry."""
1924
state, entry = self.get_state_with_a()
1925
# The file sha1 won't be cached unless the file is old
1926
state.adjust_time(+10)
1927
self.create_and_test_dir(state, entry)
1929
self.create_and_test_file(state, entry)
1931
def test_update_dir_to_symlink(self):
1932
"""Directory becomes a symlink"""
1933
self.requireFeature(SymlinkFeature)
1934
state, entry = self.get_state_with_a()
1935
# The symlink target won't be cached if it isn't old
1936
state.adjust_time(+10)
1937
self.create_and_test_dir(state, entry)
1939
self.create_and_test_symlink(state, entry)
1941
def test_update_symlink_to_file(self):
1942
"""Symlink becomes a file"""
1943
self.requireFeature(SymlinkFeature)
1944
state, entry = self.get_state_with_a()
1945
# The symlink and file info won't be cached unless old
1946
state.adjust_time(+10)
1947
self.create_and_test_symlink(state, entry)
1949
self.create_and_test_file(state, entry)
1951
def test_update_symlink_to_dir(self):
1952
"""Symlink becomes a directory"""
1953
self.requireFeature(SymlinkFeature)
1954
state, entry = self.get_state_with_a()
1955
# The symlink target won't be cached if it isn't old
1956
state.adjust_time(+10)
1957
self.create_and_test_symlink(state, entry)
1959
self.create_and_test_dir(state, entry)
1961
def test__is_executable_win32(self):
1962
state, entry = self.get_state_with_a()
1963
self.build_tree(['a'])
1965
# Make sure we are using the win32 implementation of _is_executable
1966
state._is_executable = state._is_executable_win32
1968
# The file on disk is not executable, but we are marking it as though
1969
# it is. With _is_executable_win32 we ignore what is on disk.
1970
entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1972
stat_value = os.lstat('a')
1973
packed_stat = dirstate.pack_stat(stat_value)
1975
state.adjust_time(-10) # Make sure everything is new
1976
state.update_entry(entry, abspath='a', stat_value=stat_value)
1978
# The row is updated, but the executable bit stays set.
1979
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1982
# Make the disk object look old enough to cache
1983
state.adjust_time(+20)
1984
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1985
state.update_entry(entry, abspath='a', stat_value=stat_value)
1986
self.assertEqual([('f', digest, 14, True, packed_stat)], entry[1])
1989
1669
class TestPackStat(TestCaseWithTransport):
1991
1671
def assertPackStat(self, expected, stat_value):