Mercurial > hg
annotate mercurial/pure/mpatch.py @ 35986:98a00aa0288d
wireprotoserver: move error response handling out of hgweb
The exception handler for ErrorResponse has more to do with the
wire protocol than the generic HTTP server. Move the code so it
lives alongside other wire protocol code.
Differential Revision: https://phab.mercurial-scm.org/D2021
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 31 Jan 2018 17:34:45 -0800 |
parents | 5326e4ef1dab |
children | 644a02f6b34f |
rev | line source |
---|---|
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 | 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 |
32512
0e8b0b9a7acc
cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents:
32506
diff
changeset
|
12 from .. import pycompat |
28861
86db5cb55d46
pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents:
28782
diff
changeset
|
13 stringio = pycompat.stringio |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
14 |
28782
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
15 class mpatchError(Exception): |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
16 """error raised when a delta cannot be decoded |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
17 """ |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
18 |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
19 # 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
|
20 # 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
|
21 # 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
|
22 # pointers to fragments with fragment lists. |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
23 # |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
24 # 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
|
25 # 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
|
26 # 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
|
27 # temporary string buffers. |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
28 |
28587
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
29 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
|
30 while l: |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
31 f = src.pop() |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
32 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
|
33 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
|
34 dst.append((l, f[1])) |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
35 return |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
36 dst.append(f) |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
37 l -= f[0] |
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
38 |
28588
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
39 def _move(m, dest, src, count): |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
40 """move count bytes from src to dest |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
41 |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
42 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
|
43 """ |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
44 m.seek(src) |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
45 buf = m.read(count) |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
46 m.seek(dest) |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
47 m.write(buf) |
6546afde350e
mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents:
28587
diff
changeset
|
48 |
28589
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
49 def _collect(m, buf, list): |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
50 start = buf |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
51 for l, p in reversed(list): |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
52 _move(m, buf, p, l) |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
53 buf += l |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
54 return (buf - start, start) |
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
55 |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
56 def patches(a, bins): |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
57 if not bins: |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
58 return a |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
59 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
60 plens = [len(x) for x in bins] |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
61 pl = sum(plens) |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
62 bl = len(a) + pl |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
63 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
|
64 b1, b2 = 0, bl |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
65 |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
66 if not tl: |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
67 return a |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
68 |
28861
86db5cb55d46
pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents:
28782
diff
changeset
|
69 m = stringio() |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
70 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
71 # load our original text |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
72 m.write(a) |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
73 frags = [(len(a), b1)] |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
74 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
75 # 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
|
76 pos = b2 + bl |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
77 m.seek(pos) |
34435
5326e4ef1dab
style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents:
32512
diff
changeset
|
78 for p in bins: |
5326e4ef1dab
style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents:
32512
diff
changeset
|
79 m.write(p) |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
80 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
81 for plen in plens: |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
82 # if our list gets too long, execute it |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
83 if len(frags) > 128: |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
84 b2, b1 = b1, b2 |
28589
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
85 frags = [_collect(m, b1, frags)] |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
86 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
87 new = [] |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
88 end = pos + plen |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
89 last = 0 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
90 while pos < end: |
7775
5280c39778b6
pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents:
7699
diff
changeset
|
91 m.seek(pos) |
28782
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
92 try: |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
93 p1, p2, l = struct.unpack(">lll", m.read(12)) |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
94 except struct.error: |
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
95 raise mpatchError("patch cannot be decoded") |
28587
76d7cab13f04
mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents:
27337
diff
changeset
|
96 _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
|
97 _pull([], frags, p2 - p1) # what got deleted |
16683 | 98 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
|
99 pos += l + 12 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
100 last = p2 |
16683 | 101 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
|
102 |
28589
c4c7be9f0554
mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents:
28588
diff
changeset
|
103 t = _collect(m, b2, frags) |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
104 |
7775
5280c39778b6
pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents:
7699
diff
changeset
|
105 m.seek(t[1]) |
5280c39778b6
pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents:
7699
diff
changeset
|
106 return m.read(t[0]) |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
107 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
108 def patchedsize(orig, delta): |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
109 outlen, last, bin = 0, 0, 0 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
110 binend = len(delta) |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
111 data = 12 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
112 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
113 while data <= binend: |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
114 decode = delta[bin:bin + 12] |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
115 start, end, length = struct.unpack(">lll", decode) |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
116 if start > end: |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
117 break |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
118 bin = data + length |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
119 data = bin + 12 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
120 outlen += start - last |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
121 last = end |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
122 outlen += length |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
123 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
124 if bin != binend: |
28782
f736f98e16ca
mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents:
28589
diff
changeset
|
125 raise mpatchError("patch cannot be decoded") |
7699
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
126 |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
127 outlen += orig - last |
fac054f84600
pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff
changeset
|
128 return outlen |