/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: John Arbash Meinel
  • Date: 2007-03-01 19:58:38 UTC
  • mto: (2255.7.84 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: john@arbash-meinel.com-20070301195838-7p053os20qwr6qf7
Update WorkingTree4 so that it doesn't use a HashCache,
instead caching the sha values and stat fingerprint in the 'current'
section.

Show diffs side-by-side

added added

removed removed

Lines of Context:
191
191
"""
192
192
 
193
193
 
194
 
import base64
195
194
import bisect
 
195
import codecs
196
196
import cStringIO
197
197
import os
198
198
import sha
199
199
import struct
 
200
import time
200
201
import zlib
201
202
 
202
203
from bzrlib import (
297
298
            within the root.
298
299
        :param file_id: The file id of the path being added.
299
300
        :param kind: The kind of the path.
300
 
        :param stat: The output of os.lstate for the path.
 
301
        :param stat: The output of os.lstat for the path.
301
302
        :param link_or_sha1: The sha value of the file, or the target of a
302
303
            symlink. '' for directories.
303
304
        """
900
901
 
901
902
    def _entry_to_line(self, entry):
902
903
        """Serialize entry to a NULL delimited line ready for _get_output_lines.
903
 
        
 
904
 
904
905
        :param entry: An entry_tuple as defined in the module docstring.
905
906
        """
906
907
        entire_entry = list(entry[0])
1014
1015
            raise
1015
1016
        return result
1016
1017
 
 
1018
    def get_sha1_for_entry(self, entry, abspath, stat_value=None):
 
1019
        """Return the sha1 sum for a given file.
 
1020
 
 
1021
        :param entry: This is the dirblock entry for the file in question.
 
1022
        :param abspath: The path on disk for this file.
 
1023
        :param stat_value: (optional) if we already have done a stat on the
 
1024
            file, re-use it.
 
1025
        :return: The sha1 hexdigest of the file (40 bytes)
 
1026
        """
 
1027
        # This code assumes that the entry passed in is directly held in one of
 
1028
        # the internal _dirblocks. So the dirblock state must have already been
 
1029
        # read.
 
1030
        assert self._dirblock_state != DirState.NOT_IN_MEMORY
 
1031
        assert entry[1][0][0] == 'f', \
 
1032
            'can only get sha1 for a file not: %s %s' % (
 
1033
            DirState._minikind_to_kind[entry[1][0][0]], entry[0])
 
1034
        if stat_value is None:
 
1035
            stat_value = os.lstat(abspath)
 
1036
        packed_stat = pack_stat(stat_value)
 
1037
        saved_sha1_digest = entry[1][0][1]
 
1038
        saved_file_size = entry[1][0][2]
 
1039
        saved_packed_stat = entry[1][0][4]
 
1040
        if (packed_stat == saved_packed_stat
 
1041
            and saved_sha1_digest != ''
 
1042
            # size should also be in packed_stat
 
1043
            and saved_file_size == stat_value.st_size):
 
1044
            # The stat hasn't changed since we saved, so we can potentially
 
1045
            # re-use the saved sha hash.
 
1046
            cutoff = self._sha_cutoff_time()
 
1047
            if (stat_value.st_mtime < cutoff
 
1048
                and stat_value.st_ctime < cutoff):
 
1049
                # Return the existing fingerprint
 
1050
                return saved_sha1_digest
 
1051
        # If we have gotten this far, that means that we need to actually
 
1052
        # process the file.
 
1053
        new_sha1_digest = self._sha1_file(abspath)
 
1054
        # TODO: jam 20070301 Is it worth checking to see if the new sha is
 
1055
        #       actually different? I'm guessing not, because we wouldn't have
 
1056
        #       gotten this far otherwise.
 
1057
        entry[1][0] = ('f', new_sha1_digest, stat_value.st_size,
 
1058
                       entry[1][0][3], # Executable?
 
1059
                       packed_stat
 
1060
                      )
 
1061
        self._dirblock_state = DirState.IN_MEMORY_MODIFIED
 
1062
        return new_sha1_digest
 
1063
 
 
1064
    def _sha_cutoff_time(self):
 
1065
        """Return cutoff time.
 
1066
 
 
1067
        Files modified more recently than this time are at risk of being
 
1068
        undetectably modified and so can't be cached.
 
1069
        """
 
1070
        return int(time.time()) - 3
 
1071
 
 
1072
    def _sha1_file(self, abspath):
 
1073
        """Calculate the SHA1 of a file by reading the full text"""
 
1074
        f = file(abspath, 'rb', buffering=65000)
 
1075
        try:
 
1076
            return osutils.sha_file(f)
 
1077
        finally:
 
1078
            f.close()
 
1079
 
1017
1080
    def get_ghosts(self):
1018
1081
        """Return a list of the parent tree revision ids that are ghosts."""
1019
1082
        self._read_header_if_needed()
1226
1289
                        path_utf8=real_path)
1227
1290
            return None, None
1228
1291
 
1229
 
    @staticmethod
1230
 
    def initialize(path):
 
1292
    @classmethod
 
1293
    def initialize(cls, path):
1231
1294
        """Create a new dirstate on path.
1232
1295
 
1233
1296
        The new dirstate will be an empty tree - that is it has no parents,
1245
1308
        # stock empty dirstate information - a root with ROOT_ID, no children,
1246
1309
        # and no parents. Finally it calls save() to ensure that this data will
1247
1310
        # persist.
1248
 
        result = DirState(path)
 
1311
        result = cls(path)
1249
1312
        # root dir and root dir contents with no children.
1250
1313
        empty_tree_dirblocks = [('', []), ('', [])]
1251
1314
        # a new root directory, with a NULLSTAT.
2048
2111
    return lo
2049
2112
 
2050
2113
 
2051
 
def pack_stat(st, _encode=base64.encodestring, _pack=struct.pack):
 
2114
_base64_encoder = codecs.getencoder('base64')
 
2115
 
 
2116
 
 
2117
def pack_stat(st, _encode=_base64_encoder, _pack=struct.pack):
2052
2118
    """Convert stat values into a packed representation."""
2053
2119
    # jam 20060614 it isn't really worth removing more entries if we
2054
2120
    # are going to leave it in packed form.
2058
2124
 
2059
2125
    # base64.encode always adds a final newline, so strip it off
2060
2126
    return _encode(_pack('>llllll'
2061
 
        , st.st_size, st.st_mtime, st.st_ctime
2062
 
        , st.st_dev, st.st_ino, st.st_mode))[:-1]
 
2127
        , st.st_size, int(st.st_mtime), int(st.st_ctime)
 
2128
        , st.st_dev, st.st_ino, st.st_mode))[0][:-1]