~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-07-20 13:31:43 UTC
  • mfrom: (1551.15.54 Aaron's mergeable stuff)
  • Revision ID: pqm@pqm.ubuntu.com-20070720133143-r74lo566tluurmfp
fix annotate merge to not require Tree.get_weave

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from bzrlib import (
23
23
    errors,
24
24
    osutils,
 
25
    patiencediff,
25
26
    registry,
26
27
    revision as _mod_revision,
27
28
    )
49
50
from bzrlib.transform import (TreeTransform, resolve_conflicts, cook_conflicts,
50
51
                              conflict_pass, FinalPaths, create_by_entry,
51
52
                              unique_add, ROOT_PARENT)
52
 
from bzrlib.versionedfile import WeaveMerge
 
53
from bzrlib.versionedfile import PlanWeaveMerge
53
54
from bzrlib import ui
54
55
 
55
56
# TODO: Report back as changes are merged in
918
919
                 interesting_ids=None, pb=DummyProgress(), pp=None,
919
920
                 reprocess=False, change_reporter=None,
920
921
                 interesting_files=None):
921
 
        self.this_revision_tree = self._get_revision_tree(this_tree)
922
 
        self.other_revision_tree = self._get_revision_tree(other_tree)
923
922
        super(WeaveMerger, self).__init__(working_tree, this_tree, 
924
923
                                          base_tree, other_tree, 
925
924
                                          interesting_ids=interesting_ids, 
926
925
                                          pb=pb, pp=pp, reprocess=reprocess,
927
926
                                          change_reporter=change_reporter)
928
927
 
929
 
    def _get_revision_tree(self, tree):
930
 
        """Return a revision tree related to this tree.
931
 
        If the tree is a WorkingTree, the basis will be returned.
932
 
        """
933
 
        if getattr(tree, 'get_weave', False) is False:
934
 
            # If we have a WorkingTree, try using the basis
935
 
            return tree.branch.basis_tree()
936
 
        else:
937
 
            return tree
938
 
 
939
 
    def _check_file(self, file_id):
940
 
        """Check that the revision tree's version of the file matches."""
941
 
        for tree, rt in ((self.this_tree, self.this_revision_tree), 
942
 
                         (self.other_tree, self.other_revision_tree)):
943
 
            if rt is tree:
944
 
                continue
945
 
            if tree.get_file_sha1(file_id) != rt.get_file_sha1(file_id):
946
 
                raise WorkingTreeNotRevision(self.this_tree)
947
 
 
948
928
    def _merged_lines(self, file_id):
949
929
        """Generate the merged lines.
950
930
        There is no distinction between lines that are meant to contain <<<<<<<
951
931
        and conflicts.
952
932
        """
953
 
        weave = self.this_revision_tree.get_weave(file_id)
954
 
        this_revision_id = self.this_revision_tree.inventory[file_id].revision
955
 
        other_revision_id = \
956
 
            self.other_revision_tree.inventory[file_id].revision
957
 
        wm = WeaveMerge(weave, this_revision_id, other_revision_id, 
958
 
                        '<<<<<<< TREE\n', '>>>>>>> MERGE-SOURCE\n')
959
 
        return wm.merge_lines(self.reprocess)
 
933
        plan = self.this_tree.plan_file_merge(file_id, self.other_tree)
 
934
        textmerge = PlanWeaveMerge(plan, '<<<<<<< TREE\n',
 
935
            '>>>>>>> MERGE-SOURCE\n')
 
936
        return textmerge.merge_lines(self.reprocess)
960
937
 
961
938
    def text_merge(self, file_id, trans_id):
962
939
        """Perform a (weave) text merge for a given file and file-id.
963
940
        If conflicts are encountered, .THIS and .OTHER files will be emitted,
964
941
        and a conflict will be noted.
965
942
        """
966
 
        self._check_file(file_id)
967
943
        lines, conflicts = self._merged_lines(file_id)
968
944
        lines = list(lines)
969
945
        # Note we're checking whether the OUTPUT is binary in this case, 
1065
1041
    """
1066
1042
    from bzrlib import option
1067
1043
    return option._merge_type_registry
 
1044
 
 
1045
 
 
1046
def _plan_annotate_merge(annotated_a, annotated_b, ancestors_a, ancestors_b):
 
1047
    def status_a(revision, text):
 
1048
        if revision in ancestors_b:
 
1049
            return 'killed-b', text
 
1050
        else:
 
1051
            return 'new-a', text
 
1052
 
 
1053
    def status_b(revision, text):
 
1054
        if revision in ancestors_a:
 
1055
            return 'killed-a', text
 
1056
        else:
 
1057
            return 'new-b', text
 
1058
 
 
1059
    plain_a = [t for (a, t) in annotated_a]
 
1060
    plain_b = [t for (a, t) in annotated_b]
 
1061
    matcher = patiencediff.PatienceSequenceMatcher(None, plain_a, plain_b)
 
1062
    blocks = matcher.get_matching_blocks()
 
1063
    a_cur = 0
 
1064
    b_cur = 0
 
1065
    for ai, bi, l in blocks:
 
1066
        # process all mismatched sections
 
1067
        # (last mismatched section is handled because blocks always
 
1068
        # includes a 0-length last block)
 
1069
        for revision, text in annotated_a[a_cur:ai]:
 
1070
            yield status_a(revision, text)
 
1071
        for revision, text in annotated_b[b_cur:bi]:
 
1072
            yield status_b(revision, text)
 
1073
 
 
1074
        # and now the matched section
 
1075
        a_cur = ai + l
 
1076
        b_cur = bi + l
 
1077
        for text_a, text_b in zip(plain_a[ai:a_cur], plain_b[bi:b_cur]):
 
1078
            assert text_a == text_b
 
1079
            yield "unchanged", text_a