~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Aaron Bentley
  • Date: 2007-08-20 13:07:12 UTC
  • mfrom: (2732 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2733.
  • Revision ID: abentley@panoramicfeedback.com-20070820130712-buopmg528zcgwyxc
Merge bzr.dev

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')
1021
1029
        versions = [osutils.safe_revision_id(v) for v in versions]
1022
1030
        return self._index.get_ancestry_with_ghosts(versions)
1023
1031
 
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
1032
 
 
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]
1037
 
        
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)
1041
 
 
1042
 
        for lineno, insert_id, dset, line in w.walk(version_ids):
1043
 
            yield lineno, insert_id, dset, line
1044
 
 
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)