~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_dirstate.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-09-26 04:27:28 UTC
  • mfrom: (3696.4.20 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080926042728-8dzaiolv2q1duutw
(robertc) Create a pyrex optimised iter_changes for dirstate trees.
        (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
571
571
            # Make sure everything is old enough
572
572
            state._sha_cutoff_time()
573
573
            state._cutoff_time += 10
574
 
            sha1sum = state.update_entry(entry, 'a-file', os.lstat('a-file'))
 
574
            sha1sum = dirstate.update_entry(state, entry, 'a-file', os.lstat('a-file'))
575
575
            # We should have gotten a real sha1
576
576
            self.assertEqual('ecc5374e9ed82ad3ea3b4d452ea995a5fd3e70e3',
577
577
                             sha1sum)
612
612
        state.lock_read()
613
613
        try:
614
614
            entry = state._get_entry(0, path_utf8='a-file')
615
 
            sha1sum = state.update_entry(entry, 'a-file', os.lstat('a-file'))
 
615
            sha1sum = dirstate.update_entry(state, entry, 'a-file', os.lstat('a-file'))
616
616
            # We should have gotten a real sha1
617
617
            self.assertEqual('ecc5374e9ed82ad3ea3b4d452ea995a5fd3e70e3',
618
618
                             sha1sum)
1666
1666
        self.st_mode = mode
1667
1667
 
1668
1668
 
1669
 
class TestUpdateEntry(TestCaseWithDirState):
1670
 
    """Test the DirState.update_entry functions"""
1671
 
 
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')
1678
 
        return state, entry
1679
 
 
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)],
1686
 
                         entry[1])
1687
 
        # Flush the buffers to disk
1688
 
        state.save()
1689
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1690
 
                         state._dirblock_state)
1691
 
 
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',
1697
 
                         link_or_sha1)
1698
 
 
1699
 
        # The dirblock entry should not cache the file's sha1
1700
 
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1701
 
                         entry[1])
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)
1706
 
 
1707
 
        state.save()
1708
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1709
 
                         state._dirblock_state)
1710
 
 
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)
1715
 
 
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),
1720
 
                         ], state._log)
1721
 
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1722
 
                         link_or_sha1)
1723
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1724
 
                         state._dirblock_state)
1725
 
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1726
 
                         entry[1])
1727
 
        state.save()
1728
 
 
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',
1735
 
                         link_or_sha1)
1736
 
        self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1737
 
                          ('sha1', 'a'), ('is_exec', mode, False),
1738
 
                          ('sha1', 'a'), ('is_exec', mode, False),
1739
 
                         ], state._log)
1740
 
        self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1741
 
                         entry[1])
1742
 
 
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',
1747
 
                         link_or_sha1)
1748
 
        self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1749
 
                          ('sha1', 'a'), ('is_exec', mode, False),
1750
 
                          ('sha1', 'a'), ('is_exec', mode, False),
1751
 
                         ], state._log)
1752
 
        self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1753
 
                         entry[1])
1754
 
 
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()
1759
 
        state.save()
1760
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1761
 
                         state._dirblock_state)
1762
 
        os.symlink('target', 'a')
1763
 
 
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)],
1773
 
                         entry[1])
1774
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1775
 
                         state._dirblock_state)
1776
 
 
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', ''),
1783
 
                         ], state._log)
1784
 
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
1785
 
                         entry[1])
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', ''),
1794
 
                         ], state._log)
1795
 
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
1796
 
                         entry[1])
1797
 
 
1798
 
        # Another call won't re-read the link
1799
 
        self.assertEqual([('read_link', 'a', ''),
1800
 
                          ('read_link', 'a', ''),
1801
 
                          ('read_link', 'a', ''),
1802
 
                         ], state._log)
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)],
1807
 
                         entry[1])
1808
 
 
1809
 
    def do_update_entry(self, state, entry, abspath):
1810
 
        stat_value = os.lstat(abspath)
