changeset 33295:0e8b0b9a7acc

cffi: split modules from pure The copyright lines are updated per change history. cffi/osutil.py isn't tested since I have no access to OS X machine right now, sorry.
author Yuya Nishihara <yuya@tcha.org>
date Tue, 02 May 2017 21:15:31 +0900
parents 2e431fb98c6b
children 25b37900d6e0
files mercurial/cffi/base85.py mercurial/cffi/bdiff.py mercurial/cffi/diffhelpers.py mercurial/cffi/mpatch.py mercurial/cffi/osutil.py mercurial/cffi/parsers.py mercurial/policy.py mercurial/pure/bdiff.py mercurial/pure/mpatch.py mercurial/pure/osutil.py
diffstat 10 files changed, 59 insertions(+), 702 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/mercurial/cffi/base85.py
@@ -0,0 +1,10 @@
+# base85.py: pure python base85 codec
+#
+# Copyright (C) 2009 Brendan Cully <brendan@kublai.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+from ..pure.base85 import *
copy from mercurial/pure/bdiff.py
copy to mercurial/cffi/bdiff.py
--- a/mercurial/pure/bdiff.py
+++ b/mercurial/cffi/bdiff.py
@@ -1,106 +1,22 @@
-# bdiff.py - Python implementation of bdiff.c
+# bdiff.py - CFFI implementation of bdiff.c
 #
-# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
+# Copyright 2016 Maciej Fijalkowski <fijall@gmail.com>
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from __future__ import absolute_import
 
-import difflib
-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')]
-    if lines:
-        if lines[-1] == '\n':
-            lines.pop()
-        else:
-            lines[-1] = lines[-1][:-1]
-    return lines
-
-def _normalizeblocks(a, b, blocks):
-    prev = None
-    r = []
-    for curr in blocks:
-        if prev is None:
-            prev = curr
-            continue
-        shift = 0
-
-        a1, b1, l1 = prev
-        a1end = a1 + l1
-        b1end = b1 + l1
-
-        a2, b2, l2 = curr
-        a2end = a2 + l2
-        b2end = b2 + l2
-        if a1end == a2:
-            while (a1end + shift < a2end and
-                   a[a1end + shift] == b[b1end + shift]):
-                shift += 1
-        elif b1end == b2:
-            while (b1end + shift < b2end and
-                   a[a1end + shift] == b[b1end + shift]):
-                shift += 1
-        r.append((a1, b1, l1 + shift))
-        prev = a2 + shift, b2 + shift, l2 - shift
-    r.append(prev)
-    return r
+from ..pure.bdiff import *
+from . import _bdiff
 
-def bdiff(a, b):
-    a = bytes(a).splitlines(True)
-    b = bytes(b).splitlines(True)
-
-    if not a:
-        s = "".join(b)
-        return s and (struct.pack(">lll", 0, 0, len(s)) + s)
-
-    bin = []
-    p = [0]
-    for i in a: p.append(p[-1] + len(i))
-
-    d = difflib.SequenceMatcher(None, a, b).get_matching_blocks()
-    d = _normalizeblocks(a, b, d)
-    la = 0
-    lb = 0
-    for am, bm, size in d:
-        s = "".join(b[lb:bm])
-        if am > la or s:
-            bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s)
-        la = am + size
-        lb = bm + size
+ffi = _bdiff.ffi
+lib = _bdiff.lib
 
-    return "".join(bin)
-
-def blocks(a, b):
-    an = splitnewlines(a)
-    bn = splitnewlines(b)
-    d = difflib.SequenceMatcher(None, an, bn).get_matching_blocks()
-    d = _normalizeblocks(an, bn, d)
-    return [(i, i + n, j, j + n) for (i, j, n) in d]
-
-def fixws(text, allws):
-    if allws:
-        text = re.sub('[ \t\r]+', '', text)
-    else:
-        text = re.sub('[ \t\r]+', ' ', text)
-        text = text.replace(' \n', '\n')
-    return text
-
-if modulepolicy not in policynocffi:
-    try:
-        from ..cffi._bdiff import ffi, lib
-    except ImportError:
-        if modulepolicy == 'cffi': # strict cffi import
-            raise
-    else:
+if True:
+    if True:
         def blocks(sa, sb):
             a = ffi.new("struct bdiff_line**")
             b = ffi.new("struct bdiff_line**")
