67
67
# the possible relationships.
71
72
from difflib import SequenceMatcher
73
74
from bzrlib.trace import mutter
74
from bzrlib.errors import WeaveError, WeaveFormatError, WeaveParentMismatch, \
75
WeaveRevisionNotPresent, WeaveRevisionAlreadyPresent
75
from bzrlib.errors import (WeaveError, WeaveFormatError, WeaveParentMismatch,
76
WeaveRevisionNotPresent, WeaveRevisionAlreadyPresent)
77
import bzrlib.errors as errors
76
78
from bzrlib.tsort import topo_sort
548
555
def get_iter(self, name_or_index):
549
556
"""Yield lines for the specified version."""
550
557
incls = [self.maybe_lookup(name_or_index)]
562
# We don't have sha1 sums for multiple entries
551
564
for origin, lineno, line in self._extract(incls):
569
expected_sha1 = self._sha1s[index]
570
measured_sha1 = cur_sha.hexdigest()
571
if measured_sha1 != expected_sha1:
572
raise errors.WeaveInvalidChecksum(
573
'file %s, revision %s, expected: %s, measured %s'
574
% (self._weave_name, self._names[index],
575
expected_sha1, measured_sha1))
555
578
def get_text(self, name_or_index):
600
629
raise WeaveFormatError("invalid included version %d for index %d"
601
630
% (inclusions[-1], version))
603
# try extracting all versions; this is a bit slow and parallel
604
# extraction could be used
632
# try extracting all versions; parallel extraction is used
605
633
nv = self.numversions()
634
sha1s = [sha.new() for i in range(nv)]
635
texts = [[] for i in range(nv)]
638
# For creating the ancestry, IntSet is much faster (3.7s vs 0.17s)
639
# The problem is that set membership is much more expensive
641
for p in self._parents[i]:
642
new_inc.update(inclusions[p])
644
#assert set(new_inc) == self.inclusions([i]), 'failed %s != %s' % (new_inc, self.inclusions([i]))
645
inclusions.append(new_inc)
647
nlines = len(self._weave)
649
update_text = 'checking weave'
651
short_name = os.path.basename(self._weave_name)
652
update_text = 'checking %s' % (short_name,)
653
update_text = update_text[:25]
655
for lineno, insert, deleteset, line in self._walk():
657
progress_bar.update(update_text, lineno, nlines)
659
for j, j_inc in enumerate(inclusions):
660
# The active inclusion must be an ancestor,
661
# and no ancestors must have deleted this line,
662
# because we don't support resurrection.
663
if (insert in j_inc) and not (deleteset & j_inc):
664
sha1s[j].update(line)
606
666
for version in range(nv):
608
progress_bar.update('checking text', version, nv)
610
for l in self.get_iter(version):
667
hd = sha1s[version].hexdigest()
613
668
expected = self._sha1s[version]
614
669
if hd != expected:
615
raise WeaveError("mismatched sha1 for version %d; "
616
"got %s, expected %s"
617
% (version, hd, expected))
670
raise errors.WeaveInvalidChecksum(
671
"mismatched sha1 for version %s: "
672
"got %s, expected %s"
673
% (self._names[version], hd, expected))
619
675
# TODO: check insertions are properly nested, that there are
620
676
# no lines outside of insertion blocks, that deletions are
621
677
# properly paired, etc.
625
def merge(self, merge_versions):
626
"""Automerge and mark conflicts between versions.
628
This returns a sequence, each entry describing alternatives
629
for a chunk of the file. Each of the alternatives is given as
632
If there is a chunk of the file where there's no diagreement,
633
only one alternative is given.
635
# approach: find the included versions common to all the
637
raise NotImplementedError()
641
679
def _delta(self, included, lines):
642
680
"""Return changes from basis to new revision.
774
817
# work through in index order to make sure we get all dependencies
775
818
for other_idx, name in enumerate(other._names):
776
if self._check_version_consistent(other, other_idx, name):
819
self._check_version_consistent(other, other_idx, name)
778
824
for other_idx, name in enumerate(other._names):
779
# TODO: If all the parents of the other version are already
825
# TODO: If all the parents of the other version are already
780
826
# present then we can avoid some work by just taking the delta
781
827
# and adjusting the offsets.
782
828
new_parents = self._imported_parents(other, other_idx)
829
sha1 = other._sha1s[other_idx]
833
if name in self._names:
834
idx = self.lookup(name)
835
n1 = map(other.idx_to_name, other._parents[other_idx] )
836
n2 = map(self.idx_to_name, self._parents[other_idx] )
837
if sha1 == self._sha1s[idx] and n1 == n2:
783
841
lines = other.get_lines(other_idx)
784
sha1 = other._sha1s[other_idx]
785
842
self.add(name, new_parents, lines, sha1)
844
mutter("merged = %d, processed = %d, file_id=%s; deltat=%d"%(
845
merged,processed,self._weave_name, time.time( )-time0))
788
850
def _imported_parents(self, other, other_idx):
789
851
"""Return list of parents in self corresponding to indexes in other."""
1192
def lsprofile_main(argv):
1193
from bzrlib.lsprof import profile
1194
ret,stats = profile(main, argv)
1130
1200
if __name__ == '__main__':
1132
1202
if '--profile' in sys.argv:
1133
1203
args = sys.argv[:]
1134
1204
args.remove('--profile')
1135
1205
sys.exit(profile_main(args))
1206
elif '--lsprof' in sys.argv:
1208
args.remove('--lsprof')
1209
sys.exit(lsprofile_main(args))
1137
1211
sys.exit(main(sys.argv))