mercurial/pure/mpatch.py
author Yuya Nishihara <yuya@tcha.org>
Sat, 13 Aug 2016 12:18:58 +0900
changeset 32371 151cc3b3d799
parent 29695 f2846d546645
child 32506 2dcb3d52ef41
permissions -rw-r--r--
mpatch: switch to policy importer
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
32371
151cc3b3d799 mpatch: switch to policy importer
Yuya Nishihara <yuya@tcha.org>
parents: 29695
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