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)
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.
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()
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)):
945
if tree.get_file_sha1(file_id) != rt.get_file_sha1(file_id):
946
raise WorkingTreeNotRevision(self.this_tree)
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 <<<<<<<
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)
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.
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,
1066
1042
from bzrlib import option
1067
1043
return option._merge_type_registry
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
1051
return 'new-a', text
1053
def status_b(revision, text):
1054
if revision in ancestors_a:
1055
return 'killed-a', text
1057
return 'new-b', text
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()
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)
1074
# and now the matched section
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