Mercurial > hg-stable
annotate mercurial/mpatch.c @ 18686:0bca4d31f647
backout: remove unnecessary frobbing of addremove option
There's no way for addremove to show up in backout's opts dictionary. It
was being set manually because cmdutil.commit expected it to be there
(and would throw an exception if it wasn't). This was fixed waaaaaaay
back in:
changeset: 5829:784073457a0f
user: Kirill Smelkov <kirr@mns.spb.ru>
date: Thu Jan 10 12:07:18 2008 +0300
summary: cmdutil.commit: extract 'addremove' from opts carefully
author | Kevin Bullock <kbullock@ringworld.org> |
---|---|
date | Tue, 12 Feb 2013 15:47:30 +0000 |
parents | 9a8ab5c47f84 |
children | 09e41ac6289d |
rev | line source |
---|---|
72 | 1 /* |
2 mpatch.c - efficient binary patching for Mercurial | |
3 | |
4 This implements a patch algorithm that's O(m + nlog n) where m is the | |
5 size of the output and n is the number of patches. | |
6 | |
7 Given a list of binary patches, it unpacks each into a hunk list, | |
8 then combines the hunk lists with a treewise recursion to form a | |
9 single hunk list. This hunk list is then applied to the original | |
10 text. | |
11 | |
12 The text (or binary) fragments are copied directly from their source | |
13 Python objects into a preallocated output string to avoid the | |
14 allocation of intermediate Python objects. Working memory is about 2x | |
15 the total number of hunks. | |
16 | |
2859 | 17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
72 | 18 |
19 This software may be used and distributed according to the terms | |
20 of the GNU General Public License, incorporated herein by reference. | |
21 */ | |
22 | |
16758
9a8ab5c47f84
mpatch: use Py_ssize_t for string length
Adrian Buehlmann <adrian@cadifra.com>
parents:
16757
diff
changeset
|
23 #define PY_SSIZE_T_CLEAN |
72 | 24 #include <Python.h> |
25 #include <stdlib.h> | |
26 #include <string.h> | |
2468
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
27 |
11360
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
28 #include "util.h" |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
29 |
72 | 30 static char mpatch_doc[] = "Efficient binary patching."; |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
31 static PyObject *mpatch_Error; |
72 | 32 |
33 struct frag { | |
34 int start, end, len; | |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
35 const char *data; |
72 | 36 }; |
37 | |
38 struct flist { | |
39 struct frag *base, *head, *tail; | |
40 }; | |
41 | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
42 static struct flist *lalloc(Py_ssize_t size) |
72 | 43 { |
128 | 44 struct flist *a = NULL; |
72 | 45 |
3138
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
46 if (size < 1) |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
47 size = 1; |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
48 |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
49 a = (struct flist *)malloc(sizeof(struct flist)); |
128 | 50 if (a) { |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
51 a->base = (struct frag *)malloc(sizeof(struct frag) * size); |
2048
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
52 if (a->base) { |
128 | 53 a->head = a->tail = a->base; |
2048
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
54 return a; |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
55 } |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
56 free(a); |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
57 a = NULL; |
128 | 58 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
59 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
60 PyErr_NoMemory(); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
61 return NULL; |
72 | 62 } |
63 | |
64 static void lfree(struct flist *a) | |
65 { | |
128 | 66 if (a) { |
67 free(a->base); | |
68 free(a); | |
69 } | |
72 | 70 } |
71 | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
72 static Py_ssize_t lsize(struct flist *a) |
72 | 73 { |
74 return a->tail - a->head; | |
75 } | |
76 | |
77 /* move hunks in source that are less cut to dest, compensating | |
78 for changes in offset. the last hunk may be split if necessary. | |
79 */ | |
80 static int gather(struct flist *dest, struct flist *src, int cut, int offset) | |
81 { | |
82 struct frag *d = dest->tail, *s = src->head; | |
83 int postend, c, l; | |
84 | |
85 while (s != src->tail) { | |
86 if (s->start + offset >= cut) | |
82 | 87 break; /* we've gone far enough */ |
72 | 88 |
89 postend = offset + s->start + s->len; | |
90 if (postend <= cut) { | |
91 /* save this hunk */ | |
92 offset += s->start + s->len - s->end; | |
93 *d++ = *s++; | |
94 } | |
95 else { | |
96 /* break up this hunk */ | |
97 c = cut - offset; | |
98 if (s->end < c) | |
99 c = s->end; | |
100 l = cut - offset - s->start; | |
101 if (s->len < l) | |
102 l = s->len; | |
103 | |
104 offset += s->start + l - c; | |
105 | |
106 d->start = s->start; | |
107 d->end = c; | |
108 d->len = l; | |
109 d->data = s->data; | |
110 d++; | |
111 s->start = c; | |
112 s->len = s->len - l; | |
113 s->data = s->data + l; | |
114 | |
82 | 115 break; |
72 | 116 } |
117 } | |
118 | |
119 dest->tail = d; | |
120 src->head = s; | |
121 return offset; | |
122 } | |
123 | |
124 /* like gather, but with no output list */ | |
125 static int discard(struct flist *src, int cut, int offset) | |
126 { | |
127 struct frag *s = src->head; | |
128 int postend, c, l; | |
129 | |
130 while (s != src->tail) { | |
131 if (s->start + offset >= cut) | |
82 | 132 break; |
72 | 133 |
134 postend = offset + s->start + s->len; | |
135 if (postend <= cut) { | |
136 offset += s->start + s->len - s->end; | |
137 s++; | |
138 } | |
139 else { | |
140 c = cut - offset; | |
141 if (s->end < c) | |
142 c = s->end; | |
143 l = cut - offset - s->start; | |
144 if (s->len < l) | |
145 l = s->len; | |
146 | |
147 offset += s->start + l - c; | |
148 s->start = c; | |
149 s->len = s->len - l; | |
150 s->data = s->data + l; | |
151 | |
82 | 152 break; |
72 | 153 } |
154 } | |
155 | |
156 src->head = s; | |
157 return offset; | |
158 } | |
159 | |
160 /* combine hunk lists a and b, while adjusting b for offset changes in a/ | |
161 this deletes a and b and returns the resultant list. */ | |
162 static struct flist *combine(struct flist *a, struct flist *b) | |
163 { | |
128 | 164 struct flist *c = NULL; |
165 struct frag *bh, *ct; | |
72 | 166 int offset = 0, post; |
167 | |
128 | 168 if (a && b) |
169 c = lalloc((lsize(a) + lsize(b)) * 2); | |
170 | |
171 if (c) { | |
72 | 172 |
128 | 173 for (bh = b->head; bh != b->tail; bh++) { |
174 /* save old hunks */ | |
175 offset = gather(c, a, bh->start, offset); | |
72 | 176 |
128 | 177 /* discard replaced hunks */ |
178 post = discard(a, bh->end, offset); | |
72 | 179 |
128 | 180 /* insert new hunk */ |
181 ct = c->tail; | |
182 ct->start = bh->start - offset; | |
183 ct->end = bh->end - post; | |
184 ct->len = bh->len; | |
185 ct->data = bh->data; | |
186 c->tail++; | |
187 offset = post; | |
188 } | |
189 | |
190 /* hold on to tail from a */ | |
191 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); | |
192 c->tail += lsize(a); | |
72 | 193 } |
194 | |
195 lfree(a); | |
196 lfree(b); | |
197 return c; | |
198 } | |
199 | |
200 /* decode a binary patch into a hunk list */ | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
201 static struct flist *decode(const char *bin, Py_ssize_t len) |
72 | 202 { |
203 struct flist *l; | |
204 struct frag *lt; | |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
205 const char *data = bin + 12, *end = bin + len; |
72 | 206 |
207 /* assume worst case size, we won't have many of these lists */ | |
208 l = lalloc(len / 12); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
209 if (!l) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
210 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
211 |
72 | 212 lt = l->tail; |
213 | |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
214 while (data <= end) { |
16437
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
215 lt->start = getbe32(bin); |
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
216 lt->end = getbe32(bin + 4); |
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
217 lt->len = getbe32(bin + 8); |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
218 if (lt->start > lt->end) |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
219 break; /* sanity check */ |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
220 bin = data + lt->len; |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
221 if (bin < data) |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
222 break; /* big data + big (bogus) len can wrap around */ |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
223 lt->data = data; |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
224 data = bin + 12; |
72 | 225 lt++; |
226 } | |
227 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
228 if (bin != end) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
229 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
230 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
231 lfree(l); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
232 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
233 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
234 |
72 | 235 l->tail = lt; |
236 return l; | |
237 } | |
238 | |
239 /* calculate the size of resultant text */ | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
240 static Py_ssize_t calcsize(Py_ssize_t len, struct flist *l) |
72 | 241 { |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
242 Py_ssize_t outlen = 0, last = 0; |
72 | 243 struct frag *f = l->head; |
244 | |
245 while (f != l->tail) { | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
246 if (f->start < last || f->end > len) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
247 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
248 PyErr_SetString(mpatch_Error, |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
249 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
250 return -1; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
251 } |
72 | 252 outlen += f->start - last; |
253 last = f->end; | |
254 outlen += f->len; | |
255 f++; | |
256 } | |
257 | |
258 outlen += len - last; | |
259 return outlen; | |
260 } | |
261 | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
262 static int apply(char *buf, const char *orig, Py_ssize_t len, struct flist *l) |
72 | 263 { |
264 struct frag *f = l->head; | |
265 int last = 0; | |
266 char *p = buf; | |
267 | |
268 while (f != l->tail) { | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
269 if (f->start < last || f->end > len) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
270 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
271 PyErr_SetString(mpatch_Error, |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
272 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
273 return 0; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
274 } |
72 | 275 memcpy(p, orig + last, f->start - last); |
276 p += f->start - last; | |
277 memcpy(p, f->data, f->len); | |
278 last = f->end; | |
279 p += f->len; | |
280 f++; | |
281 } | |
282 memcpy(p, orig + last, len - last); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
283 return 1; |
72 | 284 } |
285 | |
286 /* recursively generate a patch of all bins between start and end */ | |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
287 static struct flist *fold(PyObject *bins, Py_ssize_t start, Py_ssize_t end) |
72 | 288 { |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
289 Py_ssize_t len, blen; |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
290 const char *buffer; |
72 | 291 |
292 if (start + 1 == end) { | |
293 /* trivial case, output a decoded list */ | |
294 PyObject *tmp = PyList_GetItem(bins, start); | |
128 | 295 if (!tmp) |
296 return NULL; | |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
297 if (PyObject_AsCharBuffer(tmp, &buffer, &blen)) |
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
298 return NULL; |
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
299 return decode(buffer, blen); |
72 | 300 } |
301 | |
302 /* divide and conquer, memory management is elsewhere */ | |
303 len = (end - start) / 2; | |
304 return combine(fold(bins, start, start + len), | |
305 fold(bins, start + len, end)); | |
306 } | |
307 | |
308 static PyObject * | |
309 patches(PyObject *self, PyObject *args) | |
310 { | |
311 PyObject *text, *bins, *result; | |
312 struct flist *patch; | |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
313 const char *in; |
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
314 char *out; |
16757
923bd97b86a0
mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents:
16437
diff
changeset
|
315 Py_ssize_t len, outlen, inlen; |
72 | 316 |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
317 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) |
72 | 318 return NULL; |
319 | |
320 len = PyList_Size(bins); | |
321 if (!len) { | |
322 /* nothing to do */ | |
323 Py_INCREF(text); | |
324 return text; | |
325 } | |
326 | |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
327 if (PyObject_AsCharBuffer(text, &in, &inlen)) |
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
328 return NULL; |
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
329 |
72 | 330 patch = fold(bins, 0, len); |
128 | 331 if (!patch) |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
332 return NULL; |
128 | 333 |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
334 outlen = calcsize(inlen, patch); |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
335 if (outlen < 0) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
336 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
337 goto cleanup; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
338 } |
11360
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
339 result = PyBytes_FromStringAndSize(NULL, outlen); |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
340 if (!result) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
341 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
342 goto cleanup; |
128 | 343 } |
11360
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
344 out = PyBytes_AsString(result); |
5444
a0952e4e52eb
mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents:
4377
diff
changeset
|
345 if (!apply(out, in, inlen, patch)) { |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
346 Py_DECREF(result); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
347 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
348 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
349 cleanup: |
72 | 350 lfree(patch); |
351 return result; | |
352 } | |
353 | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
354 /* calculate size of a patched file directly */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
355 static PyObject * |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
356 patchedsize(PyObject *self, PyObject *args) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
357 { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
358 long orig, start, end, len, outlen = 0, last = 0; |
16758
9a8ab5c47f84
mpatch: use Py_ssize_t for string length
Adrian Buehlmann <adrian@cadifra.com>
parents:
16757
diff
changeset
|
359 Py_ssize_t patchlen; |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
360 char *bin, *binend, *data; |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
361 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
362 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
363 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
364 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
365 binend = bin + patchlen; |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
366 data = bin + 12; |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
367 |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
368 while (data <= binend) { |
16437
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
369 start = getbe32(bin); |
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
370 end = getbe32(bin + 4); |
d126a0d16856
util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents:
16385
diff
changeset
|
371 len = getbe32(bin + 8); |
4358
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
372 if (start > end) |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
373 break; /* sanity check */ |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
374 bin = data + len; |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
375 if (bin < data) |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
376 break; /* big data + big (bogus) len can wrap around */ |
11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3138
diff
changeset
|
377 data = bin + 12; |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
378 outlen += start - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
379 last = end; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
380 outlen += len; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
381 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
382 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
383 if (bin != binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
384 if (!PyErr_Occurred()) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
385 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
386 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
387 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
388 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
389 outlen += orig - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
390 return Py_BuildValue("l", outlen); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
391 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
392 |
72 | 393 static PyMethodDef methods[] = { |
394 {"patches", patches, METH_VARARGS, "apply a series of patches\n"}, | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
395 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"}, |
72 | 396 {NULL, NULL} |
397 }; | |
398 | |
11360
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
399 #ifdef IS_PY3K |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
400 static struct PyModuleDef mpatch_module = { |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
401 PyModuleDef_HEAD_INIT, |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
402 "mpatch", |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
403 mpatch_doc, |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
404 -1, |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
405 methods |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
406 }; |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
407 |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
408 PyMODINIT_FUNC PyInit_mpatch(void) |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
409 { |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
410 PyObject *m; |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
411 |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
412 m = PyModule_Create(&mpatch_module); |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
413 if (m == NULL) |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
414 return NULL; |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
415 |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
416 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
417 Py_INCREF(mpatch_Error); |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
418 PyModule_AddObject(m, "mpatchError", mpatch_Error); |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
419 |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
420 return m; |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
421 } |
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
422 #else |
72 | 423 PyMODINIT_FUNC |
424 initmpatch(void) | |
425 { | |
426 Py_InitModule3("mpatch", methods, mpatch_doc); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
427 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); |
72 | 428 } |
11360
2ac98313b26c
mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents:
10282
diff
changeset
|
429 #endif |