Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/mpatch.c @ 4359:2e3c54fb79a3
actually port simplemerge to hg
- use bdiff instead of patiencediff; this is a larger change, since
bdiff works on 2 multi-line strings, while patiencediff works on 2
lists;
- rename the main class from Merge3 to Merge3Text and add a Merge3
class that derives from Merge3Text. This new Merge3 class has
the same interface from the original class, so that the tests
still work;
- Merge3 uses util.binary to detect binary data and raises
util.Abort instead of a specific exception;
- don't use the @decorator syntax, to keep python2.3 compatibility;
- the test uses unittest, which likes to print how long it took to
run. This obviously doesn't play too well with hg's test suite,
so we override time.time to fool unittest;
- one test has a different (but still valid) output because of the
different diff algorithm used;
- the TestCase class used by bzr has some extras to help debugging.
test-merge3.py used 2 of them:
- log method to log some data
- assertEqualDiff method to ease viewing diffs of diffs
We add a dummy log method and use regular assertEquals instead of
assertEqualDiff.
- make simplemerge executable and add "#!/usr/bin/env python" header
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Mon, 16 Apr 2007 20:17:39 -0300 |
parents | 95ffa36d1d2a |
children | 4759da3e4dc8 |
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> |
4073
95ffa36d1d2a
BeOS compatibility support
Andrew Bachmann <andrewbachmann@gmail.com>
parents:
3138
diff
changeset
|
45 # ifdef __BEOS__ |
95ffa36d1d2a
BeOS compatibility support
Andrew Bachmann <andrewbachmann@gmail.com>
parents:
3138
diff
changeset
|
46 # include <ByteOrder.h> |
95ffa36d1d2a
BeOS compatibility support
Andrew Bachmann <andrewbachmann@gmail.com>
parents:
3138
diff
changeset
|
47 # else |
95ffa36d1d2a
BeOS compatibility support
Andrew Bachmann <andrewbachmann@gmail.com>
parents:
3138
diff
changeset
|
48 # include <arpa/inet.h> |
95ffa36d1d2a
BeOS compatibility support
Andrew Bachmann <andrewbachmann@gmail.com>
parents:
3138
diff
changeset
|
49 # endif |
2543
860e9c83fc59
Include inttypes.h instead of stdint.h (fixes issue299)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2468
diff
changeset
|
50 # include <inttypes.h> |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
51 #endif |
72 | 52 |
53 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
|
54 static PyObject *mpatch_Error; |
72 | 55 |
56 struct frag { | |
57 int start, end, len; | |
58 char *data; | |
59 }; | |
60 | |
61 struct flist { | |
62 struct frag *base, *head, *tail; | |
63 }; | |
64 | |
65 static struct flist *lalloc(int size) | |
66 { | |
128 | 67 struct flist *a = NULL; |
72 | 68 |
3138
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
69 if (size < 1) |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
70 size = 1; |
cc856c4d91ca
mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents:
2858
diff
changeset
|
71 |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
72 a = (struct flist *)malloc(sizeof(struct flist)); |
128 | 73 if (a) { |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
74 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
|
75 if (a->base) { |
128 | 76 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
|
77 return a; |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
78 } |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
79 free(a); |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
80 a = NULL; |
128 | 81 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
82 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
|
83 PyErr_NoMemory(); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
84 return NULL; |
72 | 85 } |
86 | |
87 static void lfree(struct flist *a) | |
88 { | |
128 | 89 if (a) { |
90 free(a->base); | |
91 free(a); | |
92 } | |
72 | 93 } |
94 | |
95 static int lsize(struct flist *a) | |
96 { | |
97 return a->tail - a->head; | |
98 } | |
99 | |
100 /* move hunks in source that are less cut to dest, compensating | |
101 for changes in offset. the last hunk may be split if necessary. | |
102 */ | |
103 static int gather(struct flist *dest, struct flist *src, int cut, int offset) | |
104 { | |
105 struct frag *d = dest->tail, *s = src->head; | |
106 int postend, c, l; | |
107 | |
108 while (s != src->tail) { | |
109 if (s->start + offset >= cut) | |
82 | 110 break; /* we've gone far enough */ |
72 | 111 |
112 postend = offset + s->start + s->len; | |
113 if (postend <= cut) { | |
114 /* save this hunk */ | |
115 offset += s->start + s->len - s->end; | |
116 *d++ = *s++; | |
117 } | |
118 else { | |
119 /* break up this hunk */ | |
120 c = cut - offset; | |
121 if (s->end < c) | |
122 c = s->end; | |
123 l = cut - offset - s->start; | |
124 if (s->len < l) | |
125 l = s->len; | |
126 | |
127 offset += s->start + l - c; | |
128 | |
129 d->start = s->start; | |
130 d->end = c; | |
131 d->len = l; | |
132 d->data = s->data; | |
133 d++; | |
134 s->start = c; | |
135 s->len = s->len - l; | |
136 s->data = s->data + l; | |
137 | |
82 | 138 break; |
72 | 139 } |
140 } | |
141 | |
142 dest->tail = d; | |
143 src->head = s; | |
144 return offset; | |
145 } | |
146 | |
147 /* like gather, but with no output list */ | |
148 static int discard(struct flist *src, int cut, int offset) | |
149 { | |
150 struct frag *s = src->head; | |
151 int postend, c, l; | |
152 | |
153 while (s != src->tail) { | |
154 if (s->start + offset >= cut) | |
82 | 155 break; |
72 | 156 |
157 postend = offset + s->start + s->len; | |
158 if (postend <= cut) { | |
159 offset += s->start + s->len - s->end; | |
160 s++; | |
161 } | |
162 else { | |
163 c = cut - offset; | |
164 if (s->end < c) | |
165 c = s->end; | |
166 l = cut - offset - s->start; | |
167 if (s->len < l) | |
168 l = s->len; | |
169 | |
170 offset += s->start + l - c; | |
171 s->start = c; | |
172 s->len = s->len - l; | |
173 s->data = s->data + l; | |
174 | |
82 | 175 break; |
72 | 176 } |
177 } | |
178 | |
179 src->head = s; | |
180 return offset; | |
181 } | |
182 | |
183 /* combine hunk lists a and b, while adjusting b for offset changes in a/ | |
184 this deletes a and b and returns the resultant list. */ | |
185 static struct flist *combine(struct flist *a, struct flist *b) | |
186 { | |
128 | 187 struct flist *c = NULL; |
188 struct frag *bh, *ct; | |
72 | 189 int offset = 0, post; |
190 | |
128 | 191 if (a && b) |
192 c = lalloc((lsize(a) + lsize(b)) * 2); | |
193 | |
194 if (c) { | |
72 | 195 |
128 | 196 for (bh = b->head; bh != b->tail; bh++) { |
197 /* save old hunks */ | |
198 offset = gather(c, a, bh->start, offset); | |
72 | 199 |
128 | 200 /* discard replaced hunks */ |
201 post = discard(a, bh->end, offset); | |
72 | 202 |
128 | 203 /* insert new hunk */ |
204 ct = c->tail; | |
205 ct->start = bh->start - offset; | |
206 ct->end = bh->end - post; | |
207 ct->len = bh->len; | |
208 ct->data = bh->data; | |
209 c->tail++; | |
210 offset = post; | |
211 } | |
212 | |
213 /* hold on to tail from a */ | |
214 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); | |
215 c->tail += lsize(a); | |
72 | 216 } |
217 | |
218 lfree(a); | |
219 lfree(b); | |
220 return c; | |
221 } | |
222 | |
223 /* decode a binary patch into a hunk list */ | |
224 static struct flist *decode(char *bin, int len) | |
225 { | |
226 struct flist *l; | |
227 struct frag *lt; | |
228 char *end = bin + len; | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
229 char decode[12]; /* for dealing with alignment issues */ |
72 | 230 |
231 /* assume worst case size, we won't have many of these lists */ | |
232 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
|
233 if (!l) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
234 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
235 |
72 | 236 lt = l->tail; |
237 | |
238 while (bin < end) { | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
239 memcpy(decode, bin, 12); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
240 lt->start = ntohl(*(uint32_t *)decode); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
241 lt->end = ntohl(*(uint32_t *)(decode + 4)); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
242 lt->len = ntohl(*(uint32_t *)(decode + 8)); |
72 | 243 lt->data = bin + 12; |
244 bin += 12 + lt->len; | |
245 lt++; | |
246 } | |
247 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
248 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
|
249 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
|
250 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
|
251 lfree(l); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
252 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
253 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
254 |
72 | 255 l->tail = lt; |
256 return l; | |
257 } | |
258 | |
259 /* calculate the size of resultant text */ | |
260 static int calcsize(int len, struct flist *l) | |
261 { | |
262 int outlen = 0, last = 0; | |
263 struct frag *f = l->head; | |
264 | |
265 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
|
266 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
|
267 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
|
268 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
|
269 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
270 return -1; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
271 } |
72 | 272 outlen += f->start - last; |
273 last = f->end; | |
274 outlen += f->len; | |
275 f++; | |
276 } | |
277 | |
278 outlen += len - last; | |
279 return outlen; | |
280 } | |
281 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
282 static int apply(char *buf, char *orig, int len, struct flist *l) |
72 | 283 { |
284 struct frag *f = l->head; | |
285 int last = 0; | |
286 char *p = buf; | |
287 | |
288 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
|
289 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
|
290 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
|
291 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
|
292 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
293 return 0; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
294 } |
72 | 295 memcpy(p, orig + last, f->start - last); |
296 p += f->start - last; | |
297 memcpy(p, f->data, f->len); | |
298 last = f->end; | |
299 p += f->len; | |
300 f++; | |
301 } | |
302 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
|
303 return 1; |
72 | 304 } |
305 | |
306 /* recursively generate a patch of all bins between start and end */ | |
307 static struct flist *fold(PyObject *bins, int start, int end) | |
308 { | |
309 int len; | |
310 | |
311 if (start + 1 == end) { | |
312 /* trivial case, output a decoded list */ | |
313 PyObject *tmp = PyList_GetItem(bins, start); | |
128 | 314 if (!tmp) |
315 return NULL; | |
72 | 316 return decode(PyString_AsString(tmp), PyString_Size(tmp)); |
317 } | |
318 | |
319 /* divide and conquer, memory management is elsewhere */ | |
320 len = (end - start) / 2; | |
321 return combine(fold(bins, start, start + len), | |
322 fold(bins, start + len, end)); | |
323 } | |
324 | |
325 static PyObject * | |
326 patches(PyObject *self, PyObject *args) | |
327 { | |
328 PyObject *text, *bins, *result; | |
329 struct flist *patch; | |
330 char *in, *out; | |
331 int len, outlen; | |
332 | |
128 | 333 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins)) |
72 | 334 return NULL; |
335 | |
336 len = PyList_Size(bins); | |
337 if (!len) { | |
338 /* nothing to do */ | |
339 Py_INCREF(text); | |
340 return text; | |
341 } | |
342 | |
343 patch = fold(bins, 0, len); | |
128 | 344 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
|
345 return NULL; |
128 | 346 |
72 | 347 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
|
348 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
|
349 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
350 goto cleanup; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
351 } |
72 | 352 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
|
353 if (!result) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
354 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
355 goto cleanup; |
128 | 356 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
357 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
|
358 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
|
359 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
|
360 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
|
361 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
362 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
363 cleanup: |
72 | 364 lfree(patch); |
365 return result; | |
366 } | |
367 | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
368 /* calculate size of a patched file directly */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
369 static PyObject * |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
370 patchedsize(PyObject *self, PyObject *args) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
371 { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
372 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
|
373 int patchlen; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
374 char *bin, *binend; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
375 char decode[12]; /* for dealing with alignment issues */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
376 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
377 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
378 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
379 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
380 binend = bin + patchlen; |
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 while (bin < binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
383 memcpy(decode, bin, 12); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
384 start = ntohl(*(uint32_t *)decode); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
385 end = ntohl(*(uint32_t *)(decode + 4)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
386 len = ntohl(*(uint32_t *)(decode + 8)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
387 bin += 12 + len; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
388 outlen += start - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
389 last = end; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
390 outlen += len; |
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 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
393 if (bin != binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
394 if (!PyErr_Occurred()) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
395 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
396 return NULL; |
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 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
399 outlen += orig - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
400 return Py_BuildValue("l", outlen); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
401 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
402 |
72 | 403 static PyMethodDef methods[] = { |
404 {"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
|
405 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"}, |
72 | 406 {NULL, NULL} |
407 }; | |
408 | |
409 PyMODINIT_FUNC | |
410 initmpatch(void) | |
411 { | |
412 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
|
413 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); |
72 | 414 } |
415 |