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
import sys, zlib, struct, mdiff, stat, os, sha
102
95
from binascii import hexlify, unhexlify
104
import bzrlib.mdiff as mdiff
250
243
return self._add_compressed(text_sha, text, _NO_RECORD, compress)
254
def _choose_base(self, seed, base):
256
if base == _NO_RECORD:
259
if idxrec[I_BASE] == _NO_RECORD:
262
base = idxrec[I_BASE]
265
return base # relative to this full text
269
246
def _add_delta(self, text, text_sha, base, compress):
270
247
"""Add a text stored relative to a previous text."""
271
248
self._check_index(base)
274
base_text = self.get(base, CHAIN_LIMIT)
251
base_text = self.get(base, recursion_limit=CHAIN_LIMIT)
275
252
except LimitHitException:
276
253
return self._add_full_text(text, text_sha, compress)
278
255
data = mdiff.bdiff(base_text, text)
281
if True: # paranoid early check for bad diff
282
result = mdiff.bpatch(base_text, data)
283
assert result == text
286
257
# If the delta is larger than the text, we might as well just
287
258
# store the text. (OK, the delta might be more compressible,
293
264
return self._add_compressed(text_sha, data, base, compress)
296
def add(self, text, base=None, compress=True):
267
def add(self, text, base=_NO_RECORD, compress=True):
297
268
"""Add a new text to the revfile.
299
270
If the text is already present them its existing id is
320
288
# it's the same, in case someone ever breaks SHA-1.
321
289
return idx # already present
323
# base = self._choose_base(ord(text_sha[0]), base)
325
291
if base == _NO_RECORD:
326
292
return self._add_full_text(text, text_sha, compress)
346
312
text = self._get_patched(idx, idxrec, recursion_limit)
348
314
if sha.new(text).digest() != idxrec[I_SHA]:
349
raise RevfileError("corrupt SHA-1 digest on record %d in %s"
350
% (idx, self.basename))
315
raise RevfileError("corrupt SHA-1 digest on record %d"
438
404
"""Read back all index records.
440
406
Do not seek the index file while this is underway!"""
441
## sys.stderr.write(" ** iter called ** \n")
407
sys.stderr.write(" ** iter called ** \n")
442
408
self._seek_index(0)
444
410
idxrec = self._read_next_index()
486
452
for idx in range(len(self)):
487
453
t += len(self.get(idx))
491
def check(self, pb=None):
492
"""Extract every version and check its hash."""
494
for i in range(total):
496
pb.update("check revision", i, total)
497
# the get method implicitly checks the SHA-1
508
461
except IndexError:
509
sys.stderr.write("usage: revfile dump REVFILE\n"
510
" revfile add REVFILE < INPUT\n"
511
" revfile add-delta REVFILE BASE < INPUT\n"
512
" revfile add-series REVFILE BASE FILE...\n"
513
" revfile get REVFILE IDX\n"
514
" revfile find-sha REVFILE HEX\n"
515
" revfile total-text-size REVFILE\n"
516
" 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"
519
if filename.endswith('.drev') or filename.endswith('.irev'):
520
filename = filename[:-5]
523
return Revfile(filename, 'w')
472
return Revfile('testrev', 'w')
526
return Revfile(filename, 'r')
475
return Revfile('testrev', 'r')
529
478
print rw().add(sys.stdin.read())
530
479
elif cmd == 'add-delta':
531
print rw().add(sys.stdin.read(), int(argv[3]))
532
elif cmd == 'add-series':
537
rev = r.add(file(fn).read(), rev)
480
print rw().add(sys.stdin.read(), int(argv[2]))
538
481
elif cmd == 'dump':
540
483
elif cmd == 'get':
543
486
except IndexError:
544
sys.stderr.write("usage: revfile get FILE IDX\n")
487
sys.stderr.write("usage: revfile get IDX\n")
549
490
if idx < 0 or idx >= len(r):
550
491
sys.stderr.write("invalid index %r\n" % idx)
553
sys.stdout.write(r.get(idx))
494
sys.stdout.write(ro().get(idx))
554
495
elif cmd == 'find-sha':
556
s = unhexlify(argv[3])
497
s = unhexlify(argv[2])
557
498
except IndexError:
558
sys.stderr.write("usage: revfile find-sha FILE HEX\n")
499
sys.stderr.write("usage: revfile find-sha HEX\n")
561
502
idx = ro().find_sha(s)