Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/mpatch.c @ 4074:0f9381cf9723
Try to pass repo.ui to reposetup hooks
The ui object we received in this function may belong to another repo,
which could be confusing from the hook point of view. Trying to use
the ui object from the newly created repo should avoid this confusion.
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Thu, 08 Feb 2007 16:31:21 -0200 |
parents | cc856c4d91ca |
children | 95ffa36d1d2a 11dc22eb8e8d |
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 | |
2858 | 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 | |
23 #include <Python.h> | |
24 #include <stdlib.h> | |
25 #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
|
26 |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
27 #ifdef _WIN32 |
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
|
28 # ifdef _MSC_VER |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
29 /* msvc 6.0 has problems */ |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
30 # define inline __inline |
551 | 31 typedef unsigned long uint32_t; |
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
|
32 # else |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
33 # include <stdint.h> |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
34 # endif |
411
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
35 static uint32_t ntohl(uint32_t x) |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
36 { |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
37 return ((x & 0x000000ffUL) << 24) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
38 ((x & 0x0000ff00UL) << 8) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
39 ((x & 0x00ff0000UL) >> 8) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
40 ((x & 0xff000000UL) >> 24); |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
41 } |
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
42 #else |
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
|
43 /* not windows */ |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
44 # include <sys/types.h> |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
45 # include <arpa/inet.h> |
2543
860e9c83fc59
Include inttypes.h instead of stdint.h (fixes issue299)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2468
diff
changeset
|
46 # include <inttypes.h> |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
47 #endif |
72 | 48 |
49 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
|
50 static PyObject *mpatch_Error; |
72 | 51 |
52 struct frag { | |
53 int start, end, len; | |
54 char *data; | |
55 }; | |
56 | |
57 struct flist { | |
58 struct frag *base, *head, *tail; | |
59 }; | |
60 | |
61 static struct flist *lalloc(int size) | |
62 { | |
128 | 63 struct flist *a = NULL; |
72 | 64 |
3138
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
65 if (size < 1) |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
66 size = 1; |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
67 |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
68 a = (struct flist *)malloc(sizeof(struct flist)); |
128 | 69 if (a) { |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
70 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
|
71 if (a->base) { |
128 | 72 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
|
73 return a; |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
74 } |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
75 free(a); |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
76 a = NULL; |
128 | 77 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
78 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
|
79 PyErr_NoMemory(); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
80 return NULL; |
72 | 81 } |
82 | |
83 static void lfree(struct flist *a) | |
84 { | |
128 | 85 if (a) { |
86 free(a->base); | |
87 free(a); | |
88 } | |
72 | 89 } |
90 | |
91 static int lsize(struct flist *a) | |
92 { | |
93 return a->tail - a->head; | |
94 } | |
95 | |
96 /* move hunks in source that are less cut to dest, compensating | |
97 for changes in offset. the last hunk may be split if necessary. | |
98 */ | |
99 static int gather(struct flist *dest, struct flist *src, int cut, int offset) | |
100 { | |
101 struct frag *d = dest->tail, *s = src->head; | |
102 int postend, c, l; | |
103 | |
104 while (s != src->tail) { | |
105 if (s->start + offset >= cut) | |
82 | 106 break; /* we've gone far enough */ |
72 | 107 |
108 postend = offset + s->start + s->len; | |
109 if (postend <= cut) { | |
110 /* save this hunk */ | |
111 offset += s->start + s->len - s->end; | |
112 *d++ = *s++; | |
113 } | |
114 else { | |
115 /* break up this hunk */ | |
116 c = cut - offset; | |
117 if (s->end < c) | |
118 c = s->end; | |
119 l = cut - offset - s->start; | |
120 if (s->len < l) | |
121 l = s->len; | |
122 | |
123 offset += s->start + l - c; | |
124 | |
125 d->start = s->start; | |
126 d->end = c; | |
127 d->len = l; | |
128 d->data = s->data; | |
129 d++; | |
130 s->start = c; | |
131 s->len = s->len - l; | |
132 s->data = s->data + l; | |
133 | |
82 | 134 break; |
72 | 135 } |
136 } | |
137 | |
138 dest->tail = d; | |
139 src->head = s; | |
140 return offset; | |
141 } | |
142 | |
143 /* like gather, but with no output list */ | |
144 static int discard(struct flist *src, int cut, int offset) | |
145 { | |
146 struct frag *s = src->head; | |
147 int postend, c, l; | |
148 | |
149 while (s != src->tail) { | |
150 if (s->start + offset >= cut) | |
82 | 151 break; |
72 | 152 |
153 postend = offset + s->start + s->len; | |
154 if (postend <= cut) { | |
155 offset += s->start + s->len - s->end; | |
156 s++; | |
157 } | |
158 else { | |
159 c = cut - offset; | |
160 if (s->end < c) | |
161 c = s->end; | |
162 l = cut - offset - s->start; | |
163 if (s->len < l) | |
164 l = s->len; | |
165 | |
166 offset += s->start + l - c; | |
167 s->start = c; | |
168 s->len = s->len - l; | |
169 s->data = s->data + l; | |
170 | |
82 | 171 break; |
72 | 172 } |
173 } | |
174 | |
175 src->head = s; | |
176 return offset; | |
177 } | |
178 | |
179 /* combine hunk lists a and b, while adjusting b for offset changes in a/ | |
180 this deletes a and b and returns the resultant list. */ | |
181 static struct flist *combine(struct flist *a, struct flist *b) | |
182 { | |
128 | 183 struct flist *c = NULL; |
184 struct frag *bh, *ct; | |
72 | 185 int offset = 0, post; |
186 | |
128 | 187 if (a && b) |
188 c = lalloc((lsize(a) + lsize(b)) * 2); | |
189 | |
190 if (c) { | |
72 | 191 |
128 | 192 for (bh = b->head; bh != b->tail; bh++) { |
193 /* save old hunks */ | |
194 offset = gather(c, a, bh->start, offset); | |
72 | 195 |
128 | 196 /* discard replaced hunks */ |
197 post = discard(a, bh->end, offset); | |
72 | 198 |
128 | 199 /* insert new hunk */ |
200 ct = c->tail; | |
201 ct->start = bh->start - offset; | |
202 ct->end = bh->end - post; | |
203 ct->len = bh->len; | |
204 ct->data = bh->data; | |
205 c->tail++; | |
206 offset = post; | |
207 } | |
208 | |
209 /* hold on to tail from a */ | |
210 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); | |
211 c->tail += lsize(a); | |
72 | 212 } |
213 | |
214 lfree(a); | |
215 lfree(b); | |
216 return c; | |
217 } | |
218 | |
219 /* decode a binary patch into a hunk list */ | |
220 static struct flist *decode(char *bin, int len) | |
221 { | |
222 struct flist *l; | |
223 struct frag *lt; | |
224 char *end = bin + len; | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
225 char decode[12]; /* for dealing with alignment issues */ |
72 | 226 |
227 /* assume worst case size, we won't have many of these lists */ | |
228 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
|
229 if (!l) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
230 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
231 |
72 | 232 lt = l->tail; |
233 | |
234 while (bin < end) { | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
235 memcpy(decode, bin, 12); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
236 lt->start = ntohl(*(uint32_t *)decode); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
237 lt->end = ntohl(*(uint32_t *)(decode + 4)); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
238 lt->len = ntohl(*(uint32_t *)(decode + 8)); |
72 | 239 lt->data = bin + 12; |
240 bin += 12 + lt->len; | |
241 lt++; | |
242 } | |
243 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
244 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
|
245 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
|
246 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
|
247 lfree(l); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
248 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
249 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
250 |
72 | 251 l->tail = lt; |
252 return l; | |
253 } | |
254 | |
255 /* calculate the size of resultant text */ | |
256 static int calcsize(int len, struct flist *l) | |
257 { | |
258 int outlen = 0, last = 0; | |
259 struct frag *f = l->head; | |
260 | |
261 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
|
262 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
|
263 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
|
264 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
|
265 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
266 return -1; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
267 } |
72 | 268 outlen += f->start - last; |
269 last = f->end; | |
270 outlen += f->len; | |
271 f++; | |
272 } | |
273 | |
274 outlen += len - last; | |
275 return outlen; | |
276 } | |
277 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
278 static int apply(char *buf, char *orig, int len, struct flist *l) |
72 | 279 { |
280 struct frag *f = l->head; | |
281 int last = 0; | |
282 char *p = buf; | |
283 | |
284 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
|
285 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
|
286 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
|
287 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
|
288 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
289 return 0; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
290 } |
72 | 291 memcpy(p, orig + last, f->start - last); |
292 p += f->start - last; | |
293 memcpy(p, f->data, f->len); | |
294 last = f->end; | |
295 p += f->len; | |
296 f++; | |
297 } | |
298 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
|
299 return 1; |
72 | 300 } |
301 | |
302 /* recursively generate a patch of all bins between start and end */ | |
303 static struct flist *fold(PyObject *bins, int start, int end) | |
304 { | |
305 int len; | |
306 | |
307 if (start + 1 == end) { | |
308 /* trivial case, output a decoded list */ | |
309 PyObject *tmp = PyList_GetItem(bins, start); | |
128 | 310 if (!tmp) |
311 return NULL; | |
72 | 312 return decode(PyString_AsString(tmp), PyString_Size(tmp)); |
313 } | |
314 | |
315 /* divide and conquer, memory management is elsewhere */ | |
316 len = (end - start) / 2; | |
317 return combine(fold(bins, start, start + len), | |
318 fold(bins, start + len, end)); | |
319 } | |
320 | |
321 static PyObject * | |
322 patches(PyObject *self, PyObject *args) | |
323 { | |
324 PyObject *text, *bins, *result; | |
325 struct flist *patch; | |
326 char *in, *out; | |
327 int len, outlen; | |
328 | |
128 | 329 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins)) |
72 | 330 return NULL; |
331 | |
332 len = PyList_Size(bins); | |
333 if (!len) { | |
334 /* nothing to do */ | |
335 Py_INCREF(text); | |
336 return text; | |
337 } | |
338 | |
339 patch = fold(bins, 0, len); | |
128 | 340 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
|
341 return NULL; |
128 | 342 |
72 | 343 outlen = calcsize(PyString_Size(text), patch); |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
344 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
|
345 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
346 goto cleanup; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
347 } |
72 | 348 result = PyString_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
|
349 if (!result) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
350 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
351 goto cleanup; |
128 | 352 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
353 in = PyString_AsString(text); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
354 out = PyString_AsString(result); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
355 if (!apply(out, in, PyString_Size(text), patch)) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
356 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
|
357 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
358 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
359 cleanup: |
72 | 360 lfree(patch); |
361 return result; | |
362 } | |
363 | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
364 /* calculate size of a patched file directly */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
365 static PyObject * |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
366 patchedsize(PyObject *self, PyObject *args) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
367 { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
368 long orig, start, end, len, outlen = 0, last = 0; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
369 int patchlen; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
370 char *bin, *binend; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
371 char decode[12]; /* for dealing with alignment issues */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
372 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
373 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
374 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
375 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
376 binend = bin + patchlen; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
377 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
378 while (bin < binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
379 memcpy(decode, bin, 12); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
380 start = ntohl(*(uint32_t *)decode); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
381 end = ntohl(*(uint32_t *)(decode + 4)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
382 len = ntohl(*(uint32_t *)(decode + 8)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
383 bin += 12 + len; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
384 outlen += start - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
385 last = end; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
386 outlen += len; |
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 if (bin != binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
390 if (!PyErr_Occurred()) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
391 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
392 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
393 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
394 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
395 outlen += orig - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
396 return Py_BuildValue("l", outlen); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
397 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
398 |
72 | 399 static PyMethodDef methods[] = { |
400 {"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
|
401 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"}, |
72 | 402 {NULL, NULL} |
403 }; | |
404 | |
405 PyMODINIT_FUNC | |
406 initmpatch(void) | |
407 { | |
408 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
|
409 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); |
72 | 410 } |
411 |