view mercurial/cffi/mpatch.py @ 40976:ef7119cd4965

py3: enable legacy stdio mode in exewrapper This drops the test failure count from 166 to 117. The failures were typically in the form of `hg serve -d` spawning but crashing immediately, leaving clients with "bad http status" lines, connection refusals, and so forth. The underlying message on the server side was either "OSError: [WinError 6] The handle is invalid" or "OSError: [WinError 1] Incorrect function". Additionally, no output was rendered if the pager was activated. Thanks to Yuya for diagnosing the problem. The failure count drops to 107 when PYTHONLEGACYWINDOWSSTDIO=1 is defined in the environment. These failures seem to revolve around the dummyssh server process, and dumbhttp.py. So I'll probably add that to the test runner. One small regression here (only in py3) is that if hg.exe is already built, a messagebox appears when building it again saying that python37.dll can't be loaded. Python3 isn't in PATH by default, and setup.py tries running bare `hg` first. But MSYS prepends '.' to PATH, so it runs the local hg, but can't find the library. It falls back to the python used to invoke setup.py, so ultimately it works. I'm not sure if it's better to strip '.' from PATH or just skip right to `sys.executable hg` on Windows. Also, something seems to be wrong with run-tests._usecorrectpython(). I accidentially left off the 'PYTHON="py -3"' when building (thus making py2 stuff), and yet managed to invoke run-tests.py with "py -3". (And that only had 67 failures.)
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 16 Dec 2018 17:42:45 -0500
parents 857876ebaed4
children 2372284d9457
line wrap: on
line source

# mpatch.py - CFFI implementation of mpatch.c
#
# 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

from ..pure.mpatch import *
from ..pure.mpatch import mpatchError  # silence pyflakes
from . import _mpatch

ffi = _mpatch.ffi
lib = _mpatch.lib

@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