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.
94
96
import sys, zlib, struct, mdiff, stat, os, sha
95
97
from binascii import hexlify, unhexlify
101
101
_HEADER = "bzr revfile v1\n"
243
242
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
246
261
def _add_delta(self, text, text_sha, base, compress):
247
262
"""Add a text stored relative to a previous text."""
248
263
self._check_index(base)
251
base_text = self.get(base, recursion_limit=CHAIN_LIMIT)
266
base_text = self.get(base, CHAIN_LIMIT)
252
267
except LimitHitException:
253
268
return self._add_full_text(text, text_sha, compress)
255
270
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
257
278
# If the delta is larger than the text, we might as well just
258
279
# store the text. (OK, the delta might be more compressible,
264
285
return self._add_compressed(text_sha, data, base, compress)
267
def add(self, text, base=_NO_RECORD, compress=True):
288
def add(self, text, base=None, compress=True):
268
289
"""Add a new text to the revfile.
270
291
If the text is already present them its existing id is
288
312
# it's the same, in case someone ever breaks SHA-1.
289
313
return idx # already present
315
# base = self._choose_base(ord(text_sha[0]), base)
291
317
if base == _NO_RECORD:
292
318
return self._add_full_text(text, text_sha, compress)
312
338
text = self._get_patched(idx, idxrec, recursion_limit)
314
340
if sha.new(text).digest() != idxrec[I_SHA]:
315
raise RevfileError("corrupt SHA-1 digest on record %d"
341
raise RevfileError("corrupt SHA-1 digest on record %d in %s"
342
% (idx, self.basename))
404
430
"""Read back all index records.
406
432
Do not seek the index file while this is underway!"""
407
sys.stderr.write(" ** iter called ** \n")
433
## sys.stderr.write(" ** iter called ** \n")
408
434
self._seek_index(0)
410
436
idxrec = self._read_next_index()
452
478
for idx in range(len(self)):
453
479
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
461
500
except IndexError:
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"
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")
511
if filename.endswith('.drev') or filename.endswith('.irev'):
512
filename = filename[:-5]
472
return Revfile('testrev', 'w')
515
return Revfile(filename, 'w')
475
return Revfile('testrev', 'r')
518
return Revfile(filename, 'r')
478
521
print rw().add(sys.stdin.read())
479
522
elif cmd == 'add-delta':
480
print rw().add(sys.stdin.read(), int(argv[2]))
523
print rw().add(sys.stdin.read(), int(argv[3]))
524
elif cmd == 'add-series':
529
rev = r.add(file(fn).read(), rev)
481
530
elif cmd == 'dump':
483
532
elif cmd == 'get':
486
535
except IndexError:
487
sys.stderr.write("usage: revfile get IDX\n")
536
sys.stderr.write("usage: revfile get FILE IDX\n")
490
541
if idx < 0 or idx >= len(r):
491
542
sys.stderr.write("invalid index %r\n" % idx)
494
sys.stdout.write(ro().get(idx))
545
sys.stdout.write(r.get(idx))
495
546
elif cmd == 'find-sha':
497
s = unhexlify(argv[2])
548
s = unhexlify(argv[3])
498
549
except IndexError:
499
sys.stderr.write("usage: revfile find-sha HEX\n")
550
sys.stderr.write("usage: revfile find-sha FILE HEX\n")
502
553
idx = ro().find_sha(s)