new file mode 100644
--- /dev/null
+++ b/mercurial/cffi/diffhelpers.py
@@ -0,0 +1,10 @@
+# diffhelpers.py - pure Python implementation of diffhelpers.c
+#
+# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+from ..pure.diffhelpers import *
copy from mercurial/pure/mpatch.py
copy to mercurial/cffi/mpatch.py
--- a/mercurial/pure/mpatch.py
+++ b/mercurial/cffi/mpatch.py
@@ -1,140 +1,21 @@
-# mpatch.py - Python implementation of mpatch.c
+# mpatch.py - CFFI implementation of mpatch.c
 #
-# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
+# Copyright 2016 Maciej Fijalkowski <fijall@gmail.com>
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from __future__ import absolute_import
 
-import struct
-
-from .. import policy, pycompat
-stringio = pycompat.stringio
-modulepolicy = policy.policy
-policynocffi = policy.policynocffi
-
-class mpatchError(Exception):
-    """error raised when a delta cannot be decoded
-    """
-
-# This attempts to apply a series of patches in time proportional to
-# the total size of the patches, rather than patches * len(text). This
-# means rather than shuffling strings around, we shuffle around
-# pointers to fragments with fragment lists.
-#
-# When the fragment lists get too long, we collapse them. To do this
-# efficiently, we do all our operations inside a buffer created by
-# mmap and simply use memmove. This avoids creating a bunch of large
-# temporary string buffers.
-
-def _pull(dst, src, l): # pull l bytes from src
-    while l:
-        f = src.pop()
-        if f[0] > l: # do we need to split?
-            src.append((f[0] - l, f[1] + l))
-            dst.append((l, f[1]))
-            return
-        dst.append(f)
-        l -= f[0]
-
-def _move(m, dest, src, count):
-    """move count bytes from src to dest
-
-    The file pointer is left at the end of dest.
-    """
-    m.seek(src)
-    buf = m.read(count)
-    m.seek(dest)
-    m.write(buf)
-
-def _collect(m, buf, list):
-    start = buf
-    for l, p in reversed(list):
-        _move(m, buf, p, l)
-        buf += l
-    return (buf - start, start)
-
-def patches(a, bins):
-    if not bins:
-        return a
-
-    plens = [len(x) for x in bins]
-    pl = sum(plens)
-    bl = len(a) + pl
-    tl = bl + bl + pl # enough for the patches and two working texts
-    b1, b2 = 0, bl
-
-    if not tl:
-        return a
-
-    m = stringio()
+from ..pure.mpatch import *
+from ..pure.mpatch import mpatchError  # silence pyflakes
+from . import _mpatch
 
-    # load our original text
-    m.write(a)
-    frags = [(len(a), b1)]
-
-    # copy all the patches into our segment so we can memmove from them
-    pos = b2 + bl
-    m.seek(pos)
-    for p in bins: m.write(p)
-
-    for plen in plens:
-        # if our list gets too long, execute it
-        if len(frags) > 128:
-            b2, b1 = b1, b2
-            frags = [_collect(m, b1, frags)]
-
-        new = []
-        end = pos + plen
-        last = 0
-        while pos < end:
-            m.seek(pos)
-            try:
-                p1, p2, l = struct.unpack(">lll", m.read(12))
-            except struct.error:
-                raise mpatchError("patch cannot be decoded")
-            _pull(new, frags, p1 - last) # what didn't change
-            _pull([], frags, p2 - p1)    # what got deleted
-            new.append((l, pos + 12))   # what got added
-            pos += l + 12
-            last = p2
-        frags.extend(reversed(new))     # what was left at the end
-
-    t = _collect(m, b2, frags)
+ffi = _mpatch.ffi
+lib = _mpatch.lib
 
-    m.seek(t[1])
-    return m.read(t[0])
-
-def patchedsize(orig, delta):
-    outlen, last, bin = 0, 0, 0
-    binend = len(delta)
-    data = 12
-
-    while data <= binend:
-        decode = delta[bin:bin + 12]
-        start, end, length = struct.unpack(">lll", decode)
-        if start > end:
-            break
-        bin = data + length
-        data = bin + 12
-        outlen += start - last
-        last = end
-        outlen += length
-
-    if bin != binend:
-        raise mpatchError("patch cannot be decoded")
-
-    outlen += orig - last
-    return outlen
-
-if modulepolicy not in policynocffi:
-    try:
-        from ..cffi._mpatch import ffi, lib
-    except ImportError:
-        if modulepolicy == 'cffi': # strict cffi import
-            raise
-    else:
+if True:
+    if True:
         @ffi.def_extern()
         def cffi_get_next_item(arg, pos):
             all, bins = ffi.from_handle(arg)
