contrib/simplemerge
changeset 4359 2e3c54fb79a3
parent 4358 465b9ea02868
child 4360 d5c3a70f8422
old mode 100644
new mode 100755
--- a/contrib/simplemerge
+++ b/contrib/simplemerge
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (C) 2004, 2005 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
@@ -19,9 +20,12 @@
 # s: "i hate that."
 
 
-from bzrlib.errors import CantReprocessAndShowBase
-import bzrlib.patiencediff
-from bzrlib.textfile import check_text_lines
+from mercurial import util, mdiff
+from mercurial.i18n import _
+
+
+class CantReprocessAndShowBase(Exception):
+    pass
 
 
 def intersect(ra, rb):
@@ -61,16 +65,21 @@ def compare_range(a, astart, aend, b, bs
 
 
 
-class Merge3(object):
+class Merge3Text(object):
     """3-way merge of texts.
 
-    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):
-        check_text_lines(base)
-        check_text_lines(a)
-        check_text_lines(b)
+    Given strings BASE, OTHER, THIS, tries to produce a combined text
+    incorporating the changes from both BASE->OTHER and BASE->THIS."""
+    def __init__(self, basetext, atext, btext, base=None, a=None, b=None):
+        self.basetext = basetext
+        self.atext = atext
+        self.btext = btext
+        if base is None:
+            base = mdiff.splitnewlines(basetext)
+        if a is None:
+            a = mdiff.splitnewlines(atext)
+        if b is None:
+            b = mdiff.splitnewlines(btext)
         self.base = base
         self.a = a
         self.b = b
@@ -300,8 +309,8 @@ class Merge3(object):
             type, iz, zmatch, ia, amatch, ib, bmatch = region
             a_region = self.a[ia:amatch]
             b_region = self.b[ib:bmatch]
-            matches = bzrlib.patiencediff.PatienceSequenceMatcher(
-                    None, a_region, b_region).get_matching_blocks()
+            matches = mdiff.get_matching_blocks(''.join(a_region),
+                                                ''.join(b_region))
             next_a = ia
             next_b = ib
             for region_ia, region_ib, region_len in matches[:-1]:
@@ -319,10 +328,10 @@ class Merge3(object):
                 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
+    mismatch_region = staticmethod(mismatch_region)
             
 
     def find_sync_regions(self):
@@ -333,10 +342,8 @@ class Merge3(object):
         """
 
         ia = ib = 0
-        amatches = bzrlib.patiencediff.PatienceSequenceMatcher(
-                None, self.base, self.a).get_matching_blocks()
-        bmatches = bzrlib.patiencediff.PatienceSequenceMatcher(
-                None, self.base, self.b).get_matching_blocks()
+        amatches = mdiff.get_matching_blocks(self.basetext, self.atext)
+        bmatches = mdiff.get_matching_blocks(self.basetext, self.btext)
         len_a = len(amatches)
         len_b = len(bmatches)
 
@@ -392,10 +399,8 @@ class Merge3(object):
 
     def find_unconflicted(self):
         """Return a list of ranges in base that are not conflicted."""
-        am = bzrlib.patiencediff.PatienceSequenceMatcher(
-                None, self.base, self.a).get_matching_blocks()
-        bm = bzrlib.patiencediff.PatienceSequenceMatcher(
-                None, self.base, self.b).get_matching_blocks()
+        am = mdiff.get_matching_blocks(self.basetext, self.atext)
+        bm = mdiff.get_matching_blocks(self.basetext, self.btext)
 
         unc = []
 
@@ -418,6 +423,22 @@ class Merge3(object):
         return unc
 
 
+# bzr compatible interface, for the tests
+class Merge3(Merge3Text):
+    """3-way merge of texts.
+
+    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):
+        basetext = '\n'.join([i.strip('\n') for i in base] + [''])
+        atext = '\n'.join([i.strip('\n') for i in a] + [''])
+        btext = '\n'.join([i.strip('\n') for i in b] + [''])
+        if util.binary(basetext) or util.binary(atext) or util.binary(btext):
+            raise util.Abort(_("don't know how to merge binary files"))
+        Merge3Text.__init__(self, basetext, atext, btext, base, a, b)
+
+
 def main(argv):
     # as for diff3 and meld the syntax is "MINE BASE OTHER"
     a = file(argv[1], 'rt').readlines()