~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__dirstate_helpers.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-05 04:05:05 UTC
  • mfrom: (3473.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080605040505-i9kqxg2fps2qjdi0
Add the 'alias' command (Tim Penhey)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
 
19
19
import bisect
20
20
import os
21
 
import time
22
21
 
23
22
from bzrlib import (
24
23
    dirstate,
25
 
    errors,
26
24
    tests,
27
25
    )
28
 
from bzrlib.tests import (
29
 
        SymlinkFeature,
30
 
        )
31
26
from bzrlib.tests import test_dirstate
32
27
 
33
28
 
696
691
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
697
692
                         state._dirblock_state)
698
693
 
699
 
    def test_trailing_garbage(self):
700
 
        tree, state, expected = self.create_basic_dirstate()
701
 
        # We can modify the file as long as it hasn't been read yet.
702
 
        f = open('dirstate', 'ab')
703
 
        try:
704
 
            # Add bogus trailing garbage
705
 
            f.write('bogus\n')
706
 
        finally:
707
 
            f.close()
708
 
        e = self.assertRaises(errors.DirstateCorrupt,
709
 
                              state._read_dirblocks_if_needed)
710
 
        # Make sure we mention the bogus characters in the error
711
 
        self.assertContainsRe(str(e), 'bogus')
712
 
 
713
694
 
714
695
class TestCompiledReadDirblocks(TestReadDirblocks):
715
696
    """Test the pyrex implementation of _read_dirblocks"""
769
750
            from bzrlib._dirstate_helpers_py import _read_dirblocks_py
770
751
            self.assertIs(_read_dirblocks_py, dirstate._read_dirblocks)
771
752
 
772
 
    def test_update_entry(self):
773
 
        if CompiledDirstateHelpersFeature.available():
774
 
            from bzrlib._dirstate_helpers_c import update_entry
775
 
            self.assertIs(update_entry, dirstate.update_entry)
776
 
        else:
777
 
            from bzrlib.dirstate import py_update_entry
778
 
            self.assertIs(py_update_entry, dirstate.py_update_entry)
779
 
 
780
 
    def test_process_entry(self):
781
 
        if CompiledDirstateHelpersFeature.available():
782
 
            from bzrlib._dirstate_helpers_c import ProcessEntryC
783
 
            self.assertIs(ProcessEntryC, dirstate._process_entry)
784
 
        else:
785
 
            from bzrlib.dirstate import ProcessEntryPython
786
 
            self.assertIs(ProcessEntryPython, dirstate._process_entry)
787
 
 
788
 
 
789
 
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
790
 
    """Test the DirState.update_entry functions"""
791
 
 
792
 
    def get_state_with_a(self):
793
 
        """Create a DirState tracking a single object named 'a'"""
794
 
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
795
 
        self.addCleanup(state.unlock)
796
 
        state.add('a', 'a-id', 'file', None, '')
797
 
        entry = state._get_entry(0, path_utf8='a')
798
 
        self.set_update_entry()
799
 
        return state, entry
800
 
 
801
 
    def set_update_entry(self):
802
 
        self.update_entry = dirstate.py_update_entry
803
 
 
804
 
    def test_observed_sha1_cachable(self):
805
 
        state, entry = self.get_state_with_a()
806
 
        atime = time.time() - 10
807
 
        self.build_tree(['a'])
808
 
        statvalue = os.lstat('a')
809
 
        statvalue = test_dirstate._FakeStat(statvalue.st_size, atime, atime,
810
 
            statvalue.st_dev, statvalue.st_ino, statvalue.st_mode)
811
 
        state._observed_sha1(entry, "foo", statvalue)
812
 
        self.assertEqual('foo', entry[1][0][1])
813
 
        packed_stat = dirstate.pack_stat(statvalue)
814
 
        self.assertEqual(packed_stat, entry[1][0][4])
815
 
 
816
 
    def test_observed_sha1_not_cachable(self):
817
 
        state, entry = self.get_state_with_a()
818
 
        oldval = entry[1][0][1]
819
 
        oldstat = entry[1][0][4]
820
 
        self.build_tree(['a'])
821
 
        statvalue = os.lstat('a')
822
 
        state._observed_sha1(entry, "foo", statvalue)
823
 
        self.assertEqual(oldval, entry[1][0][1])
824
 
        self.assertEqual(oldstat, entry[1][0][4])
825
 
 
826
 
    def test_update_entry(self):
827
 
        state, _ = self.get_state_with_a()
828
 
        tree = self.make_branch_and_tree('tree')
829
 
        tree.lock_write()
830
 
        empty_revid = tree.commit('empty')
831
 
        self.build_tree(['tree/a'])
832
 
        tree.add(['a'], ['a-id'])