1811
 
        return state.update_entry(entry, abspath, stat_value)
1812
 
 
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'))
1817
 
 
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)
1825
 
        state.save()
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)
1831
 
 
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)
1840
 
        state.save()
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)
1846
 
 
1847
 
    def create_and_test_file(self, state, entry):
1848
 
        """Create a file at 'a' and verify the state finds it.
1849
 
 
1850
 
        The state should already be versioning *something* at 'a'. This makes
1851
 
        sure that state.update_entry recognizes it as a file.
1852
 
        """
1853
 
        self.build_tree(['a'])
1854
 
        stat_value = os.lstat('a')
1855
 
        packed_stat = dirstate.pack_stat(stat_value)
1856
 
 
1857
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1858
 
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1859
 
                         link_or_sha1)
1860
 
        self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1861
 
                         entry[1])
1862
 
        return packed_stat
1863
 
 
1864
 
    def create_and_test_dir(self, state, entry):
1865
 
        """Create a directory at 'a' and verify the state finds it.
1866
 
 
1867
 
        The state should already be versioning *something* at 'a'. This makes
1868
 
        sure that state.update_entry recognizes it as a directory.
1869
 
        """
1870
 
        self.build_tree(['a/'])
1871
 
        stat_value = os.lstat('a')
1872
 
        packed_stat = dirstate.pack_stat(stat_value)
1873
 
 
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])
1877
 
 
1878
 
        return packed_stat
1879
 
 
1880
 
    def create_and_test_symlink(self, state, entry):
1881
 
        """Create a symlink at 'a' and verify the state finds it.
1882
 
 
1883
 
        The state should already be versioning *something* at 'a'. This makes
1884
 
        sure that state.update_entry recognizes it as a symlink.
1885
 
 
1886
 
        This should not be called if this platform does not have symlink
1887
 
        support.
1888
 
        """
1889
 
        # caller should care about skipping test on platforms without symlinks
1890
 
        os.symlink('path/to/foo', 'a')
1891
 
 
1892
 
        stat_value = os.lstat('a')
1893
 
        packed_stat = dirstate.pack_stat(stat_value)
1894
 
 
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)],
1898
 
                         entry[1])
1899
 
        return packed_stat
1900
 
 
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.
1904
 
        """
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)
1909
 
        os.remove('a')
1910
 
        self.create_and_test_dir(state, entry)
1911
 
 
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)
1919
 
        os.remove('a')
1920
 
        self.create_and_test_symlink(state, entry)
1921
 
 
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)
1928
 
        os.rmdir('a')
1929
 
        self.create_and_test_file(state, entry)
1930
 
 
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)
1938
 
        os.rmdir('a')
1939
 
        self.create_and_test_symlink(state, entry)
1940
 
 
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)
1948
 
        os.remove('a')
1949
 
        self.create_and_test_file(state, entry)
1950
 
 
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)
1958
 
        os.remove('a')
1959
 
        self.create_and_test_dir(state, entry)
1960
 
 
1961
 
    def test__is_executable_win32(self):
1962
 
        state, entry = self.get_state_with_a()
1963
 
        self.build_tree(['a'])
1964
 
 
1965
 
        # Make sure we are using the win32 implementation of _is_executable
1966
 
        state._is_executable = state._is_executable_win32
1967
 
 
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)
1971
 
 
1972
 
        stat_value = os.lstat('a')
1973
 
        packed_stat = dirstate.pack_stat(stat_value)
1974
 
 
1975
 
        state.adjust_time(-10) # Make sure everything is new
1976
 
        state.update_entry(entry, abspath='a', stat_value=stat_value)
1977
 
 
1978
 
        # The row is updated, but the executable bit stays set.
1979
 
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1980
 
                         entry[1])
1981
 
 
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])
1987
 
 
1988
 
 
1989
1669
class TestPackStat(TestCaseWithTransport):
1990
1670
 
1991
1671
    def assertPackStat(self, expected, stat_value):