mercurial/mdiff.py
changeset 0 9117c6561b0b
child 35 9197c26a414b
equal deleted inserted replaced
-1:000000000000 0:9117c6561b0b
       
     1 #!/usr/bin/python
       
     2 import difflib, struct
       
     3 from cStringIO import StringIO
       
     4 
       
     5 def unidiff(a, b, fn):
       
     6     a = a.splitlines(1)
       
     7     b = b.splitlines(1)
       
     8     l = difflib.unified_diff(a, b, fn, fn)
       
     9     return "".join(l)
       
    10 
       
    11 def textdiff(a, b):
       
    12     return diff(a.splitlines(1), b.splitlines(1))
       
    13 
       
    14 def sortdiff(a, b):
       
    15     la = lb = 0
       
    16 
       
    17     while 1:
       
    18         if la >= len(a) or lb >= len(b): break
       
    19         if b[lb] < a[la]:
       
    20             si = lb
       
    21             while lb < len(b) and b[lb] < a[la] : lb += 1
       
    22             yield "insert", la, la, si, lb
       
    23         elif a[la] < b[lb]:
       
    24             si = la
       
    25             while la < len(a) and a[la] < b[lb]: la += 1
       
    26             yield "delete", si, la, lb, lb
       
    27         else:
       
    28             la += 1
       
    29             lb += 1
       
    30 
       
    31     si = lb
       
    32     while lb < len(b):
       
    33         lb += 1
       
    34         yield "insert", la, la, si, lb
       
    35 
       
    36     si = la
       
    37     while la < len(a):
       
    38         la += 1
       
    39         yield "delete", si, la, lb, lb
       
    40 
       
    41 def diff(a, b, sorted=0):
       
    42     bin = []
       
    43     p = [0]
       
    44     for i in a: p.append(p[-1] + len(i))
       
    45 
       
    46     if sorted:
       
    47         d = sortdiff(a, b)
       
    48     else:
       
    49         d = difflib.SequenceMatcher(None, a, b).get_opcodes()
       
    50 
       
    51     for o, m, n, s, t in d:
       
    52         if o == 'equal': continue
       
    53         s = "".join(b[s:t])
       
    54         bin.append(struct.pack(">lll", p[m], p[n], len(s)) + s)
       
    55 
       
    56     return "".join(bin)
       
    57 
       
    58 def patch(a, bin):
       
    59     last = pos = 0
       
    60     r = []
       
    61 
       
    62     while pos < len(bin):
       
    63         p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
       
    64         pos += 12
       
    65         r.append(a[last:p1])
       
    66         r.append(bin[pos:pos + l])
       
    67         pos += l
       
    68         last = p2
       
    69     r.append(a[last:])
       
    70 
       
    71     return "".join(r)
       
    72 
       
    73 
       
    74 
       
    75 
       
    76