641
642
__contains__ = has_version
643
644
def _merge_annotations(self, content, parents, parent_texts={},
644
delta=None, annotated=None):
645
delta=None, annotated=None,
646
left_matching_blocks=None):
645
647
"""Merge annotations for content. This is done by comparing
646
648
the annotations based on changed to the text.
650
if left_matching_blocks is not None:
651
delta_seq = diff._PrematchedMatcher(left_matching_blocks)
650
655
for parent_id in parents:
651
656
merge_content = self._get_content(parent_id, parent_texts)
652
seq = patiencediff.PatienceSequenceMatcher(
653
None, merge_content.text(), content.text())
654
if delta_seq is None:
655
# setup a delta seq to reuse.
657
if (parent_id == parents[0] and delta_seq is not None):
660
seq = patiencediff.PatienceSequenceMatcher(
661
None, merge_content.text(), content.text())
657
662
for i, j, n in seq.get_matching_blocks():
660
# this appears to copy (origin, text) pairs across to the new
661
# content for any line that matches the last-checked parent.
662
# FIXME: save the sequence control data for delta compression
663
# against the most relevant parent rather than rediffing.
665
# this appears to copy (origin, text) pairs across to the
666
# new content for any line that matches the last-checked
664
668
content._lines[j:j+n] = merge_content._lines[i:i+n]
670
if delta_seq is None:
667
671
reference_content = self._get_content(parents[0], parent_texts)
668
672
new_texts = content.text()
669
673
old_texts = reference_content.text()
729
733
self._check_add(version_id, lines)
730
734
return self._add(version_id, lines[:], parents, self.delta, parent_texts)
732
def _add_lines(self, version_id, parents, lines, parent_texts):
736
def _add_lines(self, version_id, parents, lines, parent_texts,
737
left_matching_blocks=None):
733
738
"""See VersionedFile.add_lines."""
734
739
self._check_add(version_id, lines)
735
740
self._check_versions_present(parents)
736
return self._add(version_id, lines[:], parents, self.delta, parent_texts)
741
return self._add(version_id, lines[:], parents, self.delta,
742
parent_texts, left_matching_blocks)
738
744
def _check_add(self, version_id, lines):
739
745
"""check that version_id and lines are safe to add."""
747
753
self._check_lines_not_unicode(lines)
748
754
self._check_lines_are_lines(lines)
750
def _add(self, version_id, lines, parents, delta, parent_texts):
756
def _add(self, version_id, lines, parents, delta, parent_texts,
757
left_matching_blocks=None):
751
758
"""Add a set of lines on top of version specified by parents.
753
760
If delta is true, compress the text as a line-delta against
797
804
lines = self.factory.make(lines, version_id)
798
805
if delta or (self.factory.annotated and len(present_parents) > 0):
799
806
# Merge annotations from parent texts if so is needed.
800
delta_hunks = self._merge_annotations(lines, present_parents, parent_texts,
801
delta, self.factory.annotated)
807
delta_hunks = self._merge_annotations(lines, present_parents,
808
parent_texts, delta, self.factory.annotated,
809
left_matching_blocks)
804
812
options.append('line-delta')
1021
1029
versions = [osutils.safe_revision_id(v) for v in versions]
1022
1030
return self._index.get_ancestry_with_ghosts(versions)
1024
#@deprecated_method(zero_eight)
1025
def walk(self, version_ids):
1026
"""See VersionedFile.walk."""
1027
# We take the short path here, and extract all relevant texts
1028
# and put them in a weave and let that do all the work. Far
1029
# from optimal, but is much simpler.
1030
# FIXME RB 20060228 this really is inefficient!
1031
from bzrlib.weave import Weave
1033
w = Weave(self.filename)
1034
ancestry = set(self.get_ancestry(version_ids, topo_sorted=False))
1035
sorted_graph = topo_sort(self._index.get_graph())
1036
version_list = [vid for vid in sorted_graph if vid in ancestry]
1038
for version_id in version_list:
1039
lines = self.get_lines(version_id)
1040
w.add_lines(version_id, self.get_parents(version_id), lines)
1042
for lineno, insert_id, dset, line in w.walk(version_ids):
1043
yield lineno, insert_id, dset, line
1045
1032
def plan_merge(self, ver_a, ver_b):
1046
1033
"""See VersionedFile.plan_merge."""
1047
1034
ver_a = osutils.safe_revision_id(ver_a)