copy from mercurial/pure/osutil.py
copy to mercurial/cffi/osutil.py
--- a/mercurial/pure/osutil.py
+++ b/mercurial/cffi/osutil.py
@@ -1,82 +1,27 @@
-# osutil.py - pure Python version of osutil.c
+# osutil.py - CFFI version of osutil.c
 #
-#  Copyright 2009 Matt Mackall <mpm@selenic.com> and others
+# Copyright 2016 Maciej Fijalkowski <fijall@gmail.com>
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from __future__ import absolute_import
 
-import ctypes
-import ctypes.util
 import os
-import socket
 import stat as statmod
 
+from ..pure.osutil import *
+
 from .. import (
-    policy,
     pycompat,
 )
 
-modulepolicy = policy.policy
-policynocffi = policy.policynocffi
-
-def _mode_to_kind(mode):
-    if statmod.S_ISREG(mode):
-        return statmod.S_IFREG
-    if statmod.S_ISDIR(mode):
-        return statmod.S_IFDIR
-    if statmod.S_ISLNK(mode):
-        return statmod.S_IFLNK
-    if statmod.S_ISBLK(mode):
-        return statmod.S_IFBLK
-    if statmod.S_ISCHR(mode):
-        return statmod.S_IFCHR
-    if statmod.S_ISFIFO(mode):
-        return statmod.S_IFIFO
-    if statmod.S_ISSOCK(mode):
-        return statmod.S_IFSOCK
-    return mode
-
-def listdirpure(path, stat=False, skip=None):
-    '''listdir(path, stat=False) -> list_of_tuples
-
-    Return a sorted list containing information about the entries
-    in the directory.
-
-    If stat is True, each element is a 3-tuple:
-
-      (name, type, stat object)
+if pycompat.sysplatform == 'darwin':
+    from . import _osutil
 
-    Otherwise, each element is a 2-tuple:
+    ffi = _osutil.ffi
+    lib = _osutil.lib
 
-      (name, type)
-    '''
-    result = []
-    prefix = path
-    if not prefix.endswith(pycompat.ossep):
-        prefix += pycompat.ossep
-    names = os.listdir(path)
-    names.sort()
-    for fn in names:
-        st = os.lstat(prefix + fn)
-        if fn == skip and statmod.S_ISDIR(st.st_mode):
-            return []
-        if stat:
-            result.append((fn, _mode_to_kind(st.st_mode), st))
-        else:
-            result.append((fn, _mode_to_kind(st.st_mode)))
-    return result
-
-ffi = None
-if modulepolicy not in policynocffi and pycompat.sysplatform == 'darwin':
-    try:
-        from ..cffi._osutil import ffi, lib
-    except ImportError:
-        if modulepolicy == 'cffi': # strict cffi import
-            raise
-
-if pycompat.sysplatform == 'darwin' and ffi is not None:
     listdir_batch_size = 4096
     # tweakable number, only affects performance, which chunks
     # of bytes do we get back from getattrlistbulk
@@ -155,211 +100,3 @@
                 pass # we ignore all the errors from closing, not
                 # much we can do about that
         return ret