833
 
        with_a_id = tree.commit('with_a')
834
 
        self.addCleanup(tree.unlock)
835
 
        state.set_parent_trees(
836
 
            [(empty_revid, tree.branch.repository.revision_tree(empty_revid))],
837
 
            [])
838
 
        entry = state._get_entry(0, path_utf8='a')
839
 
        self.build_tree(['a'])
840
 
        # Add one where we don't provide the stat or sha already
841
 
        self.assertEqual(('', 'a', 'a-id'), entry[0])
842
 
        self.assertEqual(('f', '', 0, False, dirstate.DirState.NULLSTAT),
843
 
                         entry[1][0])
844
 
        # Flush the buffers to disk
845
 
        state.save()
846
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
847
 
                         state._dirblock_state)
848
 
 
849
 
        stat_value = os.lstat('a')
850
 
        packed_stat = dirstate.pack_stat(stat_value)
851
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
852
 
                                          stat_value=stat_value)
853
 
        self.assertEqual(None, link_or_sha1)
854
 
 
855
 
        # The dirblock entry should not have cached the file's sha1 (too new)
856
 
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
857
 
                         entry[1][0])
858
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
859
 
                         state._dirblock_state)
860
 
        mode = stat_value.st_mode
861
 
        self.assertEqual([('is_exec', mode, False)], state._log)
862
 
 
863
 
        state.save()
864
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
865
 
                         state._dirblock_state)
866
 
 
867
 
        # If we do it again right away, we don't know if the file has changed
868
 
        # so we will re-read the file. Roll the clock back so the file is
869
 
        # guaranteed to look too new.
870
 
        state.adjust_time(-10)
871
 
        del state._log[:]
872
 
 
873
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
874
 
                                          stat_value=stat_value)
875
 
        self.assertEqual([('is_exec', mode, False)], state._log)
876
 
        self.assertEqual(None, link_or_sha1)
877
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
878
 
                         state._dirblock_state)
879
 
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
880
 
                         entry[1][0])
881
 
        state.save()
882
 
 
883
 
        # If it is cachable (the clock has moved forward) but new it still
884
 
        # won't calculate the sha or cache it.
885
 
        state.adjust_time(+20)
886
 
        del state._log[:]
887
 
        link_or_sha1 = dirstate.update_entry(state, entry, abspath='a',
888
 
                                          stat_value=stat_value)
889
 
        self.assertEqual(None, link_or_sha1)
890
 
        self.assertEqual([('is_exec', mode, False)], state._log)
891
 
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
892
 
                         entry[1][0])
893
 
 
894
 
        # If the file is no longer new, and the clock has been moved forward
895
 
        # sufficiently, it will cache the sha.
896
 
        del state._log[:]
897
 
        state.set_parent_trees(
898
 
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
899
 
            [])
900
 
        entry = state._get_entry(0, path_utf8='a')
901
 
 
902
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
903
 
                                          stat_value=stat_value)
904
 
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
905
 
                         link_or_sha1)
906
 
        self.assertEqual([('is_exec', mode, False), ('sha1', 'a')],
907
 
                          state._log)
908
 
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
909
 
                         entry[1][0])
910
 
 
911
 
        # Subsequent calls will just return the cached value
912
 
        del state._log[:]
913
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
914
 
                                          stat_value=stat_value)
915
 
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
916
 
                         link_or_sha1)
917
 
        self.assertEqual([], state._log)
918
 
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
919
 
                         entry[1][0])
920
 
 
921
 
    def test_update_entry_symlink(self):
922
 
        """Update entry should read symlinks."""
923
 
        self.requireFeature(SymlinkFeature)
924
 
        state, entry = self.get_state_with_a()
925
 
        state.save()
926
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
927
 
                         state._dirblock_state)
928
 
        os.symlink('target', 'a')
929
 
 
930
 
        state.adjust_time(-10) # Make the symlink look new
931
 
        stat_value = os.lstat('a')
932
 
        packed_stat = dirstate.pack_stat(stat_value)
933
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
934
 
                                          stat_value=stat_value)
935
 
        self.assertEqual('target', link_or_sha1)
936
 
        self.assertEqual([('read_link', 'a', '')], state._log)
937
 
        # Dirblock is not updated (the link is too new)
938
 
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
939
 
                         entry[1])
940
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
941
 
                         state._dirblock_state)
942
 
 
943
 
        # Because the stat_value looks new, we should re-read the target
944
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
945
 
                                          stat_value=stat_value)
946
 
        self.assertEqual('target', link_or_sha1)
947
 
        self.assertEqual([('read_link', 'a', ''),
948
 
                          ('read_link', 'a', ''),
949
 
                         ], state._log)
