Rev 3279: (jam) Implement Cherrypick support for Merge3 in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Sat Mar 15 01:07:24 GMT 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3279
revision-id:pqm at pqm.ubuntu.com-20080315010714-k7pnu991eg5f0k0q
parent: pqm at pqm.ubuntu.com-20080314225929-4y11nn6gml5qfzz1
parent: john at arbash-meinel.com-20080314162755-e6cwmpv188h2ns5i
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Sat 2008-03-15 01:07:14 +0000
message:
(jam) Implement Cherrypick support for Merge3
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/merge3.py merge3.py-20050704130834-bf0597094828a2e1
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_merge3.py merge3.py-20050704130834-556689114c89e6f2
------------------------------------------------------------
revno: 3249.3.4
revision-id:john at arbash-meinel.com-20080314162755-e6cwmpv188h2ns5i
parent: john at arbash-meinel.com-20080314162328-9uc5ut91w0at3otd
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: cherrypick_merge
timestamp: Fri 2008-03-14 16:27:55 +0000
message:
NEWS for fixing bug #151731
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3249.3.3
revision-id:john at arbash-meinel.com-20080314162328-9uc5ut91w0at3otd
parent: john at arbash-meinel.com-20080314161325-3cxcyg5nerrbimt2
parent: pqm at pqm.ubuntu.com-20080314152947-u92b6klpfcnigv4e
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: cherrypick_merge
timestamp: Fri 2008-03-14 16:23:28 +0000
message:
[merge] bzr.dev 3276
added:
bzrlib/directory_service.py directory_service.py-20080305221044-vr2mkvlsk8jypa2y-1
bzrlib/tests/test_directory_service.py test_directory_servi-20080305221044-vr2mkvlsk8jypa2y-2
doc/en/admin-guide/ docenadminguide-20080305135054-y7y2c986yf94zljn-1
doc/en/admin-guide/index.txt index.txt-20080305140741-ecw0lap8dxkxc05g-1
renamed:
bzrlib/plugins/launchpad/lp_indirect.py => bzrlib/plugins/launchpad/lp_directory.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
bzrlib/plugins/launchpad/test_lp_indirect.py => bzrlib/plugins/launchpad/test_lp_directory.py test_lp_indirect.py-20070126002743-oyle362tzv9cd8mi-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/debug.py debug.py-20061102062349-vdhrw9qdpck8cl35-1
bzrlib/delta.py delta.py-20050729221636-54cf14ef94783d0a
bzrlib/deprecated_graph.py graph.py-20050905070950-b47dce53236c5e48
bzrlib/diff.py diff.py-20050309040759-26944fbbf2ebbf36
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/help_topics/__init__.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/mail_client.py mail_client.py-20070809192806-vuxt3t19srtpjpdn-1
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/merge_directive.py merge_directive.py-20070228184838-ja62280spt1g7f4x-1
bzrlib/missing.py missing.py-20050812153334-097f7097e2a8bcd1
bzrlib/plugins/launchpad/__init__.py __init__.py-20060315182712-2d5feebd2a1032dc
bzrlib/plugins/launchpad/lp_registration.py lp_registration.py-20060315190948-daa617eafe3a8d48
bzrlib/registry.py lazy_factory.py-20060809213415-2gfvqadtvdn0phtg-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/status.py status.py-20050505062338-431bfa63ec9b19e6
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_merge.py test_merge.py-20060323225809-9bc0459c19917f41
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
bzrlib/tests/blackbox/test_send.py test_bundle.py-20060616222707-c21c8b7ea5ef57b1
bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
bzrlib/tests/branch_implementations/test_revision_history.py test_revision_histor-20070326062311-v7co92liyuchb80w-1
bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_mail_client.py test_mail_client.py-20070809192806-vuxt3t19srtpjpdn-2
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_merge_directive.py test_merge_directive-20070228184838-ja62280spt1g7f4x-2
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/tests/test_registry.py test_lazy_factory.py-20060809213415-2gfvqadtvdn0phtg-2
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/tests/test_tsort.py testtsort.py-20051025073946-27da871c394d5be4
bzrlib/tests/test_upgrade.py test_upgrade.py-20051004040251-555fe1d2bae1bc71
bzrlib/tests/test_urlutils.py test_urlutils.py-20060502192900-46b1f9579987cf9c
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_merge_from_branch.py test_merge_from_bran-20060904034200-12jxyk2zlhpufxe1-1
bzrlib/tests/workingtree_implementations/test_parents.py test_set_parents.py-20060807231740-yicmnlci1mj8smu1-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
bzrlib/tsort.py tsort.py-20051025073946-7808f6aaf7d07208
bzrlib/urlutils.py urlutils.py-20060502195429-e8a161ecf8fac004
bzrlib/util/configobj/configobj.py configobj.py-20051018184548-06992a2246425e3e
bzrlib/util/configobj/docs/configobj.txt configobj.txt-20051018184548-4949b5f17e6a19c7
bzrlib/util/configobj/docs/validate.txt validate.txt-20051018184548-9e0e5ad913e258f5
bzrlib/workingtree.py workingtree.py-20050511021032-29b6ec0a681e02e3
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
doc/developers/lca-merge.txt lcamerge.txt-20080103061803-9isydn4ivgwrvorw-1
doc/en/mini-tutorial/index.txt index.txt-20070813141352-2u64ooqzo0or4hss-2
doc/en/user-guide/resolving_conflicts.txt resolving_conflicts.-20071122141511-0knao2lklsdsvb1q-5
doc/en/user-guide/version_info.txt version_info.txt-20060921215543-gju6o5xdic8w25np-1
setup.py setup.py-20050314065409-02f8a0a6e3f9bc70
bzrlib/plugins/launchpad/lp_directory.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
bzrlib/plugins/launchpad/test_lp_directory.py test_lp_indirect.py-20070126002743-oyle362tzv9cd8mi-1
------------------------------------------------------------
revno: 3249.3.2
revision-id:john at arbash-meinel.com-20080314161325-3cxcyg5nerrbimt2
parent: john at arbash-meinel.com-20080304142546-zuwwy0o9roo14928
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: cherrypick_merge
timestamp: Fri 2008-03-14 16:13:25 +0000
message:
review feedback from Robert
Use clearer variable names
profile the 'assert' section, which seemed to cost about 20% of the
time spent in find_sync_regions. (which is about 50% of merge_lines).
It seems the big overhead is actually iter_merge3(). So for now,
leave the asserts in, -O will remove them anyway.
modified:
bzrlib/merge3.py merge3.py-20050704130834-bf0597094828a2e1
------------------------------------------------------------
revno: 3249.3.1
revision-id:john at arbash-meinel.com-20080304142546-zuwwy0o9roo14928
parent: pqm at pqm.ubuntu.com-20080304003709-35vh1eqa8tuuq548
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: cherrypick_merge
timestamp: Tue 2008-03-04 14:25:46 +0000
message:
Implement cherrypick support for Merge3
When merging a cherrypick, use a slightly different resolve logic.
When encountering a conflict, the new logic does not include lines that
were present in BASE that are conflicting with OTHER.
This is done since a cherrypick is (by definition) avoiding changes that
are present in the base.
(related to bug #151731)
modified:
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/merge3.py merge3.py-20050704130834-bf0597094828a2e1
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_merge3.py merge3.py-20050704130834-556689114c89e6f2
=== modified file 'NEWS'
--- a/NEWS 2008-03-14 19:44:24 +0000
+++ b/NEWS 2008-03-15 01:07:14 +0000
@@ -65,6 +65,9 @@
BUGFIXES:
+ * Cherrypicking when using ``--format=merge3`` now explictly excludes
+ BASE lines. (John Arbash Meinel, #151731)
+
* Disable plink's interactive prompt for password.
(#107593, Dmitry Vasiliev)
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2008-03-07 14:15:10 +0000
+++ b/bzrlib/merge.py 2008-03-14 16:23:28 +0000
@@ -116,7 +116,9 @@
def _get_base_is_other_ancestor(self):
if self._base_is_other_ancestor is None:
- self.base_is_other_ancestor = self.revision_graph.is_ancestor(
+ if self.other_basis is None:
+ return True
+ self._base_is_other_ancestor = self.revision_graph.is_ancestor(
self.base_rev_id, self.other_basis)
return self._base_is_other_ancestor
@@ -162,7 +164,7 @@
return merger, verified
@staticmethod
- def from_revision_ids(pb, this, other, base=None, other_branch=None,
+ def from_revision_ids(pb, tree, other, base=None, other_branch=None,
base_branch=None, revision_graph=None):
"""Return a Merger for revision-ids.
@@ -171,15 +173,17 @@
:param base: The revision-id to use as BASE. If not specified, will
be auto-selected.
:param other_branch: A branch containing the other revision-id. If
- not supplied, this.branch is used.
+ not supplied, tree.branch is used.
:param base_branch: A branch containing the base revision-id. If
- not supplied, other_branch or this.branch will be used.
+ not supplied, other_branch or tree.branch will be used.
+ :param revision_graph: If you have a revision_graph precomputed, pass
+ it in, otherwise it will be created for you.
:param pb: A progress indicator
"""
- merger = Merger(this.branch, this_tree=this, pb=pb,
+ merger = Merger(tree.branch, this_tree=tree, pb=pb,
revision_graph=revision_graph)
if other_branch is None:
- other_branch = this.branch
+ other_branch = tree.branch
merger.set_other_revision(other, other_branch)
if base is None:
merger.find_base()
@@ -399,7 +403,7 @@
if (not getattr(self.merge_type, 'supports_reverse_cherrypick', True)
and not self.base_is_other_ancestor):
raise errors.CannotReverseCherrypick()
- if self.merge_type.history_based:
+ if self.merge_type.supports_cherrypick:
kwargs['cherrypick'] = (not self.base_is_ancestor or
not self.base_is_other_ancestor)
return self.merge_type(pb=self._pb,
@@ -407,13 +411,13 @@
**kwargs)
def do_merge(self):
- merge = self.make_merger()
self.this_tree.lock_tree_write()
if self.base_tree is not None:
self.base_tree.lock_read()
if self.other_tree is not None:
self.other_tree.lock_read()
try:
+ merge = self.make_merger()
merge.do_merge()
if self.recurse == 'down':
for path, file_id in self.this_tree.iter_references():
@@ -430,6 +434,7 @@
base_revision = self.base_tree.get_reference_revision(file_id)
sub_merge.base_tree = \
sub_tree.branch.repository.revision_tree(base_revision)
+ sub_merge.base_rev_id = base_revision
sub_merge.do_merge()
finally:
@@ -453,13 +458,15 @@
supports_reprocess = True
supports_show_base = True
history_based = False
+ supports_cherrypick = True
supports_reverse_cherrypick = True
winner_idx = {"this": 2, "other": 1, "conflict": 1}
def __init__(self, working_tree, this_tree, base_tree, other_tree,
interesting_ids=None, reprocess=False, show_base=False,
pb=DummyProgress(), pp=None, change_reporter=None,
- interesting_files=None, do_merge=True):
+ interesting_files=None, do_merge=True,
+ cherrypick=False):
"""Initialize the merger object and perform the merge.
:param working_tree: The working tree to apply the merge to
@@ -497,6 +504,7 @@
self.pb = pb
self.pp = pp
self.change_reporter = change_reporter
+ self.cherrypick = cherrypick
if self.pp is None:
self.pp = ProgressPhase("Merge phase", 3, self.pb)
if do_merge:
@@ -865,7 +873,8 @@
base_lines = []
other_lines = self.get_lines(self.other_tree, file_id)
this_lines = self.get_lines(self.this_tree, file_id)
- m3 = Merge3(base_lines, this_lines, other_lines)
+ m3 = Merge3(base_lines, this_lines, other_lines,
+ is_cherrypick=self.cherrypick)
start_marker = "!START OF MERGE CONFLICT!" + "I HOPE THIS IS UNIQUE"
if self.show_base is True:
base_marker = '|' * 7
@@ -1040,19 +1049,6 @@
supports_reverse_cherrypick = False
history_based = True
- def __init__(self, working_tree, this_tree, base_tree, other_tree,
- interesting_ids=None, pb=DummyProgress(), pp=None,
- reprocess=False, change_reporter=None,
- interesting_files=None, cherrypick=False, do_merge=True):
- self.cherrypick = cherrypick
- super(WeaveMerger, self).__init__(working_tree, this_tree,
- base_tree, other_tree,
- interesting_files=interesting_files,
- interesting_ids=interesting_ids,
- pb=pb, pp=pp, reprocess=reprocess,
- change_reporter=change_reporter,
- do_merge=do_merge)
-
def _merged_lines(self, file_id):
"""Generate the merged lines.
There is no distinction between lines that are meant to contain <<<<<<<
@@ -1195,6 +1191,10 @@
merger.reprocess = reprocess
merger.other_rev_id = other_rev_id
merger.other_basis = other_rev_id
+ get_revision_id = getattr(base_tree, 'get_revision_id', None)
+ if get_revision_id is None:
+ get_revision_id = base_tree.last_revision
+ merger.set_base_revision(get_revision_id(), this_branch)
return merger.do_merge()
def get_merge_type_registry():
=== modified file 'bzrlib/merge3.py'
--- a/bzrlib/merge3.py 2007-03-12 19:56:41 +0000
+++ b/bzrlib/merge3.py 2008-03-14 16:13:25 +0000
@@ -67,15 +67,14 @@
Given BASE, OTHER, THIS, tries to produce a combined text
incorporating the changes from both BASE->OTHER and BASE->THIS.
All three will typically be sequences of lines."""
- def __init__(self, base, a, b):
+ def __init__(self, base, a, b, is_cherrypick=False):
check_text_lines(base)
check_text_lines(a)
check_text_lines(b)
self.base = base
self.a = a
self.b = b
-
-
+ self.is_cherrypick = is_cherrypick
def merge_lines(self,
name_a=None,
@@ -130,10 +129,6 @@
yield end_marker + newline
else:
raise ValueError(what)
-
-
-
-
def merge_annotated(self):
"""Return merge with conflicts, showing origin of lines.
@@ -161,10 +156,6 @@
yield '>>>>\n'
else:
raise ValueError(what)
-
-
-
-
def merge_groups(self):
"""Yield sequence of line groups. Each one is a tuple:
@@ -200,7 +191,6 @@
else:
raise ValueError(what)
-
def merge_regions(self):
"""Return sequences of matching and conflicting regions.
@@ -250,23 +240,30 @@
if len_a or len_b:
# try to avoid actually slicing the lists
- equal_a = compare_range(self.a, ia, amatch,
- self.base, iz, zmatch)
- equal_b = compare_range(self.b, ib, bmatch,
- self.base, iz, zmatch)
same = compare_range(self.a, ia, amatch,
self.b, ib, bmatch)
if same:
yield 'same', ia, amatch
- elif equal_a and not equal_b:
- yield 'b', ib, bmatch
- elif equal_b and not equal_a:
- yield 'a', ia, amatch
- elif not equal_a and not equal_b:
- yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
else:
- raise AssertionError("can't handle a=b=base but unmatched")
+ equal_a = compare_range(self.a, ia, amatch,
+ self.base, iz, zmatch)
+ equal_b = compare_range(self.b, ib, bmatch,
+ self.base, iz, zmatch)
+ if equal_a and not equal_b:
+ yield 'b', ib, bmatch
+ elif equal_b and not equal_a:
+ yield 'a', ia, amatch
+ elif not equal_a and not equal_b:
+ if self.is_cherrypick:
+ for node in self._refine_cherrypick_conflict(
+ iz, zmatch, ia, amatch,
+ ib, bmatch):
+ yield node
+ else:
+ yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
+ else:
+ raise AssertionError("can't handle a=b=base but unmatched")
ia = amatch
ib = bmatch
@@ -275,7 +272,6 @@
# if the same part of the base was deleted on both sides
# that's OK, we can just skip it.
-
if matchlen > 0:
assert ia == amatch
assert ib == bmatch
@@ -285,7 +281,46 @@
iz = zend
ia = aend
ib = bend
-
+
+ def _refine_cherrypick_conflict(self, zstart, zend, astart, aend, bstart, bend):
+ """When cherrypicking b => a, ignore matches with b and base."""
+ # Do not emit regions which match, only regions which do not match
+ matches = bzrlib.patiencediff.PatienceSequenceMatcher(None,
+ self.base[zstart:zend], self.b[bstart:bend]).get_matching_blocks()
+ last_base_idx = 0
+ last_b_idx = 0
+ last_b_idx = 0
+ yielded_a = False
+ for base_idx, b_idx, match_len in matches:
+ conflict_z_len = base_idx - last_base_idx
+ conflict_b_len = b_idx - last_b_idx
+ if conflict_b_len == 0: # There are no lines in b which conflict,
+ # so skip it
+ pass
+ else:
+ if yielded_a:
+ yield ('conflict',
+ zstart + last_base_idx, zstart + base_idx,
+ aend, aend, bstart + last_b_idx, bstart + b_idx)
+ else:
+ # The first conflict gets the a-range
+ yielded_a = True
+ yield ('conflict', zstart + last_base_idx, zstart +
+ base_idx,
+ astart, aend, bstart + last_b_idx, bstart + b_idx)
+ last_base_idx = base_idx + match_len
+ last_b_idx = b_idx + match_len
+ if last_base_idx != zend - zstart or last_b_idx != bend - bstart:
+ if yielded_a:
+ yield ('conflict', zstart + last_base_idx, zstart + base_idx,
+ aend, aend, bstart + last_b_idx, bstart + b_idx)
+ else:
+ # The first conflict gets the a-range
+ yielded_a = True
+ yield ('conflict', zstart + last_base_idx, zstart + base_idx,
+ astart, aend, bstart + last_b_idx, bstart + b_idx)
+ if not yielded_a:
+ yield ('conflict', zstart, zend, astart, aend, bstart, bend)
def reprocess_merge_regions(self, merge_regions):
"""Where there are conflict regions, remove the agreed lines.
@@ -318,12 +353,10 @@
if reg is not None:
yield reg
-
@staticmethod
def mismatch_region(next_a, region_ia, next_b, region_ib):
if next_a < region_ia or next_b < region_ib:
return 'conflict', None, None, next_a, region_ia, next_b, region_ib
-
def find_sync_regions(self):
"""Return a list of sync regions, where both descendents match the base.
@@ -388,8 +421,6 @@
return sl
-
-
def find_unconflicted(self):
"""Return a list of ranges in base that are not conflicted."""
am = bzrlib.patiencediff.PatienceSequenceMatcher(
=== modified file 'bzrlib/tests/test_merge.py'
--- a/bzrlib/tests/test_merge.py 2008-03-03 17:39:50 +0000
+++ b/bzrlib/tests/test_merge.py 2008-03-14 16:23:28 +0000
@@ -352,6 +352,30 @@
merger.merge_type = _mod_merge.Merge3Merger
merger.do_merge()
+ def test_merge3_will_detect_cherrypick(self):
+ this_tree = self.make_branch_and_tree('this')
+ self.build_tree_contents([('this/file', "a\n")])
+ this_tree.add('file')
+ this_tree.commit('rev1')
+ other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
+ self.build_tree_contents([('other/file', "a\nb\n")])
+ other_tree.commit('rev2b', rev_id='rev2b')
+ self.build_tree_contents([('other/file', "a\nb\nc\n")])
+ other_tree.commit('rev3b', rev_id='rev3b')
+ this_tree.lock_write()
+ self.addCleanup(this_tree.unlock)
+
+ merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
+ this_tree, 'rev3b', 'rev2b', other_tree.branch)
+ merger.merge_type = _mod_merge.Merge3Merger
+ merger.do_merge()
+ self.assertFileEqual('a\n'
+ '<<<<<<< TREE\n'
+ '=======\n'
+ 'c\n'
+ '>>>>>>> MERGE-SOURCE\n',
+ 'this/file')
+
def test_make_merger(self):
this_tree = self.make_branch_and_tree('this')
this_tree.commit('rev1', rev_id='rev1')
=== modified file 'bzrlib/tests/test_merge3.py'
--- a/bzrlib/tests/test_merge3.py 2007-03-12 19:56:41 +0000
+++ b/bzrlib/tests/test_merge3.py 2008-03-04 14:25:46 +0000
@@ -383,3 +383,42 @@
m_lines = m3.merge_lines('OTHER', 'THIS')
self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
'>>>>>>> THIS\r'.splitlines(True), list(m_lines))
+
+ def test_merge3_cherrypick(self):
+ base_text = "a\nb\n"
+ this_text = "a\n"
+ other_text = "a\nb\nc\n"
+ # When cherrypicking, lines in base are not part of the conflict
+ m3 = Merge3(base_text.splitlines(True), this_text.splitlines(True),
+ other_text.splitlines(True), is_cherrypick=True)
+ m_lines = m3.merge_lines()
+ self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
+ ''.join(m_lines))
+
+ # This is not symmetric
+ m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
+ this_text.splitlines(True), is_cherrypick=True)
+ m_lines = m3.merge_lines()
+ self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
+ ''.join(m_lines))
+
+ def test_merge3_cherrypick_w_mixed(self):
+ base_text = 'a\nb\nc\nd\ne\n'
+ this_text = 'a\nb\nq\n'
+ other_text = 'a\nb\nc\nd\nf\ne\ng\n'
+ # When cherrypicking, lines in base are not part of the conflict
+ m3 = Merge3(base_text.splitlines(True), this_text.splitlines(True),
+ other_text.splitlines(True), is_cherrypick=True)
+ m_lines = m3.merge_lines()
+ self.assertEqualDiff('a\n'
+ 'b\n'
+ '<<<<<<<\n'
+ 'q\n'
+ '=======\n'
+ 'f\n'
+ '>>>>>>>\n'
+ '<<<<<<<\n'
+ '=======\n'
+ 'g\n'
+ '>>>>>>>\n',
+ ''.join(m_lines))
More information about the bazaar-commits
mailing list