-else:
-    listdir = listdirpure
-
-if pycompat.osname != 'nt':
-    posixfile = open
-
-    _SCM_RIGHTS = 0x01
-    _socklen_t = ctypes.c_uint
-
-    if pycompat.sysplatform.startswith('linux'):
-        # socket.h says "the type should be socklen_t but the definition of
-        # the kernel is incompatible with this."
-        _cmsg_len_t = ctypes.c_size_t
-        _msg_controllen_t = ctypes.c_size_t
-        _msg_iovlen_t = ctypes.c_size_t
-    else:
-        _cmsg_len_t = _socklen_t
-        _msg_controllen_t = _socklen_t
-        _msg_iovlen_t = ctypes.c_int
-
-    class _iovec(ctypes.Structure):
-        _fields_ = [
-            (u'iov_base', ctypes.c_void_p),
-            (u'iov_len', ctypes.c_size_t),
-        ]
-
-    class _msghdr(ctypes.Structure):
-        _fields_ = [
-            (u'msg_name', ctypes.c_void_p),
-            (u'msg_namelen', _socklen_t),
-            (u'msg_iov', ctypes.POINTER(_iovec)),
-            (u'msg_iovlen', _msg_iovlen_t),
-            (u'msg_control', ctypes.c_void_p),
-            (u'msg_controllen', _msg_controllen_t),
-            (u'msg_flags', ctypes.c_int),
-        ]
-
-    class _cmsghdr(ctypes.Structure):
-        _fields_ = [
-            (u'cmsg_len', _cmsg_len_t),
-            (u'cmsg_level', ctypes.c_int),
-            (u'cmsg_type', ctypes.c_int),
-            (u'cmsg_data', ctypes.c_ubyte * 0),
-        ]
-
-    _libc = ctypes.CDLL(ctypes.util.find_library(u'c'), use_errno=True)
-    _recvmsg = getattr(_libc, 'recvmsg', None)
-    if _recvmsg:
-        _recvmsg.restype = getattr(ctypes, 'c_ssize_t', ctypes.c_long)
-        _recvmsg.argtypes = (ctypes.c_int, ctypes.POINTER(_msghdr),
-                             ctypes.c_int)
-    else:
-        # recvmsg isn't always provided by libc; such systems are unsupported
-        def _recvmsg(sockfd, msg, flags):
-            raise NotImplementedError('unsupported platform')
-
-    def _CMSG_FIRSTHDR(msgh):
-        if msgh.msg_controllen < ctypes.sizeof(_cmsghdr):
-            return
-        cmsgptr = ctypes.cast(msgh.msg_control, ctypes.POINTER(_cmsghdr))
-        return cmsgptr.contents
-
-    # The pure version is less portable than the native version because the
-    # handling of socket ancillary data heavily depends on C preprocessor.
-    # Also, some length fields are wrongly typed in Linux kernel.
-    def recvfds(sockfd):
-        """receive list of file descriptors via socket"""
-        dummy = (ctypes.c_ubyte * 1)()
-        iov = _iovec(ctypes.cast(dummy, ctypes.c_void_p), ctypes.sizeof(dummy))
-        cbuf = ctypes.create_string_buffer(256)
-        msgh = _msghdr(None, 0,
-                       ctypes.pointer(iov), 1,
-                       ctypes.cast(cbuf, ctypes.c_void_p), ctypes.sizeof(cbuf),
-                       0)
-        r = _recvmsg(sockfd, ctypes.byref(msgh), 0)
-        if r < 0:
-            e = ctypes.get_errno()
-            raise OSError(e, os.strerror(e))
-        # assumes that the first cmsg has fds because it isn't easy to write
-        # portable CMSG_NXTHDR() with ctypes.
-        cmsg = _CMSG_FIRSTHDR(msgh)
-        if not cmsg:
-            return []
-        if (cmsg.cmsg_level != socket.SOL_SOCKET or
-            cmsg.cmsg_type != _SCM_RIGHTS):
-            return []
-        rfds = ctypes.cast(cmsg.cmsg_data, ctypes.POINTER(ctypes.c_int))
-        rfdscount = ((cmsg.cmsg_len - _cmsghdr.cmsg_data.offset) /
-                     ctypes.sizeof(ctypes.c_int))
-        return [rfds[i] for i in xrange(rfdscount)]
-
-else:
-    import msvcrt
-
-    _kernel32 = ctypes.windll.kernel32
-
-    _DWORD = ctypes.c_ulong
-    _LPCSTR = _LPSTR = ctypes.c_char_p
-    _HANDLE = ctypes.c_void_p
-
-    _INVALID_HANDLE_VALUE = _HANDLE(-1).value
-
-    # CreateFile
-    _FILE_SHARE_READ = 0x00000001
-    _FILE_SHARE_WRITE = 0x00000002
-    _FILE_SHARE_DELETE = 0x00000004
-
-    _CREATE_ALWAYS = 2
-    _OPEN_EXISTING = 3
-    _OPEN_ALWAYS = 4
-
-    _GENERIC_READ = 0x80000000
-    _GENERIC_WRITE = 0x40000000
-
-    _FILE_ATTRIBUTE_NORMAL = 0x80
-
-    # open_osfhandle flags
-    _O_RDONLY = 0x0000
-    _O_RDWR = 0x0002
-    _O_APPEND = 0x0008
-
-    _O_TEXT = 0x4000
-    _O_BINARY = 0x8000
-
-    # types of parameters of C functions used (required by pypy)
-
-    _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
-        _DWORD, _DWORD, _HANDLE]
-    _kernel32.CreateFileA.restype = _HANDLE
-
-    def _raiseioerror(name):
-        err = ctypes.WinError()
-        raise IOError(err.errno, '%s: %s' % (name, err.strerror))
-
-    class posixfile(object):
-        '''a file object aiming for POSIX-like semantics
-
-        CPython's open() returns a file that was opened *without* setting the
-        _FILE_SHARE_DELETE flag, which causes rename and unlink to abort.
-        This even happens if any hardlinked copy of the file is in open state.
-        We set _FILE_SHARE_DELETE here, so files opened with posixfile can be
-        renamed and deleted while they are held open.
-        Note that if a file opened with posixfile is unlinked, the file
-        remains but cannot be opened again or be recreated under the same name,
-        until all reading processes have closed the file.'''
-
-        def __init__(self, name, mode='r', bufsize=-1):
-            if 'b' in mode:
-                flags = _O_BINARY
-            else:
-                flags = _O_TEXT
-
-            m0 = mode[0]
-            if m0 == 'r' and '+' not in mode:
-                flags |= _O_RDONLY
-                access = _GENERIC_READ
-            else:
-                # work around http://support.microsoft.com/kb/899149 and
-                # set _O_RDWR for 'w' and 'a', even if mode has no '+'
-                flags |= _O_RDWR
-                access = _GENERIC_READ | _GENERIC_WRITE
-
-            if m0 == 'r':
-                creation = _OPEN_EXISTING
-            elif m0 == 'w':
-                creation = _CREATE_ALWAYS
-            elif m0 == 'a':
-                creation = _OPEN_ALWAYS
-                flags |= _O_APPEND
-            else:
-                raise ValueError("invalid mode: %s" % mode)
-
-            fh = _kernel32.CreateFileA(name, access,
-                    _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
-                    None, creation, _FILE_ATTRIBUTE_NORMAL, None)
-            if fh == _INVALID_HANDLE_VALUE:
-                _raiseioerror(name)
-
-            fd = msvcrt.open_osfhandle(fh, flags)
-            if fd == -1:
-                _kernel32.CloseHandle(fh)
-                _raiseioerror(name)
-
-            f = os.fdopen(fd, pycompat.sysstr(mode), bufsize)
-            # unfortunately, f.name is '<fdopen>' at this point -- so we store
-            # the name on this wrapper. We cannot just assign to f.name,
-            # because that attribute is read-only.
-            object.__setattr__(self, r'name', name)
-            object.__setattr__(self, r'_file', f)
-
-        def __iter__(self):
-            return self._file
-
-        def __getattr__(self, name):
-            return getattr(self._file, name)
-
-        def __setattr__(self, name, value):
-            '''mimics the read-only attributes of Python file objects
-            by raising 'TypeError: readonly attribute' if someone tries:
-              f = posixfile('foo.txt')
-              f.name = 'bla'  '''
-            return self._file.__setattr__(name, value)
-
-        def __enter__(self):
-            return self._file.__enter__()
-
-        def __exit__(self, exc_type, exc_value, exc_tb):
-            return self._file.__exit__(exc_type, exc_value, exc_tb)
new file mode 100644
--- /dev/null
+++ b/mercurial/cffi/parsers.py
@@ -0,0 +1,10 @@
+# parsers.py - Python implementation of parsers.c
+#
+# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+from ..pure.parsers import *
--- a/mercurial/policy.py
+++ b/mercurial/policy.py
@@ -28,8 +28,8 @@
     # policy: (versioned package, pure package)
     b'c': (r'cext', None),
     b'allow': (r'cext', r'pure'),
