~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/hashcache.py

  • Committer: Robert Collins
  • Date: 2009-03-27 04:10:25 UTC
  • mfrom: (4208 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4216.
  • Revision ID: robertc@robertcollins.net-20090327041025-rgutx4q03xo4pq6l
Resolve NEWS conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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
29
29
 
30
30
CACHE_HEADER = "### bzr hashcache v5\n"
31
31
 
32
 
import os
33
 
import stat
34
 
import time
 
32
import os, stat, time
35
33
 
36
 
from bzrlib import (
37
 
    atomicfile,
38
 
    errors,
39
 
    filters as _mod_filters,
40
 
    osutils,
41
 
    trace,
42
 
    )
 
34
from bzrlib.filters import internal_size_sha_file_byname
 
35
from bzrlib.osutils import sha_file, sha_string, pathjoin, safe_unicode
 
36
from bzrlib.trace import mutter, warning
 
37
from bzrlib.atomicfile import AtomicFile
 
38
from bzrlib.errors import BzrError
43
39
 
44
40
 
45
41
FP_MTIME_COLUMN = 1
93
89
            parameters and returns a stack of ContentFilters.
94
90
            If None, no content filtering is performed.
95
91
        """
96
 
        self.root = osutils.safe_unicode(root)
 
92
        self.root = safe_unicode(root)
97
93
        self.root_utf8 = self.root.encode('utf8') # where is the filesystem encoding ?
98
94
        self.hit_count = 0
99
95
        self.miss_count = 0
103
99
        self.update_count = 0
104
100
        self._cache = {}
105
101
        self._mode = mode
106
 
        self._cache_file_name = osutils.safe_unicode(cache_file_name)
 
102
        self._cache_file_name = safe_unicode(cache_file_name)
107
103
        self._filter_provider = content_filter_stack_provider
108
104
 
109
105
    def cache_file_name(self):
129
125
        prep.sort()
130
126
 
131
127
        for inum, path, cache_entry in prep:
132
 
            abspath = osutils.pathjoin(self.root, path)
 
128
            abspath = pathjoin(self.root, path)
133
129
            fp = self._fingerprint(abspath)
134
130
            self.stat_count += 1
135
131
 
145
141
        """Return the sha1 of a file.
146
142
        """
147
143
        if path.__class__ is str:
148
 
            abspath = osutils.pathjoin(self.root_utf8, path)
 
144
            abspath = pathjoin(self.root_utf8, path)
149
145
        else:
150
 
            abspath = osutils.pathjoin(self.root, path)
 
146
            abspath = pathjoin(self.root, path)
151
147
        self.stat_count += 1
152
148
        file_fp = self._fingerprint(abspath, stat_value)
153
149
 
180
176
                filters = self._filter_provider(path=path, file_id=None)
181
177
            digest = self._really_sha1_file(abspath, filters)
182
178
        elif stat.S_ISLNK(mode):
183
 
            target = osutils.readlink(osutils.safe_unicode(abspath))
184
 
            digest = osutils.sha_string(target.encode('UTF-8'))
 
179
            digest = sha_string(os.readlink(abspath))
185
180
        else:
186
 
            raise errors.BzrError("file %r: unknown file stat mode: %o"
187
 
                                  % (abspath, mode))
 
181
            raise BzrError("file %r: unknown file stat mode: %o"%(abspath,mode))
188
182
 
189
183
        # window of 3 seconds to allow for 2s resolution on windows,
190
184
        # unsynchronized file servers, etc.
219
213
 
220
214
    def _really_sha1_file(self, abspath, filters):
221
215
        """Calculate the SHA1 of a file by reading the full text"""
222
 
        return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
 
216
        return internal_size_sha_file_byname(abspath, filters)[1]
223
217
 
224
218
    def write(self):
225
219
        """Write contents of cache to file."""
226
 
        outf = atomicfile.AtomicFile(self.cache_file_name(), 'wb',
227
 
                                     new_mode=self._mode)
 
220
        outf = AtomicFile(self.cache_file_name(), 'wb', new_mode=self._mode)
228
221
        try:
229
222
            outf.write(CACHE_HEADER)
230
223
 
255
248
        try:
256
249
            inf = file(fn, 'rb', buffering=65000)
257
250
        except IOError, e:
258
 
            trace.mutter("failed to open %s: %s", fn, e)
 
251
            mutter("failed to open %s: %s", fn, e)
259
252
            # better write it now so it is valid
260
253
            self.needs_write = True
261
254
            return
262
255
 
263
256
        hdr = inf.readline()
264
257
        if hdr != CACHE_HEADER:
265
 
            trace.mutter('cache header marker not found at top of %s;'
266
 
                         ' discarding cache', fn)
 
258
            mutter('cache header marker not found at top of %s;'
 
259
                   ' discarding cache', fn)
267
260
            self.needs_write = True
268
261
            return
269
262
 
271
264
            pos = l.index('// ')
272
265
            path = l[:pos].decode('utf-8')
273
266
            if path in self._cache:
274
 
                trace.warning('duplicated path %r in cache' % path)
 
267
                warning('duplicated path %r in cache' % path)
275
268
                continue
276
269
 
277
270
            pos += 3
278
271
            fields = l[pos:].split(' ')
279
272
            if len(fields) != 7:
280
 
                trace.warning("bad line in hashcache: %r" % l)
 
273
                warning("bad line in hashcache: %r" % l)
281
274
                continue
282
275
 
283
276
            sha1 = fields[0]
284
277
            if len(sha1) != 40:
285
 
                trace.warning("bad sha1 in hashcache: %r" % sha1)
 
278
                warning("bad sha1 in hashcache: %r" % sha1)
286
279
                continue
287
280
 
288
281
            fp = tuple(map(long, fields[1:]))
289
282
 
290
283
            self._cache[path] = (sha1, fp)
291
284
 
292
 
        # GZ 2009-09-20: Should really use a try/finally block to ensure close
293
 
        inf.close()
294
 
 
295
285
        self.needs_write = False
296
286
 
297
287
    def _cutoff_time(self):