~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
78
78
""")
79
79
from bzrlib import (
80
80
    cache_utf8,
 
81
    diff,
81
82
    errors,
82
83
    osutils,
83
84
    patiencediff,
641
642
    __contains__ = has_version
642
643
 
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.
647
649
        """
 
650
        if left_matching_blocks is not None:
 
651
            delta_seq = diff._PrematchedMatcher(left_matching_blocks)
 
652
        else:
 
653
            delta_seq = None
648
654
        if annotated:
649
 
            delta_seq = None
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.
656
 
                    delta_seq = seq
 
657
                if (parent_id == parents[0] and delta_seq is not None):
 
658
                    seq = delta_seq
 
659
                else:
 
660
                    seq = patiencediff.PatienceSequenceMatcher(
 
661
                        None, merge_content.text(), content.text())
657
662
                for i, j, n in seq.get_matching_blocks():
658
663
                    if n == 0:
659
664
                        continue
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
 
667
                    # parent.
664
668
                    content._lines[j:j+n] = merge_content._lines[i:i+n]
665
669
        if delta:
666
 
            if not annotated:
 
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)
731
735
 
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)
737
743
 
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)
749
755
 
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.
752
759
 
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)
802
810
 
803
811
        if delta:
804
812
            options.append('line-delta')