-    b'cffi': (None, r'pure'),  # TODO: (r'cffi', None)
-    b'cffi-allow': (None, r'pure'),  # TODO: (r'cffi', r'pure')
+    b'cffi': (r'cffi', None),
+    b'cffi-allow': (r'cffi', r'pure'),
     b'py': (None, r'pure'),
 }
 
--- a/mercurial/pure/bdiff.py
+++ b/mercurial/pure/bdiff.py
@@ -11,10 +11,6 @@
 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')]
@@ -93,70 +89,3 @@
         text = re.sub('[ \t\r]+', ' ', text)
         text = text.replace(' \n', '\n')
     return text
-
-if modulepolicy not in policynocffi:
-    try:
-        from ..cffi._bdiff 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[]", str(sa))
-            bc = ffi.new("char[]", str(sb))
-            l = ffi.new("struct bdiff_hunk*")
-            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
-                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
-
-        def bdiff(sa, sb):
-            a = ffi.new("struct bdiff_line**")
-            b = ffi.new("struct bdiff_line**")
-            ac = ffi.new("char[]", str(sa))
-            bc = ffi.new("char[]", str(sb))
-            l = ffi.new("struct bdiff_hunk*")
-            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
-                count = lib.bdiff_diff(a[0], an, b[0], bn, l)
-                if count < 0:
-                    raise MemoryError
-                rl = []
-                h = l.next
-                la = lb = 0
-                while h:
-                    if h.a1 != la or h.b1 != lb:
-                        lgt = (b[0] + h.b1).l - (b[0] + lb).l
-                        rl.append(struct.pack(">lll", (a[0] + la).l - a[0].l,
-                            (a[0] + h.a1).l - a[0].l, lgt))
-                        rl.append(str(ffi.buffer((b[0] + lb).l, lgt)))
-                    la = h.a2
-                    lb = h.b2
-                    h = h.next
-
-            finally:
-                lib.free(a[0])
-                lib.free(b[0])
-                lib.bdiff_freehunks(l.next)
-            return "".join(rl)
--- a/mercurial/pure/mpatch.py
+++ b/mercurial/pure/mpatch.py
@@ -9,10 +9,8 @@
 
 import struct
 