950
 
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
951
 
                         entry[1])
952
 
        state.adjust_time(+20) # Skip into the future, all files look old
953
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
954
 
                                          stat_value=stat_value)
955
 
        self.assertEqual('target', link_or_sha1)
956
 
        # We need to re-read the link because only now can we cache it
957
 
        self.assertEqual([('read_link', 'a', ''),
958
 
                          ('read_link', 'a', ''),
959
 
                          ('read_link', 'a', ''),
960
 
                         ], state._log)
961
 
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
962
 
                         entry[1])
963
 
 
964
 
        # Another call won't re-read the link
965
 
        self.assertEqual([('read_link', 'a', ''),
966
 
                          ('read_link', 'a', ''),
967
 
                          ('read_link', 'a', ''),
968
 
                         ], state._log)
969
 
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
970
 
                                          stat_value=stat_value)
971
 
        self.assertEqual('target', link_or_sha1)
972
 
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
973
 
                         entry[1])
974
 
 
975
 
    def do_update_entry(self, state, entry, abspath):
976
 
        stat_value = os.lstat(abspath)
977
 
        return self.update_entry(state, entry, abspath, stat_value)
978
 
 
979
 
    def test_update_entry_dir(self):
980
 
        state, entry = self.get_state_with_a()
981
 
        self.build_tree(['a/'])
982
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
983
 
 
984
 
    def test_update_entry_dir_unchanged(self):
985
 
        state, entry = self.get_state_with_a()
986
 
        self.build_tree(['a/'])
987
 
        state.adjust_time(+20)
988
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
989
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
990
 
                         state._dirblock_state)
991
 
        state.save()
992
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
993
 
                         state._dirblock_state)
994
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
995
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
996
 
                         state._dirblock_state)
997
 
 
998
 
    def test_update_entry_file_unchanged(self):
999
 
        state, _ = self.get_state_with_a()
1000
 
        tree = self.make_branch_and_tree('tree')
1001
 
        tree.lock_write()
1002
 
        self.build_tree(['tree/a'])
1003
 
        tree.add(['a'], ['a-id'])
1004
 
        with_a_id = tree.commit('witha')
1005
 
        self.addCleanup(tree.unlock)
1006
 
        state.set_parent_trees(
1007
 
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
1008
 
            [])
1009
 
        entry = state._get_entry(0, path_utf8='a')
1010
 
        self.build_tree(['a'])
1011
 
        sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1012
 
        state.adjust_time(+20)
1013
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1014
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1015
 
                         state._dirblock_state)
1016
 
        state.save()
1017
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1018
 
                         state._dirblock_state)
1019
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1020
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1021
 
                         state._dirblock_state)
1022
 
 
1023
 
    def create_and_test_file(self, state, entry):
1024
 
        """Create a file at 'a' and verify the state finds it during update.
1025
 
 
1026
 
        The state should already be versioning *something* at 'a'. This makes
1027
 
        sure that state.update_entry recognizes it as a file.
1028
 
        """
1029
 
        self.build_tree(['a'])
1030
 
        stat_value = os.lstat('a')
1031
 
        packed_stat = dirstate.pack_stat(stat_value)
1032
 
 
1033
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1034
 
        self.assertEqual(None, link_or_sha1)
1035
 
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1036
 
                         entry[1])
1037
 
        return packed_stat
1038
 
 
1039
 
    def create_and_test_dir(self, state, entry):
1040
 
        """Create a directory at 'a' and verify the state finds it.
1041
 
 
1042
 
        The state should already be versioning *something* at 'a'. This makes
1043
 
        sure that state.update_entry recognizes it as a directory.
1044
 
        """
1045
 
        self.build_tree(['a/'])
1046
 
        stat_value = os.lstat('a')
1047
 
        packed_stat = dirstate.pack_stat(stat_value)
1048
 
 
1049
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1050
 
        self.assertIs(None, link_or_sha1)
1051
 
        self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1052
 
 
1053
 
        return packed_stat
1054
 
 
1055
 
    def create_and_test_symlink(self, state, entry):
1056
 
        """Create a symlink at 'a' and verify the state finds it.
1057
 
 
1058
 
        The state should already be versioning *something* at 'a'. This makes
1059
 
        sure that state.update_entry recognizes it as a symlink.
1060
 
 
1061
 
        This should not be called if this platform does not have symlink
1062
 
        support.
1063
 
        """
1064
 
        # caller should care about skipping test on platforms without symlinks
1065
 
        os.symlink('path/to/foo', 'a')
1066
 
 
1067
 
        stat_value = os.lstat('a')
1068
 
        packed_stat = dirstate.pack_stat(stat_value)
