~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/statcache.py

  • Committer: Martin Pool
  • Date: 2005-05-30 02:45:48 UTC
  • Revision ID: mbp@sourcefrog.net-20050530024548-120dad7e43de5fec
- rsync upload should be quieter

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 to allow faster lookup by file-id.
 
61
to use a tdb instead.
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
 
This version of the file on disk has one line per record, and fields
69
 
separated by \0 records.
 
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.)
70
71
"""
71
72
 
72
73
# order of fields returned by fingerprint()
88
89
 
89
90
 
90
91
 
91
 
CACHE_HEADER = "### bzr statcache v4"
 
92
CACHE_HEADER = "### bzr statcache v3"
92
93
 
93
94
 
94
95
def fingerprint(abspath):
106
107
 
107
108
 
108
109
 
 
110
def safe_quote(s):
 
111
    return s.encode('unicode_escape') \
 
112
           .replace('\n', '\\u000a')  \
 
113
           .replace(' ', '\\u0020')   \
 
114
           .replace('\r', '\\u000d')
 
115
 
 
116
 
109
117
def _write_cache(basedir, entries):
110
118
    from atomicfile import AtomicFile
111
119
 
112
120
    cachefn = os.path.join(basedir, '.bzr', 'stat-cache')
113
121
    outf = AtomicFile(cachefn, 'wb')
 
122
    outf.write(CACHE_HEADER + '\n')
114
123
    try:
115
 
        outf.write(CACHE_HEADER + '\n')
116
 
    
117
124
        for entry in entries:
118
125
            if len(entry) != 8:
119
126
                raise ValueError("invalid statcache entry tuple %r" % entry)
120
 
            outf.write(entry[0].encode('utf-8')) # file id
121
 
            outf.write('\0')
 
127
            outf.write(safe_quote(entry[0])) # file id
 
128
            outf.write(' ')
122
129
            outf.write(entry[1])             # hex sha1
123
 
            outf.write('\0')
124
 
            outf.write(entry[2].encode('utf-8')) # name
 
130
            outf.write(' ')
 
131
            outf.write(safe_quote(entry[2])) # name
125
132
            for nf in entry[3:]:
126
 
                outf.write('\0%d' % nf)
 
133
                outf.write(' %d' % nf)
127
134
            outf.write('\n')
128
135
 
129
136
        outf.commit()
146
153
    import re
147
154
    cache = {}
148
155
    seen_paths = {}
149
 
    from bzrlib.trace import warning
150
156
 
151
157
    sha_re = re.compile(r'[a-f0-9]{40}')
152
158
 
158
164
 
159
165
    line1 = cachefile.readline().rstrip('\r\n')
160
166
    if line1 != CACHE_HEADER:
161
 
        mutter('cache header marker not found at top of %s; discarding cache'
162
 
               % cachefn)
 
167
        mutter('cache header marker not found at top of %s' % cachefn)
163
168
        return cache
164
169
 
165
170
    for l in cachefile:
166
 
        f = l.split('\0')
 
171
        f = l.split(' ')
167
172
 
168
 
        file_id = f[0].decode('utf-8')
 
173
        file_id = f[0].decode('unicode_escape')
169
174
        if file_id in cache:
170
 
            warning("duplicated file_id in cache: {%s}" % file_id)
 
175
            raise BzrCheckError("duplicated file_id in cache: {%s}" % file_id)
171
176
 
172
177
        text_sha = f[1]
173
178
        if len(text_sha) != 40 or not sha_re.match(text_sha):
174
179
            raise BzrCheckError("invalid file SHA-1 in cache: %r" % text_sha)
175
180
        
176
 
        path = f[2].decode('utf-8')
 
181
        path = f[2].decode('unicode_escape')
177
182
        if path in seen_paths:
178
 
            warning("duplicated path in cache: %r" % path)
 
183
            raise BzrCheckError("duplicated path in cache: %r" % path)
179
184
        seen_paths[path] = True
180
185
        
181
186
        entry = (file_id, text_sha, path) + tuple([long(x) for x in f[3:]])
187
192
 
188
193
 
189
194
 
 
195
 
190
196
def _files_from_inventory(inv):
191
197
    for path, ie in inv.iter_entries():
192
198
        if ie.kind != 'file':