-from .. import policy, pycompat
+from .. import pycompat
 stringio = pycompat.stringio
-modulepolicy = policy.policy
-policynocffi = policy.policynocffi
 
 class mpatchError(Exception):
     """error raised when a delta cannot be decoded
@@ -127,43 +125,3 @@
 
     outlen += orig - last
     return outlen
-
-if modulepolicy not in policynocffi:
-    try:
-        from ..cffi._mpatch import ffi, lib
-    except ImportError:
-        if modulepolicy == 'cffi': # strict cffi import
-            raise
-    else:
-        @ffi.def_extern()
-        def cffi_get_next_item(arg, pos):
-            all, bins = ffi.from_handle(arg)
-            container = ffi.new("struct mpatch_flist*[1]")
-            to_pass = ffi.new("char[]", str(bins[pos]))
-            all.append(to_pass)
-            r = lib.mpatch_decode(to_pass, len(to_pass) - 1, container)
-            if r < 0:
-                return ffi.NULL
-            return container[0]
-
-        def patches(text, bins):
-            lgt = len(bins)
-            all = []
-            if not lgt:
-                return text
-            arg = (all, bins)
-            patch = lib.mpatch_fold(ffi.new_handle(arg),
-                                    lib.cffi_get_next_item, 0, lgt)
-            if not patch:
-                raise mpatchError("cannot decode chunk")
-            outlen = lib.mpatch_calcsize(len(text), patch)
-            if outlen < 0:
-                lib.mpatch_lfree(patch)
-                raise mpatchError("inconsistency detected")
-            buf = ffi.new("char[]", outlen)
-            if lib.mpatch_apply(buf, text, len(text), patch) < 0:
-                lib.mpatch_lfree(patch)
-                raise mpatchError("error applying patches")
-            res = ffi.buffer(buf, outlen)[:]
-            lib.mpatch_lfree(patch)
-            return res
--- a/mercurial/pure/osutil.py
+++ b/mercurial/pure/osutil.py
@@ -14,13 +14,9 @@
 import stat as statmod
 
 from .. import (
-    policy,
     pycompat,
 )
 
-modulepolicy = policy.policy
-policynocffi = policy.policynocffi
-
 def _mode_to_kind(mode):
     if statmod.S_ISREG(mode):
         return statmod.S_IFREG
@@ -38,7 +34,7 @@
         return statmod.S_IFSOCK
     return mode
 
-def listdirpure(path, stat=False, skip=None):
+def listdir(path, stat=False, skip=None):
     '''listdir(path, stat=False) -> list_of_tuples
 
     Return a sorted list containing information about the entries
@@ -68,96 +64,6 @@
             result.append((fn, _mode_to_kind(st.st_mode)))
     return result
 
-ffi = None
-if modulepolicy not in policynocffi and pycompat.sysplatform == 'darwin':
-    try:
-        from ..cffi._osutil import ffi, lib
-    except ImportError:
-        if modulepolicy == 'cffi': # strict cffi import
-            raise
-
-if pycompat.sysplatform == 'darwin' and ffi is not None:
-    listdir_batch_size = 4096
-    # tweakable number, only affects performance, which chunks
-    # of bytes do we get back from getattrlistbulk
-
-    attrkinds = [None] * 20 # we need the max no for enum VXXX, 20 is plenty
-
-    attrkinds[lib.VREG] = statmod.S_IFREG
-    attrkinds[lib.VDIR] = statmod.S_IFDIR
-    attrkinds[lib.VLNK] = statmod.S_IFLNK
-    attrkinds[lib.VBLK] = statmod.S_IFBLK
-    attrkinds[lib.VCHR] = statmod.S_IFCHR
-    attrkinds[lib.VFIFO] = statmod.S_IFIFO
-    attrkinds[lib.VSOCK] = statmod.S_IFSOCK
-
-    class stat_res(object):
-        def __init__(self, st_mode, st_mtime, st_size):
-            self.st_mode = st_mode
-            self.st_mtime = st_mtime
-            self.st_size = st_size
-
-    tv_sec_ofs = ffi.offsetof("struct timespec", "tv_sec")
-    buf = ffi.new("char[]", listdir_batch_size)
-
-    def listdirinternal(dfd, req, stat, skip):
-        ret = []
-        while True:
-            r = lib.getattrlistbulk(dfd, req, buf, listdir_batch_size, 0)
-            if r == 0:
-                break
-            if r == -1:
-                raise OSError(ffi.errno, os.strerror(ffi.errno))
-            cur = ffi.cast("val_attrs_t*", buf)
-            for i in range(r):
-                lgt = cur.length
-                assert lgt == ffi.cast('uint32_t*', cur)[0]
-                ofs = cur.name_info.attr_dataoffset
-                str_lgt = cur.name_info.attr_length
-                base_ofs = ffi.offsetof('val_attrs_t', 'name_info')
-                name = str(ffi.buffer(ffi.cast("char*", cur) + base_ofs + ofs,
-                           str_lgt - 1))
-                tp = attrkinds[cur.obj_type]
-                if name == "." or name == "..":
-                    continue
-                if skip == name and tp == statmod.S_ISDIR:
-                    return []
-                if stat:
-                    mtime = cur.mtime.tv_sec
-                    mode = (cur.accessmask & ~lib.S_IFMT)| tp
-                    ret.append((name, tp, stat_res(st_mode=mode, st_mtime=mtime,
-                                st_size=cur.datalength)))
-                else:
-                    ret.append((name, tp))
-                cur = ffi.cast("val_attrs_t*", int(ffi.cast("intptr_t", cur))
-                    + lgt)
-        return ret
-
-    def listdir(path, stat=False, skip=None):
-        req = ffi.new("struct attrlist*")
-        req.bitmapcount = lib.ATTR_BIT_MAP_COUNT
-        req.commonattr = (lib.ATTR_CMN_RETURNED_ATTRS |
-                          lib.ATTR_CMN_NAME |
-                          lib.ATTR_CMN_OBJTYPE |
-                          lib.ATTR_CMN_ACCESSMASK |
-                          lib.ATTR_CMN_MODTIME)
-        req.fileattr = lib.ATTR_FILE_DATALENGTH
-        dfd = lib.open(path, lib.O_RDONLY, 0)
-        if dfd == -1:
-            raise OSError(ffi.errno, os.strerror(ffi.errno))
-
-        try:
-            ret = listdirinternal(dfd, req, stat, skip)
-        finally:
-            try:
-                lib.close(dfd)
-            except BaseException:
-                pass # we ignore all the errors from closing, not
-                # much we can do about that
-        return ret
-else:
-    listdir = listdirpure
-
 if pycompat.osname != 'nt':
     posixfile = open