1069
 
 
1070
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1071
 
        self.assertEqual('path/to/foo', link_or_sha1)
1072
 
        self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1073
 
                         entry[1])
1074
 
        return packed_stat
1075
 
 
1076
 
    def test_update_file_to_dir(self):
1077
 
        """If a file changes to a directory we return None for the sha.
1078
 
        We also update the inventory record.
1079
 
        """
1080
 
        state, entry = self.get_state_with_a()
1081
 
        # The file sha1 won't be cached unless the file is old
1082
 
        state.adjust_time(+10)
1083
 
        self.create_and_test_file(state, entry)
1084
 
        os.remove('a')
1085
 
        self.create_and_test_dir(state, entry)
1086
 
 
1087
 
    def test_update_file_to_symlink(self):
1088
 
        """File becomes a symlink"""
1089
 
        self.requireFeature(SymlinkFeature)
1090
 
        state, entry = self.get_state_with_a()
1091
 
        # The file sha1 won't be cached unless the file is old
1092
 
        state.adjust_time(+10)
1093
 
        self.create_and_test_file(state, entry)
1094
 
        os.remove('a')
1095
 
        self.create_and_test_symlink(state, entry)
1096
 
 
1097
 
    def test_update_dir_to_file(self):
1098
 
        """Directory becoming a file updates the entry."""
1099
 
        state, entry = self.get_state_with_a()
1100
 
        # The file sha1 won't be cached unless the file is old
1101
 
        state.adjust_time(+10)
1102
 
        self.create_and_test_dir(state, entry)
1103
 
        os.rmdir('a')
1104
 
        self.create_and_test_file(state, entry)
1105
 
 
1106
 
    def test_update_dir_to_symlink(self):
1107
 
        """Directory becomes a symlink"""
1108
 
        self.requireFeature(SymlinkFeature)
1109
 
        state, entry = self.get_state_with_a()
1110
 
        # The symlink target won't be cached if it isn't old
1111
 
        state.adjust_time(+10)
1112
 
        self.create_and_test_dir(state, entry)
1113
 
        os.rmdir('a')
1114
 
        self.create_and_test_symlink(state, entry)
1115
 
 
1116
 
    def test_update_symlink_to_file(self):
1117
 
        """Symlink becomes a file"""
1118
 
        self.requireFeature(SymlinkFeature)
1119
 
        state, entry = self.get_state_with_a()
1120
 
        # The symlink and file info won't be cached unless old
1121
 
        state.adjust_time(+10)
1122
 
        self.create_and_test_symlink(state, entry)
1123
 
        os.remove('a')
1124
 
        self.create_and_test_file(state, entry)
1125
 
 
1126
 
    def test_update_symlink_to_dir(self):
1127
 
        """Symlink becomes a directory"""
1128
 
        self.requireFeature(SymlinkFeature)
1129
 
        state, entry = self.get_state_with_a()
1130
 
        # The symlink target won't be cached if it isn't old
1131
 
        state.adjust_time(+10)
1132
 
        self.create_and_test_symlink(state, entry)
1133
 
        os.remove('a')
1134
 
        self.create_and_test_dir(state, entry)
1135
 
 
1136
 
    def test__is_executable_win32(self):
1137
 
        state, entry = self.get_state_with_a()
1138
 
        self.build_tree(['a'])
1139
 
 
1140
 
        # Make sure we are using the win32 implementation of _is_executable
1141
 
        state._is_executable = state._is_executable_win32
1142
 
 
1143
 
        # The file on disk is not executable, but we are marking it as though
1144
 
        # it is. With _is_executable_win32 we ignore what is on disk.
1145
 
        entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1146
 
 
1147
 
        stat_value = os.lstat('a')
1148
 
        packed_stat = dirstate.pack_stat(stat_value)
1149
 
 
1150
 
        state.adjust_time(-10) # Make sure everything is new
1151
 
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1152
 
 
1153
 
        # The row is updated, but the executable bit stays set.
1154
 
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1155
 
                         entry[1])
1156
 
 
1157
 
        # Make the disk object look old enough to cache (but it won't cache the sha
1158
 
        # as it is a new file).
1159
 
        state.adjust_time(+20)
1160
 
        digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1161
 
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1162
 
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1163
 
            entry[1])
1164
 
 
1165
 
 
1166
 
class TestCompiledUpdateEntry(TestUpdateEntry):
1167
 
    """Test the pyrex implementation of _read_dirblocks"""
1168
 
 
1169
 
    _test_needs_features = [CompiledDirstateHelpersFeature]
1170
 
 
1171
 
    def set_update_entry(self):
1172
 
        from bzrlib._dirstate_helpers_c import update_entry
1173
 
        self.update_entry = update_entry