[Pkg-bazaar-commits] ./bzr/unstable r822: - Renamed merge3 test suite for easier access.
Martin Pool
mbp at sourcefrog.net
Fri Apr 10 08:21:08 UTC 2009
------------------------------------------------------------
revno: 822
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Tue 2005-07-05 17:19:12 +1000
message:
- Renamed merge3 test suite for easier access.
- New merge approach based on finding triple-matching regions, and comparing
the regions between them; add find_sync_regions() and some tests for it.
renamed:
bzrlib/selftest/merge3.py => bzrlib/selftest/testmerge3.py
modified:
bzrlib/merge3.py
bzrlib/selftest/__init__.py
bzrlib/selftest/testmerge3.py
-------------- next part --------------
=== modified file 'bzrlib/merge3.py'
--- a/bzrlib/merge3.py 2005-07-04 13:08:55 +0000
+++ b/bzrlib/merge3.py 2005-07-05 07:19:12 +0000
@@ -39,6 +39,16 @@
return None
+def threeway(baseline, aline, bline):
+ if baseline == aline:
+ return bline
+ elif baseline == bline:
+ return aline
+ else:
+ return [aline, bline]
+
+
+
class Merge3(object):
"""3-way merge of texts.
@@ -49,21 +59,75 @@
self.base = base
self.a = a
self.b = b
-
- #from difflib import SequenceMatcher
-
- #self.a_ops = SequenceMatcher(None, self.base, self.a).get_opcodes()
- #self.b_ops = SequenceMatcher(None, self.base, self.b).get_opcodes()
+ from difflib import SequenceMatcher
+ self.a_ops = SequenceMatcher(None, base, a).get_opcodes()
+ self.b_ops = SequenceMatcher(None, base, b).get_opcodes()
+
+
+ def merge(self):
+ """Return sequences of matching and conflicting regions.
+
+ Method is as follows:
+
+ The two sequences align only on regions which match the base
+ and both descendents. These are found by doing a two-way diff
+ of each one against the base, and then finding the
+ intersections between those regions. These "sync regions"
+ are by definition unchanged in both and easily dealt with.
+
+ The regions in between can be in any of three cases:
+ conflicted, or changed on only one side.
+ """
- def find_conflicts(self):
- """Return a list of conflict regions.
-
- Each entry is given as (base1, base2, a1, a2, b1, b2).
-
- This indicates that the range [base1,base2] can be replaced by either
- [a1,a2] or [b1,b2].
+ def find_sync_regions(self):
+ """Return a list of sync regions, where both descendents match the base.
+
+ Generates a list of ((base1, base2), (a1, a2), (b1, b2)).
"""
+ from difflib import SequenceMatcher
+ aiter = iter(SequenceMatcher(None, self.base, self.a).get_matching_blocks())
+ biter = iter(SequenceMatcher(None, self.base, self.b).get_matching_blocks())
+
+ abase, amatch, alen = aiter.next()
+ bbase, bmatch, blen = biter.next()
+
+ while aiter and biter:
+ # there is an unconflicted block at i; how long does it
+ # extend? until whichever one ends earlier.
+ i = intersect((abase, abase+alen), (bbase, bbase+blen))
+ if i:
+ intbase = i[0]
+ intend = i[1]
+ intlen = intend - intbase
+
+ # found a match of base[i[0], i[1]]; this may be less than
+ # the region that matches in either one
+ assert intlen <= alen
+ assert intlen <= blen
+ assert abase <= intbase
+ assert bbase <= intbase
+
+ asub = amatch + (intbase - abase)
+ bsub = bmatch + (intbase - bbase)
+ aend = asub + intlen
+ bend = bsub + intlen
+
+ assert self.base[intbase:intend] == self.a[asub:aend], \
+ (self.base[intbase:intend], self.a[asub:aend])
+
+ assert self.base[intbase:intend] == self.b[bsub:bend]
+
+ yield ((intbase, intend),
+ (asub, aend),
+ (bsub, bend))
+
+ # advance whichever one ends first in the base text
+ if (abase + alen) < (bbase + blen):
+ abase, amatch, alen = aiter.next()
+ else:
+ bbase, bmatch, blen = biter.next()
+
def find_unconflicted(self):
=== modified file 'bzrlib/selftest/__init__.py'
--- a/bzrlib/selftest/__init__.py 2005-07-04 13:08:55 +0000
+++ b/bzrlib/selftest/__init__.py 2005-07-05 07:19:12 +0000
@@ -214,7 +214,7 @@
import bzrlib.selftest.whitebox
import bzrlib.selftest.blackbox
import bzrlib.selftest.versioning
- import bzrlib.selftest.merge3
+ import bzrlib.selftest.testmerge3
import bzrlib.merge_core
from doctest import DocTestSuite
import os
@@ -237,7 +237,7 @@
for m in bzrlib.selftest.whitebox, \
bzrlib.selftest.versioning, \
- bzrlib.selftest.merge3:
+ bzrlib.selftest.testmerge3:
suite.addTest(tl.loadTestsFromModule(m))
for m in bzrlib.store, bzrlib.inventory, bzrlib.branch, bzrlib.osutils, \
=== renamed file 'bzrlib/selftest/merge3.py' => 'bzrlib/selftest/testmerge3.py'
--- a/bzrlib/selftest/merge3.py 2005-07-04 13:08:55 +0000
+++ b/bzrlib/selftest/testmerge3.py 2005-07-05 07:19:12 +0000
@@ -18,17 +18,6 @@
from bzrlib.selftest import InTempDir, TestBase
from bzrlib.merge3 import Merge3
-class NoConflicts(TestBase):
- """No conflicts because only one side changed"""
- def runTest(self):
- m3 = Merge3(['aaa', 'bbb'],
- ['aaa', '111', 'bbb'],
- ['aaa', 'bbb'])
-
- self.assertEquals(m3.find_unconflicted(),
- [(0, 1), (1, 2)])
-
-
class NoChanges(TestBase):
"""No conflicts because nothing changed"""
def runTest(self):
@@ -39,8 +28,27 @@
self.assertEquals(m3.find_unconflicted(),
[(0, 2)])
+ self.assertEquals(list(m3.find_sync_regions()),
+ [((0, 2), (0, 2), (0, 2))])
+
+class NoConflicts(TestBase):
+ """No conflicts because only one side changed"""
+ def runTest(self):
+ m3 = Merge3(['aaa', 'bbb'],
+ ['aaa', '111', 'bbb'],
+ ['aaa', 'bbb'])
+
+ self.assertEquals(m3.find_unconflicted(),
+ [(0, 1), (1, 2)])
+
+
+ self.assertEquals(list(m3.find_sync_regions()),
+ [((0, 1), (0, 1), (0, 1)),
+ ((1, 2), (2, 3), (1, 2))])
+
+
class InsertClash(TestBase):
"""Both try to insert lines in the same place."""
def runTest(self):
@@ -51,7 +59,9 @@
self.assertEquals(m3.find_unconflicted(),
[(0, 1), (1, 2)])
-
+ self.assertEquals(list(m3.find_sync_regions()),
+ [((0, 1), (0, 1), (0, 1)),
+ ((1, 2), (2, 3), (2, 3))])
@@ -65,4 +75,26 @@
self.assertEquals(m3.find_unconflicted(),
[(0, 1), (2, 3)])
+ self.assertEquals(list(m3.find_sync_regions()),
+ [((0, 1), (0, 1), (0, 1)),
+ ((2, 3), (2, 3), (2, 3))])
+
+
+
+class ReplaceMulti(TestBase):
+ """Replacement with regions of different size."""
+ def runTest(self):
+ m3 = Merge3(['aaa', '000', '000', 'bbb'],
+ ['aaa', '111', '111', '111', 'bbb'],
+ ['aaa', '222', '222', '222', '222', 'bbb'])
+
+ self.assertEquals(m3.find_unconflicted(),
+ [(0, 1), (3, 4)])
+
+
+ self.assertEquals(list(m3.find_sync_regions()),
+ [((0, 1), (0, 1), (0, 1)),
+ ((3, 4), (4, 5), (5, 6))])
+
+
More information about the Pkg-bazaar-commits
mailing list