##// END OF EJS Templates
py3: use bytes() to cast to immutable bytes in pure.bdiff.bdiff()
Yuya Nishihara -
r31641:f2b334e6 default
parent child Browse files
Show More
@@ -1,165 +1,162 b''
1 1 # bdiff.py - Python implementation of bdiff.c
2 2 #
3 3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import difflib
11 11 import re
12 12 import struct
13 13
14 14 from . import policy
15 15 policynocffi = policy.policynocffi
16 16 modulepolicy = policy.policy
17 17
18 18 def splitnewlines(text):
19 19 '''like str.splitlines, but only split on newlines.'''
20 20 lines = [l + '\n' for l in text.split('\n')]
21 21 if lines:
22 22 if lines[-1] == '\n':
23 23 lines.pop()
24 24 else:
25 25 lines[-1] = lines[-1][:-1]
26 26 return lines
27 27
28 28 def _normalizeblocks(a, b, blocks):
29 29 prev = None
30 30 r = []
31 31 for curr in blocks:
32 32 if prev is None:
33 33 prev = curr
34 34 continue
35 35 shift = 0
36 36
37 37 a1, b1, l1 = prev
38 38 a1end = a1 + l1
39 39 b1end = b1 + l1
40 40
41 41 a2, b2, l2 = curr
42 42 a2end = a2 + l2
43 43 b2end = b2 + l2
44 44 if a1end == a2:
45 45 while (a1end + shift < a2end and
46 46 a[a1end + shift] == b[b1end + shift]):
47 47 shift += 1
48 48 elif b1end == b2:
49 49 while (b1end + shift < b2end and
50 50 a[a1end + shift] == b[b1end + shift]):
51 51 shift += 1
52 52 r.append((a1, b1, l1 + shift))
53 53 prev = a2 + shift, b2 + shift, l2 - shift
54 54 r.append(prev)
55 55 return r
56 56
57 def _tostring(c):
58 return str(c)
59
60 57 def bdiff(a, b):
61 a = _tostring(a).splitlines(True)
62 b = _tostring(b).splitlines(True)
58 a = bytes(a).splitlines(True)
59 b = bytes(b).splitlines(True)
63 60
64 61 if not a:
65 62 s = "".join(b)
66 63 return s and (struct.pack(">lll", 0, 0, len(s)) + s)
67 64
68 65 bin = []
69 66 p = [0]
70 67 for i in a: p.append(p[-1] + len(i))
71 68
72 69 d = difflib.SequenceMatcher(None, a, b).get_matching_blocks()
73 70 d = _normalizeblocks(a, b, d)
74 71 la = 0
75 72 lb = 0
76 73 for am, bm, size in d:
77 74 s = "".join(b[lb:bm])
78 75 if am > la or s:
79 76 bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s)
80 77 la = am + size
81 78 lb = bm + size
82 79
83 80 return "".join(bin)
84 81
85 82 def blocks(a, b):
86 83 an = splitnewlines(a)
87 84 bn = splitnewlines(b)
88 85 d = difflib.SequenceMatcher(None, an, bn).get_matching_blocks()
89 86 d = _normalizeblocks(an, bn, d)
90 87 return [(i, i + n, j, j + n) for (i, j, n) in d]
91 88
92 89 def fixws(text, allws):
93 90 if allws:
94 91 text = re.sub('[ \t\r]+', '', text)
95 92 else:
96 93 text = re.sub('[ \t\r]+', ' ', text)
97 94 text = text.replace(' \n', '\n')
98 95 return text
99 96
100 97 if modulepolicy not in policynocffi:
101 98 try:
102 99 from _bdiff_cffi import ffi, lib
103 100 except ImportError:
104 101 if modulepolicy == 'cffi': # strict cffi import
105 102 raise
106 103 else:
107 104 def blocks(sa, sb):
108 105 a = ffi.new("struct bdiff_line**")
109 106 b = ffi.new("struct bdiff_line**")
110 107 ac = ffi.new("char[]", str(sa))
111 108 bc = ffi.new("char[]", str(sb))
112 109 l = ffi.new("struct bdiff_hunk*")
113 110 try:
114 111 an = lib.bdiff_splitlines(ac, len(sa), a)
115 112 bn = lib.bdiff_splitlines(bc, len(sb), b)
116 113 if not a[0] or not b[0]:
117 114 raise MemoryError
118 115 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
119 116 if count < 0:
120 117 raise MemoryError
121 118 rl = [None] * count
122 119 h = l.next
123 120 i = 0
124 121 while h:
125 122 rl[i] = (h.a1, h.a2, h.b1, h.b2)
126 123 h = h.next
127 124 i += 1
128 125 finally:
129 126 lib.free(a[0])
130 127 lib.free(b[0])
131 128 lib.bdiff_freehunks(l.next)
132 129 return rl
133 130
134 131 def bdiff(sa, sb):
135 132 a = ffi.new("struct bdiff_line**")
136 133 b = ffi.new("struct bdiff_line**")
137 134 ac = ffi.new("char[]", str(sa))
138 135 bc = ffi.new("char[]", str(sb))
139 136 l = ffi.new("struct bdiff_hunk*")
140 137 try:
141 138 an = lib.bdiff_splitlines(ac, len(sa), a)
142 139 bn = lib.bdiff_splitlines(bc, len(sb), b)
143 140 if not a[0] or not b[0]:
144 141 raise MemoryError
145 142 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
146 143 if count < 0:
147 144 raise MemoryError
148 145 rl = []
149 146 h = l.next
150 147 la = lb = 0
151 148 while h:
152 149 if h.a1 != la or h.b1 != lb:
153 150 lgt = (b[0] + h.b1).l - (b[0] + lb).l
154 151 rl.append(struct.pack(">lll", (a[0] + la).l - a[0].l,
155 152 (a[0] + h.a1).l - a[0].l, lgt))
156 153 rl.append(str(ffi.buffer((b[0] + lb).l, lgt)))
157 154 la = h.a2
158 155 lb = h.b2
159 156 h = h.next
160 157
161 158 finally:
162 159 lib.free(a[0])
163 160 lib.free(b[0])
164 161 lib.bdiff_freehunks(l.next)
165 162 return "".join(rl)
General Comments 0
You need to be logged in to leave comments. Login now