--- a/mercurial/pure/bdiff.py Fri Aug 19 13:30:40 2016 -0700
+++ b/mercurial/pure/bdiff.py Thu Jul 28 14:17:08 2016 +0200
@@ -12,6 +12,10 @@
import re
import struct
+from . import policy
+policynocffi = policy.policynocffi
+modulepolicy = policy.policy
+
def splitnewlines(text):
'''like str.splitlines, but only split on newlines.'''
lines = [l + '\n' for l in text.split('\n')]
@@ -96,3 +100,37 @@
text = re.sub('[ \t\r]+', ' ', text)
text = text.replace(' \n', '\n')
return text
+
+if modulepolicy not in policynocffi:
+ try:
+ from _bdiff_cffi import ffi, lib
+ except ImportError:
+ if modulepolicy == 'cffi': # strict cffi import
+ raise
+ else:
+ def blocks(sa, sb):
+ a = ffi.new("struct bdiff_line**")
+ b = ffi.new("struct bdiff_line**")
+ ac = ffi.new("char[]", sa)
+ bc = ffi.new("char[]", sb)
+ try:
+ an = lib.bdiff_splitlines(ac, len(sa), a)
+ bn = lib.bdiff_splitlines(bc, len(sb), b)
+ if not a[0] or not b[0]:
+ raise MemoryError
+ l = ffi.new("struct bdiff_hunk*")
+ count = lib.bdiff_diff(a[0], an, b[0], bn, l)
+ if count < 0:
+ raise MemoryError
+ rl = [None] * count
+ h = l.next
+ i = 0
+ while h:
+ rl[i] = (h.a1, h.a2, h.b1, h.b2)
+ h = h.next
+ i += 1
+ finally:
+ lib.free(a[0])
+ lib.free(b[0])
+ lib.bdiff_freehunks(l.next)
+ return rl
--- a/setup.py Fri Aug 19 13:30:40 2016 -0700
+++ b/setup.py Thu Jul 28 14:17:08 2016 +0200
@@ -319,7 +319,9 @@
self.distribution.ext_modules = []
elif self.distribution.cffi:
import setup_mpatch_cffi
- exts = [setup_mpatch_cffi.ffi.distutils_extension()]
+ import setup_bdiff_cffi
+ exts = [setup_mpatch_cffi.ffi.distutils_extension(),
+ setup_bdiff_cffi.ffi.distutils_extension()]
# cffi modules go here
if sys.platform == 'darwin':
import setup_osutil_cffi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/setup_bdiff_cffi.py Thu Jul 28 14:17:08 2016 +0200
@@ -0,0 +1,31 @@
+from __future__ import absolute_import
+
+import cffi
+import os
+
+ffi = cffi.FFI()
+ffi.set_source("_bdiff_cffi",
+ open(os.path.join(os.path.join(os.path.dirname(__file__), 'mercurial'),
+ 'bdiff.c')).read(), include_dirs=['mercurial'])
+ffi.cdef("""
+struct bdiff_line {
+ int hash, n, e;
+ ssize_t len;
+ const char *l;
+};
+
+struct bdiff_hunk;
+struct bdiff_hunk {
+ int a1, a2, b1, b2;
+ struct bdiff_hunk *next;
+};
+
+int bdiff_splitlines(const char *a, ssize_t len, struct bdiff_line **lr);
+int bdiff_diff(struct bdiff_line *a, int an, struct bdiff_line *b, int bn,
+ struct bdiff_hunk *base);
+void bdiff_freehunks(struct bdiff_hunk *l);
+void free(void*);
+""")
+
+if __name__ == '__main__':
+ ffi.compile()