~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/statcache.py

  • Committer: Martin Pool
  • Date: 2005-07-04 07:34:19 UTC
  • Revision ID: mbp@sourcefrog.net-20050704073419-44eb753d5556a4d0
- rename control file to pending-merges

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
to gradually adjust your clock or don't use bzr over the step.
59
59
 
60
60
At the moment this is stored in a simple textfile; it might be nice
61
 
to use a tdb instead.
 
61
to use a tdb instead to allow faster lookup by file-id.
62
62
 
63
63
The cache is represented as a map from file_id to a tuple of (file_id,
64
64
sha1, path, size, mtime, ctime, ino, dev).
65
65
 
66
66
The SHA-1 is stored in memory as a hexdigest.
67
67
 
68
 
File names and file-ids are written out with non-ascii or whitespace
69
 
characters given as python-style unicode escapes.  (file-ids shouldn't
70
 
contain wierd characters, but it might happen.)
 
68
This version of the file on disk has one line per record, and fields
 
69
separated by \0 records.
71
70
"""
72
71
 
73
72
# order of fields returned by fingerprint()
89
88
 
90
89
 
91
90
 
92
 
CACHE_HEADER = "### bzr statcache v3"
 
91
CACHE_HEADER = "### bzr statcache v4"
93
92
 
94
93
 
95
94
def fingerprint(abspath):
107
106
 
108
107
 
109
108
 
110
 
def safe_quote(s):
111
 
    return s.encode('unicode_escape') \
112
 
           .replace('\n', '\\u000a')  \
113
 
           .replace(' ', '\\u0020')   \
114
 
           .replace('\r', '\\u000d')
115
 
 
116
 
 
117
109
def _write_cache(basedir, entries):
118
110
    from atomicfile import AtomicFile
119
111
 
120
112
    cachefn = os.path.join(basedir, '.bzr', 'stat-cache')
121
113
    outf = AtomicFile(cachefn, 'wb')
122
 
    outf.write(CACHE_HEADER + '\n')
123
114
    try:
 
115
        outf.write(CACHE_HEADER + '\n')
 
116
    
124
117
        for entry in entries:
125
118
            if len(entry) != 8:
126
119
                raise ValueError("invalid statcache entry tuple %r" % entry)
127
 
            outf.write(safe_quote(entry[0])) # file id
128
 
            outf.write(' ')
 
120
            outf.write(entry[0].encode('utf-8')) # file id
 
121
            outf.write('\0')
129
122
            outf.write(entry[1])             # hex sha1
130
 
            outf.write(' ')
131
 
            outf.write(safe_quote(entry[2])) # name
 
123
            outf.write('\0')
 
124
            outf.write(entry[2].encode('utf-8')) # name
132
125
            for nf in entry[3:]:
133
 
                outf.write(' %d' % nf)
 
126
                outf.write('\0%d' % nf)
134
127
            outf.write('\n')
135
128
 
136
129
        outf.commit()
153
146
    import re
154
147
    cache = {}
155
148
    seen_paths = {}
 
149
    from bzrlib.trace import warning
 
150
 
 
151
    assert isinstance(basedir, basestring)
156
152
 
157
153
    sha_re = re.compile(r'[a-f0-9]{40}')
158
154
 
164
160
 
165
161
    line1 = cachefile.readline().rstrip('\r\n')
166
162
    if line1 != CACHE_HEADER:
167
 
        mutter('cache header marker not found at top of %s' % cachefn)
 
163
        mutter('cache header marker not found at top of %s; discarding cache'
 
164
               % cachefn)
168
165
        return cache
169
166
 
170
167
    for l in cachefile:
171
 
        f = l.split(' ')
 
168
        f = l.split('\0')
172
169
 
173
 
        file_id = f[0].decode('unicode_escape')
 
170
        file_id = f[0].decode('utf-8')
174
171
        if file_id in cache:
175
 
            raise BzrCheckError("duplicated file_id in cache: {%s}" % file_id)
 
172
            warning("duplicated file_id in cache: {%s}" % file_id)
176
173
 
177
174
        text_sha = f[1]
178
175
        if len(text_sha) != 40 or not sha_re.match(text_sha):
179
176
            raise BzrCheckError("invalid file SHA-1 in cache: %r" % text_sha)
180
177
        
181
 
        path = f[2].decode('unicode_escape')
 
178
        path = f[2].decode('utf-8')
182
179
        if path in seen_paths:
183
 
            raise BzrCheckError("duplicated path in cache: %r" % path)
 
180
            warning("duplicated path in cache: %r" % path)
184
181
        seen_paths[path] = True
185
182
        
186
183
        entry = (file_id, text_sha, path) + tuple([long(x) for x in f[3:]])
192
189
 
193
190
 
194
191
 
195
 
 
196
192
def _files_from_inventory(inv):
197
193
    for path, ie in inv.iter_entries():
198
194
        if ie.kind != 'file':