89
89
# if there are gaps and that can happen if we're interrupted while
90
90
# writing to the datafile. Overlapping would be very bad though.
92
# TODO: Shouldn't need to lock if we always write in append mode and
93
# then ftell after writing to see where it went. In any case we
94
# assume the whole branch is protected by a lock.
96
94
import sys, zlib, struct, mdiff, stat, os, sha
97
95
from binascii import hexlify, unhexlify
101
101
_HEADER = "bzr revfile v1\n"
242
243
return self._add_compressed(text_sha, text, _NO_RECORD, compress)
246
def _choose_base(self, seed, base):
248
if base == _NO_RECORD:
251
if idxrec[I_BASE] == _NO_RECORD:
254
base = idxrec[I_BASE]
257
return base # relative to this full text
261
246
def _add_delta(self, text, text_sha, base, compress):
262
247
"""Add a text stored relative to a previous text."""
263
248
self._check_index(base)
266
base_text = self.get(base, CHAIN_LIMIT)
251
base_text = self.get(base, recursion_limit=CHAIN_LIMIT)
267
252
except LimitHitException:
268
253
return self._add_full_text(text, text_sha, compress)
270
255
data = mdiff.bdiff(base_text, text)
273
if True: # paranoid early check for bad diff
274
result = mdiff.bpatch(base_text, data)
275
assert result == text
278
257
# If the delta is larger than the text, we might as well just
279
258
# store the text. (OK, the delta might be more compressible,
285
264
return self._add_compressed(text_sha, data, base, compress)
288
def add(self, text, base=None, compress=True):
267
def add(self, text, base=_NO_RECORD, compress=True):
289
268
"""Add a new text to the revfile.
291
270
If the text is already present them its existing id is
312
288
# it's the same, in case someone ever breaks SHA-1.
313
289
return idx # already present
315
# base = self._choose_base(ord(text_sha[0]), base)
317
291
if base == _NO_RECORD:
318
292
return self._add_full_text(text, text_sha, compress)
338
312
text = self._get_patched(idx, idxrec, recursion_limit)
340
314
if sha.new(text).digest() != idxrec[I_SHA]:
341
raise RevfileError("corrupt SHA-1 digest on record %d in %s"
342
% (idx, self.basename))
315
raise RevfileError("corrupt SHA-1 digest on record %d"
430
404
"""Read back all index records.
432
406
Do not seek the index file while this is underway!"""
433
## sys.stderr.write(" ** iter called ** \n")
407
sys.stderr.write(" ** iter called ** \n")
434
408
self._seek_index(0)
436
410
idxrec = self._read_next_index()
478
452
for idx in range(len(self)):
479
453
t += len(self.get(idx))
483
def check(self, pb=None):
484
"""Extract every version and check its hash."""
486
for i in range(total):
488
pb.update("check revision", i, total)
489
# the get method implicitly checks the SHA-1
500
461
except IndexError:
501
sys.stderr.write("usage: revfile dump REVFILE\n"
502
" revfile add REVFILE < INPUT\n"
503
" revfile add-delta REVFILE BASE < INPUT\n"
504
" revfile add-series REVFILE BASE FILE...\n"
505
" revfile get REVFILE IDX\n"
506
" revfile find-sha REVFILE HEX\n"
507
" revfile total-text-size REVFILE\n"
508
" revfile last REVFILE\n")
462
sys.stderr.write("usage: revfile dump\n"
464
" revfile add-delta BASE\n"
466
" revfile find-sha HEX\n"
467
" revfile total-text-size\n"
511
if filename.endswith('.drev') or filename.endswith('.irev'):
512
filename = filename[:-5]
515
return Revfile(filename, 'w')
472
return Revfile('testrev', 'w')
518
return Revfile(filename, 'r')
475
return Revfile('testrev', 'r')
521
478
print rw().add(sys.stdin.read())
522
479
elif cmd == 'add-delta':
523
print rw().add(sys.stdin.read(), int(argv[3]))
524
elif cmd == 'add-series':
529
rev = r.add(file(fn).read(), rev)
480
print rw().add(sys.stdin.read(), int(argv[2]))
530
481
elif cmd == 'dump':
532
483
elif cmd == 'get':
535
486
except IndexError:
536
sys.stderr.write("usage: revfile get FILE IDX\n")
487
sys.stderr.write("usage: revfile get IDX\n")
541
490
if idx < 0 or idx >= len(r):
542
491
sys.stderr.write("invalid index %r\n" % idx)
545
sys.stdout.write(r.get(idx))
494
sys.stdout.write(ro().get(idx))
546
495
elif cmd == 'find-sha':
548
s = unhexlify(argv[3])
497
s = unhexlify(argv[2])
549
498
except IndexError:
550
sys.stderr.write("usage: revfile find-sha FILE HEX\n")
499
sys.stderr.write("usage: revfile find-sha HEX\n")
553
502
idx = ro().find_sha(s)