mercurial/pure/mpatch.py
author Gábor Stefanik <gabor.stefanik@nng.com>
Thu, 13 Oct 2016 02:19:43 +0200
changeset 30197 0accd5a5ad04
parent 29695 f2846d546645
child 32371 151cc3b3d799
permissions -rw-r--r--
mergecopies: invoke _computenonoverlap for both base and tca during merges The algorithm of _checkcopies can only walk backwards in the DAG, never forward. Because of this, the two _checkcopies patches need to run from their respective endpoints to the TCA to cover the entire subgraph where the merge is being performed. However, detection of files new in both endpoints, as well as directory rename detection, need to run with respect to the merge base, so we need lists of new files both from the TCA's and the merge base's viewpoint to correctly detect renames in a graft-like merge scenario. (Series reworked by Pierre-Yves David)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     1
# mpatch.py - Python implementation of mpatch.c
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     2
#
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     3
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7775
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
     6
# GNU General Public License version 2 or any later version.
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     7
27337
9a17576103a4 mpatch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 16683
diff changeset
     8
from __future__ import absolute_import
9a17576103a4 mpatch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 16683
diff changeset
     9
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
    10
import struct
27337
9a17576103a4 mpatch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 16683
diff changeset
    11
29695
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
    12
from . import policy, pycompat
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28782
diff changeset
    13
stringio = pycompat.stringio
29695
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
    14
modulepolicy = policy.policy
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
    15
policynocffi = policy.policynocffi
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    16
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    17
class mpatchError(Exception):
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    18
    """error raised when a delta cannot be decoded
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    19
    """
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    20
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    21
# This attempts to apply a series of patches in time proportional to
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    22
# the total size of the patches, rather than patches * len(text). This
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    23
# means rather than shuffling strings around, we shuffle around
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    24
# pointers to fragments with fragment lists.
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    25
#
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    26
# When the fragment lists get too long, we collapse them. To do this
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    27
# efficiently, we do all our operations inside a buffer created by
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    28
# mmap and simply use memmove. This avoids creating a bunch of large
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    29
# temporary string buffers.
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    30
28587
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    31
def _pull(dst, src, l): # pull l bytes from src
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    32
    while l:
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    33
        f = src.pop()
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    34
        if f[0] > l: # do we need to split?
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    35
            src.append((f[0] - l, f[1] + l))
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    36
            dst.append((l, f[1]))
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    37
            return
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    38
        dst.append(f)
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    39
        l -= f[0]
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    40
28588
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    41
def _move(m, dest, src, count):
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    42
    """move count bytes from src to dest
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    43
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    44
    The file pointer is left at the end of dest.
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    45
    """
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    46
    m.seek(src)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    47
    buf = m.read(count)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    48
    m.seek(dest)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    49
    m.write(buf)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
    50
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    51
def _collect(m, buf, list):
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    52
    start = buf
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    53
    for l, p in reversed(list):
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    54
        _move(m, buf, p, l)
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    55
        buf += l
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    56
    return (buf - start, start)
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    57
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    58
def patches(a, bins):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    59
    if not bins:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    60
        return a
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    61
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    62
    plens = [len(x) for x in bins]
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    63
    pl = sum(plens)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    64
    bl = len(a) + pl
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    65
    tl = bl + bl + pl # enough for the patches and two working texts
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    66
    b1, b2 = 0, bl
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    67
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    68
    if not tl:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    69
        return a
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    70
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28782
diff changeset
    71
    m = stringio()
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    72
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    73
    # load our original text
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    74
    m.write(a)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    75
    frags = [(len(a), b1)]
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    76
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    77
    # copy all the patches into our segment so we can memmove from them
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    78
    pos = b2 + bl
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    79
    m.seek(pos)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    80
    for p in bins: m.write(p)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    81
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    82
    for plen in plens:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    83
        # if our list gets too long, execute it
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    84
        if len(frags) > 128:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    85
            b2, b1 = b1, b2
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
    86
            frags = [_collect(m, b1, frags)]
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    87
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    88
        new = []
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    89
        end = pos + plen
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    90
        last = 0
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    91
        while pos < end:
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
    92
            m.seek(pos)
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    93
            try:
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    94
                p1, p2, l = struct.unpack(">lll", m.read(12))
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    95
            except struct.error:
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
    96
                raise mpatchError("patch cannot be decoded")
28587
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    97
            _pull(new, frags, p1 - last) # what didn't change
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
    98
            _pull([], frags, p2 - p1)    # what got deleted
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 14065
diff changeset
    99
            new.append((l, pos + 12))   # what got added
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   100
            pos += l + 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   101
            last = p2
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 14065
diff changeset
   102
        frags.extend(reversed(new))     # what was left at the end
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   103
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
   104
    t = _collect(m, b2, frags)
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   105
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
   106
    m.seek(t[1])
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
   107
    return m.read(t[0])
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   108
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   109
def patchedsize(orig, delta):
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   110
    outlen, last, bin = 0, 0, 0
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   111
    binend = len(delta)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   112
    data = 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   113
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   114
    while data <= binend:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   115
        decode = delta[bin:bin + 12]
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   116
        start, end, length = struct.unpack(">lll", decode)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   117
        if start > end:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   118
            break
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   119
        bin = data + length
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   120
        data = bin + 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   121
        outlen += start - last
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   122
        last = end
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   123
        outlen += length
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   124
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   125
    if bin != binend:
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
   126
        raise mpatchError("patch cannot be decoded")
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   127
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   128
    outlen += orig - last
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
   129
    return outlen
29695
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   130
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   131
if modulepolicy not in policynocffi:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   132
    try:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   133
        from _mpatch_cffi import ffi, lib
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   134
    except ImportError:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   135
        if modulepolicy == 'cffi': # strict cffi import
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   136
            raise
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   137
    else:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   138
        @ffi.def_extern()
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   139
        def cffi_get_next_item(arg, pos):
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   140
            all, bins = ffi.from_handle(arg)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   141
            container = ffi.new("struct mpatch_flist*[1]")
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   142
            to_pass = ffi.new("char[]", str(bins[pos]))
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   143
            all.append(to_pass)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   144
            r = lib.mpatch_decode(to_pass, len(to_pass) - 1, container)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   145
            if r < 0:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   146
                return ffi.NULL
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   147
            return container[0]
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   148
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   149
        def patches(text, bins):
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   150
            lgt = len(bins)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   151
            all = []
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   152
            if not lgt:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   153
                return text
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   154
            arg = (all, bins)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   155
            patch = lib.mpatch_fold(ffi.new_handle(arg),
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   156
                                    lib.cffi_get_next_item, 0, lgt)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   157
            if not patch:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   158
                raise mpatchError("cannot decode chunk")
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   159
            outlen = lib.mpatch_calcsize(len(text), patch)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   160
            if outlen < 0:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   161
                lib.mpatch_lfree(patch)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   162
                raise mpatchError("inconsistency detected")
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   163
            buf = ffi.new("char[]", outlen)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   164
            if lib.mpatch_apply(buf, text, len(text), patch) < 0:
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   165
                lib.mpatch_lfree(patch)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   166
                raise mpatchError("error applying patches")
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   167
            res = ffi.buffer(buf, outlen)[:]
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   168
            lib.mpatch_lfree(patch)
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   169
            return res
f2846d546645 mpatch: write a cffi version of mpatch.patches
Maciej Fijalkowski <fijall@gmail.com>
parents: 28861
diff changeset
   170