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