~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revfile.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-09 04:01:25 UTC
  • Revision ID: mbp@sourcefrog.net-20050409040125-5c53f66535269927911b91b9
Revfile:- new find-sha command and implementation- new _check_index helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
71
71
 
72
72
 
73
73
import sys, zlib, struct, mdiff, stat, os, sha
74
 
from binascii import hexlify
 
74
from binascii import hexlify, unhexlify
75
75
 
76
76
factor = 10
77
77
 
79
79
 
80
80
_HEADER = "bzr revfile v1\n"
81
81
_HEADER = _HEADER + ('\xff' * (_RECORDSIZE - len(_HEADER)))
82
 
_NO_BASE = 0xFFFFFFFFL
 
82
_NO_RECORD = 0xFFFFFFFFL
83
83
 
84
84
# fields in the index record
85
85
I_SHA = 0
150
150
        return text    
151
151
 
152
152
 
153
 
    def add_full_text(self, t):
 
153
    def _add_full_text(self, t):
154
154
        """Add a full text to the file.
155
155
 
156
156
        This is not compressed against any reference version.
177
177
        return idx
178
178
 
179
179
 
 
180
    def _check_index(self, idx):
 
181
        if idx < 0 or idx > len(self):
 
182
            raise RevfileError("invalid index %r" % idx)
 
183
 
 
184
 
 
185
    def find_sha(self, s):
 
186
        assert isinstance(s, str)
 
187
        assert len(s) == 20
 
188
        
 
189
        for idx, idxrec in enumerate(self):
 
190
            if idxrec[I_SHA] == s:
 
191
                return idx
 
192
        else:
 
193
            return _NO_RECORD        
 
194
 
 
195
 
 
196
    def _add_diff(self, text, base):
 
197
        """Add a text stored relative to a previous text."""
 
198
        self._check_index(base)
 
199
        text_sha = sha.new(text).digest()
 
200
 
 
201
        
 
202
    def addrevision(self, text, changeset):
 
203
        t = self.tip()
 
204
        n = t + 1
 
205
 
 
206
        if not n % factor:
 
207
            data = zlib.compress(text)
 
208
            base = n
 
209
        else:
 
210
            prev = self.revision(t)
 
211
            data = zlib.compress(mdiff.bdiff(prev, text))
 
212
            base = self.index[t][0]
 
213
 
 
214
        offset = 0
 
215
        if t >= 0:
 
216
            offset = self.index[t][1] + self.index[t][2]
 
217
 
 
218
        self.index.append((base, offset, len(data), changeset))
 
219
        entry = struct.pack(">llll", base, offset, len(data), changeset)
 
220
 
 
221
        open(self.indexfile(), "a").write(entry)
 
222
        open(self.datafile(), "a").write(data)
 
223
 
180
224
    def _get_full_text(self, idx):
181
225
        idxrec = self[idx]
182
226
        assert idxrec[I_FLAGS] == 0
183
 
        assert idxrec[I_BASE] == _NO_BASE
 
227
        assert idxrec[I_BASE] == _NO_RECORD
184
228
 
185
229
        l = idxrec[I_LEN]
186
230
        if l == 0:
193
237
            raise RevfileError("short read %d of %d "
194
238
                               "getting text for record %d in %r"
195
239
                               % (len(text), l, idx, self.basename))
 
240
 
 
241
        if sha.new(text).digest() != idxrec[I_SHA]:
 
242
            raise RevfileError("corrupt SHA-1 digest on record %d"
 
243
                               % idx)
196
244
        
197
245
        return text
198
246
 
209
257
 
210
258
    def __getitem__(self, idx):
211
259
        """Index by sequence id returns the index field"""
 
260
        ## TODO: Can avoid seek if we just moved there...
212
261
        self._seek_index(idx)
213
262
        return self._read_next_index()
214
263
 
228
277
        return struct.unpack(">20sIIII12x", rec)
229
278
 
230
279
        
231
 
        
232
 
    def addrevision(self, text, changeset):
233
 
        t = self.tip()
234
 
        n = t + 1
235
 
 
236
 
        if not n % factor:
237
 
            data = zlib.compress(text)
238
 
            base = n
239
 
        else:
240
 
            prev = self.revision(t)
241
 
            data = zlib.compress(mdiff.bdiff(prev, text))
242
 
            base = self.index[t][0]
243
 
 
244
 
        offset = 0
245
 
        if t >= 0:
246
 
            offset = self.index[t][1] + self.index[t][2]
247
 
 
248
 
        self.index.append((base, offset, len(data), changeset))
249
 
        entry = struct.pack(">llll", base, offset, len(data), changeset)
250
 
 
251
 
        open(self.indexfile(), "a").write(entry)
252
 
        open(self.datafile(), "a").write(data)
253
 
 
254
280
    def dump(self, f=sys.stdout):
255
281
        f.write('%-8s %-40s %-8s %-8s %-8s %-8s\n' 
256
282
                % tuple('idx sha1 base flags offset len'.split()))
259
285
 
260
286
        for i, rec in enumerate(self):
261
287
            f.write("#%-7d %40s " % (i, hexlify(rec[0])))
262
 
            if rec[1] == _NO_BASE:
 
288
            if rec[1] == _NO_RECORD:
263
289
                f.write("(none)   ")
264
290
            else:
265
291
                f.write("#%-7d " % rec[1])
276
302
    except IndexError:
277
303
        sys.stderr.write("usage: revfile dump\n"
278
304
                         "       revfile add\n"
279
 
                         "       revfile get IDX\n")
 
305
                         "       revfile get IDX\n"
 
306
                         "       revfile find-sha HEX\n")
280
307
        return 1
281
308
        
282
309
 
283
310
    if cmd == 'add':
284
 
        new_idx = r.add_full_text(sys.stdin.read())
 
311
        new_idx = r._add_full_text(sys.stdin.read())
285
312
        print 'added idx %d' % new_idx
286
313
    elif cmd == 'dump':
287
314
        r.dump()
297
324
            return 1
298
325
 
299
326
        sys.stdout.write(r._get_full_text(idx))
 
327
    elif cmd == 'find-sha':
 
328
        try:
 
329
            s = unhexlify(argv[2])
 
330
        except IndexError:
 
331
            sys.stderr.write("usage: revfile find-sha HEX\n")
 
332
            return 1
 
333
 
 
334
        idx = r.find_sha(s)
 
335
        if idx == _NO_RECORD:
 
336
            sys.stderr.write("no such record\n")
 
337
            return 1
 
338
        else:
 
339
            print idx
 
340
            
300
341
    else:
301
342
        sys.stderr.write("unknown command %r\n" % cmd)
302
343
        return 1