##// END OF EJS Templates
mpatch: remove superfluous whitespaces
Yuya Nishihara -
r29740:21ac534d default
parent child Browse files
Show More
@@ -1,284 +1,283 b''
1 /*
1 /*
2 mpatch.c - efficient binary patching for Mercurial
2 mpatch.c - efficient binary patching for Mercurial
3
3
4 This implements a patch algorithm that's O(m + nlog n) where m is the
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.
5 size of the output and n is the number of patches.
6
6
7 Given a list of binary patches, it unpacks each into a hunk list,
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
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
9 single hunk list. This hunk list is then applied to the original
10 text.
10 text.
11
11
12 The text (or binary) fragments are copied directly from their source
12 The text (or binary) fragments are copied directly from their source
13 Python objects into a preallocated output string to avoid the
13 Python objects into a preallocated output string to avoid the
14 allocation of intermediate Python objects. Working memory is about 2x
14 allocation of intermediate Python objects. Working memory is about 2x
15 the total number of hunks.
15 the total number of hunks.
16
16
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
18
18
19 This software may be used and distributed according to the terms
19 This software may be used and distributed according to the terms
20 of the GNU General Public License, incorporated herein by reference.
20 of the GNU General Public License, incorporated herein by reference.
21 */
21 */
22
22
23 #include <stdlib.h>
23 #include <stdlib.h>
24 #include <string.h>
24 #include <string.h>
25
25
26 #include "bitmanipulation.h"
26 #include "bitmanipulation.h"
27 #include "compat.h"
27 #include "compat.h"
28 #include "mpatch.h"
28 #include "mpatch.h"
29
29
30 char *mpatch_errors[] = {NULL, "invalid patch", "patch cannot be decoded",
30 char *mpatch_errors[] = {NULL, "invalid patch", "patch cannot be decoded",
31 "no memory"};
31 "no memory"};
32
32
33 struct mpatch_flist *lalloc(ssize_t size)
33 struct mpatch_flist *lalloc(ssize_t size)
34 {
34 {
35 struct mpatch_flist *a = NULL;
35 struct mpatch_flist *a = NULL;
36
36
37 if (size < 1)
37 if (size < 1)
38 size = 1;
38 size = 1;
39
39
40 a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist));
40 a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist));
41 if (a) {
41 if (a) {
42 a->base = (struct mpatch_frag *)malloc(sizeof(struct mpatch_frag) * size);
42 a->base = (struct mpatch_frag *)malloc(sizeof(struct mpatch_frag) * size);
43 if (a->base) {
43 if (a->base) {
44 a->head = a->tail = a->base;
44 a->head = a->tail = a->base;
45 return a;
45 return a;
46 }
46 }
47 free(a);
47 free(a);
48 }
48 }
49 return NULL;
49 return NULL;
50 }
50 }
51
51
52 void mpatch_lfree(struct mpatch_flist *a)
52 void mpatch_lfree(struct mpatch_flist *a)
53 {
53 {
54 if (a) {
54 if (a) {
55 free(a->base);
55 free(a->base);
56 free(a);
56 free(a);
57 }
57 }
58 }
58 }
59
59
60 static ssize_t lsize(struct mpatch_flist *a)
60 static ssize_t lsize(struct mpatch_flist *a)
61 {
61 {
62 return a->tail - a->head;
62 return a->tail - a->head;
63 }
63 }
64
64
65 /* move hunks in source that are less cut to dest, compensating
65 /* move hunks in source that are less cut to dest, compensating
66 for changes in offset. the last hunk may be split if necessary.
66 for changes in offset. the last hunk may be split if necessary.
67 */
67 */
68 static int gather(struct mpatch_flist *dest, struct mpatch_flist *src, int cut,
68 static int gather(struct mpatch_flist *dest, struct mpatch_flist *src, int cut,
69 int offset)
69 int offset)
70 {
70 {
71 struct mpatch_frag *d = dest->tail, *s = src->head;
71 struct mpatch_frag *d = dest->tail, *s = src->head;
72 int postend, c, l;
72 int postend, c, l;
73
73
74 while (s != src->tail) {
74 while (s != src->tail) {
75 if (s->start + offset >= cut)
75 if (s->start + offset >= cut)
76 break; /* we've gone far enough */
76 break; /* we've gone far enough */
77
77
78 postend = offset + s->start + s->len;
78 postend = offset + s->start + s->len;
79 if (postend <= cut) {
79 if (postend <= cut) {
80 /* save this hunk */
80 /* save this hunk */
81 offset += s->start + s->len - s->end;
81 offset += s->start + s->len - s->end;
82 *d++ = *s++;
82 *d++ = *s++;
83 }
83 }
84 else {
84 else {
85 /* break up this hunk */
85 /* break up this hunk */
86 c = cut - offset;
86 c = cut - offset;
87 if (s->end < c)
87 if (s->end < c)
88 c = s->end;
88 c = s->end;
89 l = cut - offset - s->start;
89 l = cut - offset - s->start;
90 if (s->len < l)
90 if (s->len < l)
91 l = s->len;
91 l = s->len;
92
92
93 offset += s->start + l - c;
93 offset += s->start + l - c;
94
94
95 d->start = s->start;
95 d->start = s->start;
96 d->end = c;
96 d->end = c;
97 d->len = l;
97 d->len = l;
98 d->data = s->data;
98 d->data = s->data;
99 d++;
99 d++;
100 s->start = c;
100 s->start = c;
101 s->len = s->len - l;
101 s->len = s->len - l;
102 s->data = s->data + l;
102 s->data = s->data + l;
103
103
104 break;
104 break;
105 }
105 }
106 }
106 }
107
107
108 dest->tail = d;
108 dest->tail = d;
109 src->head = s;
109 src->head = s;
110 return offset;
110 return offset;
111 }
111 }
112
112
113 /* like gather, but with no output list */
113 /* like gather, but with no output list */
114 static int discard(struct mpatch_flist *src, int cut, int offset)
114 static int discard(struct mpatch_flist *src, int cut, int offset)
115 {
115 {
116 struct mpatch_frag *s = src->head;
116 struct mpatch_frag *s = src->head;
117 int postend, c, l;
117 int postend, c, l;
118
118
119 while (s != src->tail) {
119 while (s != src->tail) {
120 if (s->start + offset >= cut)
120 if (s->start + offset >= cut)
121 break;
121 break;
122
122
123 postend = offset + s->start + s->len;
123 postend = offset + s->start + s->len;
124 if (postend <= cut) {
124 if (postend <= cut) {
125 offset += s->start + s->len - s->end;
125 offset += s->start + s->len - s->end;
126 s++;
126 s++;
127 }
127 }
128 else {
128 else {
129 c = cut - offset;
129 c = cut - offset;
130 if (s->end < c)
130 if (s->end < c)
131 c = s->end;
131 c = s->end;
132 l = cut - offset - s->start;
132 l = cut - offset - s->start;
133 if (s->len < l)
133 if (s->len < l)
134 l = s->len;
134 l = s->len;
135
135
136 offset += s->start + l - c;
136 offset += s->start + l - c;
137 s->start = c;
137 s->start = c;
138 s->len = s->len - l;
138 s->len = s->len - l;
139 s->data = s->data + l;
139 s->data = s->data + l;
140
140
141 break;
141 break;
142 }
142 }
143 }
143 }
144
144
145 src->head = s;
145 src->head = s;
146 return offset;
146 return offset;
147 }
147 }
148
148
149 /* combine hunk lists a and b, while adjusting b for offset changes in a/
149 /* combine hunk lists a and b, while adjusting b for offset changes in a/
150 this deletes a and b and returns the resultant list. */
150 this deletes a and b and returns the resultant list. */
151 static struct mpatch_flist *combine(struct mpatch_flist *a,
151 static struct mpatch_flist *combine(struct mpatch_flist *a,
152 struct mpatch_flist *b)
152 struct mpatch_flist *b)
153 {
153 {
154 struct mpatch_flist *c = NULL;
154 struct mpatch_flist *c = NULL;
155 struct mpatch_frag *bh, *ct;
155 struct mpatch_frag *bh, *ct;
156 int offset = 0, post;
156 int offset = 0, post;
157
157
158 if (a && b)
158 if (a && b)
159 c = lalloc((lsize(a) + lsize(b)) * 2);
159 c = lalloc((lsize(a) + lsize(b)) * 2);
160
160
161 if (c) {
161 if (c) {
162
162
163 for (bh = b->head; bh != b->tail; bh++) {
163 for (bh = b->head; bh != b->tail; bh++) {
164 /* save old hunks */
164 /* save old hunks */
165 offset = gather(c, a, bh->start, offset);
165 offset = gather(c, a, bh->start, offset);
166
166
167 /* discard replaced hunks */
167 /* discard replaced hunks */
168 post = discard(a, bh->end, offset);
168 post = discard(a, bh->end, offset);
169
169
170 /* insert new hunk */
170 /* insert new hunk */
171 ct = c->tail;
171 ct = c->tail;
172 ct->start = bh->start - offset;
172 ct->start = bh->start - offset;
173 ct->end = bh->end - post;
173 ct->end = bh->end - post;
174 ct->len = bh->len;
174 ct->len = bh->len;
175 ct->data = bh->data;
175 ct->data = bh->data;
176 c->tail++;
176 c->tail++;
177 offset = post;
177 offset = post;
178 }
178 }
179
179
180 /* hold on to tail from a */
180 /* hold on to tail from a */
181 memcpy(c->tail, a->head, sizeof(struct mpatch_frag) * lsize(a));
181 memcpy(c->tail, a->head, sizeof(struct mpatch_frag) * lsize(a));
182 c->tail += lsize(a);
182 c->tail += lsize(a);
183 }
183 }
184
184
185 mpatch_lfree(a);
185 mpatch_lfree(a);
186 mpatch_lfree(b);
186 mpatch_lfree(b);
187 return c;
187 return c;
188 }
188 }
189
189
190 /* decode a binary patch into a hunk list */
190 /* decode a binary patch into a hunk list */
191 int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist **res)
191 int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist **res)
192 {
192 {
193 struct mpatch_flist *l;
193 struct mpatch_flist *l;
194 struct mpatch_frag *lt;
194 struct mpatch_frag *lt;
195 int pos = 0;
195 int pos = 0;
196
196
197 /* assume worst case size, we won't have many of these lists */
197 /* assume worst case size, we won't have many of these lists */
198 l = lalloc(len / 12 + 1);
198 l = lalloc(len / 12 + 1);
199 if (!l)
199 if (!l)
200 return MPATCH_ERR_NO_MEM;
200 return MPATCH_ERR_NO_MEM;
201
201
202 lt = l->tail;
202 lt = l->tail;
203
203
204 while (pos >= 0 && pos < len) {
204 while (pos >= 0 && pos < len) {
205 lt->start = getbe32(bin + pos);
205 lt->start = getbe32(bin + pos);
206 lt->end = getbe32(bin + pos + 4);
206 lt->end = getbe32(bin + pos + 4);
207 lt->len = getbe32(bin + pos + 8);
207 lt->len = getbe32(bin + pos + 8);
208 lt->data = bin + pos + 12;
208 lt->data = bin + pos + 12;
209 pos += 12 + lt->len;
209 pos += 12 + lt->len;
210 if (lt->start > lt->end || lt->len < 0)
210 if (lt->start > lt->end || lt->len < 0)
211 break; /* sanity check */
211 break; /* sanity check */
212 lt++;
212 lt++;
213 }
213 }
214
214
215 if (pos != len) {
215 if (pos != len) {
216 mpatch_lfree(l);
216 mpatch_lfree(l);
217 return MPATCH_ERR_CANNOT_BE_DECODED;
217 return MPATCH_ERR_CANNOT_BE_DECODED;
218 }
218 }
219
219
220 l->tail = lt;
220 l->tail = lt;
221 *res = l;
221 *res = l;
222 return 0;
222 return 0;
223 }
223 }
224
224
225 /* calculate the size of resultant text */
225 /* calculate the size of resultant text */
226 ssize_t mpatch_calcsize(ssize_t len, struct mpatch_flist *l)
226 ssize_t mpatch_calcsize(ssize_t len, struct mpatch_flist *l)
227 {
227 {
228 ssize_t outlen = 0, last = 0;
228 ssize_t outlen = 0, last = 0;
229 struct mpatch_frag *f = l->head;
229 struct mpatch_frag *f = l->head;
230
230
231 while (f != l->tail) {
231 while (f != l->tail) {
232 if (f->start < last || f->end > len) {
232 if (f->start < last || f->end > len) {
233 return MPATCH_ERR_INVALID_PATCH;
233 return MPATCH_ERR_INVALID_PATCH;
234 }
234 }
235 outlen += f->start - last;
235 outlen += f->start - last;
236 last = f->end;
236 last = f->end;
237 outlen += f->len;
237 outlen += f->len;
238 f++;
238 f++;
239 }
239 }
240
240
241 outlen += len - last;
241 outlen += len - last;
242 return outlen;
242 return outlen;
243 }
243 }
244
244
245 int mpatch_apply(char *buf, const char *orig, ssize_t len,
245 int mpatch_apply(char *buf, const char *orig, ssize_t len,
246 struct mpatch_flist *l)
246 struct mpatch_flist *l)
247 {
247 {
248 struct mpatch_frag *f = l->head;
248 struct mpatch_frag *f = l->head;
249 int last = 0;
249 int last = 0;
250 char *p = buf;
250 char *p = buf;
251
251
252 while (f != l->tail) {
252 while (f != l->tail) {
253 if (f->start < last || f->end > len) {
253 if (f->start < last || f->end > len) {
254 return MPATCH_ERR_INVALID_PATCH;
254 return MPATCH_ERR_INVALID_PATCH;
255 }
255 }
256 memcpy(p, orig + last, f->start - last);
256 memcpy(p, orig + last, f->start - last);
257 p += f->start - last;
257 p += f->start - last;
258 memcpy(p, f->data, f->len);
258 memcpy(p, f->data, f->len);
259 last = f->end;
259 last = f->end;
260 p += f->len;
260 p += f->len;
261 f++;
261 f++;
262 }
262 }
263 memcpy(p, orig + last, len - last);
263 memcpy(p, orig + last, len - last);
264 return 0;
264 return 0;
265 }
265 }
266
266
267 /* recursively generate a patch of all bins between start and end */
267 /* recursively generate a patch of all bins between start and end */
268 struct mpatch_flist *mpatch_fold(void *bins,
268 struct mpatch_flist *mpatch_fold(void *bins,
269 struct mpatch_flist* (*get_next_item)(void*, ssize_t),
269 struct mpatch_flist* (*get_next_item)(void*, ssize_t),
270 ssize_t start, ssize_t end)
270 ssize_t start, ssize_t end)
271 {
271 {
272 ssize_t len;
272 ssize_t len;
273
273
274 if (start + 1 == end) {
274 if (start + 1 == end) {
275 /* trivial case, output a decoded list */
275 /* trivial case, output a decoded list */
276 return get_next_item(bins, start);
276 return get_next_item(bins, start);
277 }
277 }
278
278
279 /* divide and conquer, memory management is elsewhere */
279 /* divide and conquer, memory management is elsewhere */
280 len = (end - start) / 2;
280 len = (end - start) / 2;
281 return combine(mpatch_fold(bins, get_next_item, start, start + len),
281 return combine(mpatch_fold(bins, get_next_item, start, start + len),
282 mpatch_fold(bins, get_next_item, start + len, end));
282 mpatch_fold(bins, get_next_item, start + len, end));
283 }
283 }
284
@@ -1,180 +1,180 b''
1 /*
1 /*
2 mpatch.c - efficient binary patching for Mercurial
2 mpatch.c - efficient binary patching for Mercurial
3
3
4 This implements a patch algorithm that's O(m + nlog n) where m is the
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.
5 size of the output and n is the number of patches.
6
6
7 Given a list of binary patches, it unpacks each into a hunk list,
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
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
9 single hunk list. This hunk list is then applied to the original
10 text.
10 text.
11
11
12 The text (or binary) fragments are copied directly from their source
12 The text (or binary) fragments are copied directly from their source
13 Python objects into a preallocated output string to avoid the
13 Python objects into a preallocated output string to avoid the
14 allocation of intermediate Python objects. Working memory is about 2x
14 allocation of intermediate Python objects. Working memory is about 2x
15 the total number of hunks.
15 the total number of hunks.
16
16
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
18
18
19 This software may be used and distributed according to the terms
19 This software may be used and distributed according to the terms
20 of the GNU General Public License, incorporated herein by reference.
20 of the GNU General Public License, incorporated herein by reference.
21 */
21 */
22
22
23 #define PY_SSIZE_T_CLEAN
23 #define PY_SSIZE_T_CLEAN
24 #include <Python.h>
24 #include <Python.h>
25 #include <stdlib.h>
25 #include <stdlib.h>
26 #include <string.h>
26 #include <string.h>
27
27
28 #include "util.h"
28 #include "util.h"
29 #include "bitmanipulation.h"
29 #include "bitmanipulation.h"
30 #include "compat.h"
30 #include "compat.h"
31 #include "mpatch.h"
31 #include "mpatch.h"
32
32
33 static char mpatch_doc[] = "Efficient binary patching.";
33 static char mpatch_doc[] = "Efficient binary patching.";
34 static PyObject *mpatch_Error;
34 static PyObject *mpatch_Error;
35
35
36 struct mpatch_flist *cpygetitem(void *bins, ssize_t pos)
36 struct mpatch_flist *cpygetitem(void *bins, ssize_t pos)
37 {
37 {
38 const char *buffer;
38 const char *buffer;
39 struct mpatch_flist *res;
39 struct mpatch_flist *res;
40 ssize_t blen;
40 ssize_t blen;
41 int r;
41 int r;
42
42
43 PyObject *tmp = PyList_GetItem((PyObject*)bins, pos);
43 PyObject *tmp = PyList_GetItem((PyObject*)bins, pos);
44 if (!tmp)
44 if (!tmp)
45 return NULL;
45 return NULL;
46 if (PyObject_AsCharBuffer(tmp, &buffer, (Py_ssize_t*)&blen))
46 if (PyObject_AsCharBuffer(tmp, &buffer, (Py_ssize_t*)&blen))
47 return NULL;
47 return NULL;
48 if ((r = mpatch_decode(buffer, blen, &res)) < 0) {
48 if ((r = mpatch_decode(buffer, blen, &res)) < 0) {
49 if (!PyErr_Occurred())
49 if (!PyErr_Occurred())
50 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
50 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
51 return NULL;
51 return NULL;
52 }
52 }
53 return res;
53 return res;
54 }
54 }
55
55
56 static PyObject *
56 static PyObject *
57 patches(PyObject *self, PyObject *args)
57 patches(PyObject *self, PyObject *args)
58 {
58 {
59 PyObject *text, *bins, *result;
59 PyObject *text, *bins, *result;
60 struct mpatch_flist *patch;
60 struct mpatch_flist *patch;
61 const char *in;
61 const char *in;
62 int r;
62 int r;
63 char *out;
63 char *out;
64 Py_ssize_t len, outlen, inlen;
64 Py_ssize_t len, outlen, inlen;
65
65
66 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
66 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
67 return NULL;
67 return NULL;
68
68
69 len = PyList_Size(bins);
69 len = PyList_Size(bins);
70 if (!len) {
70 if (!len) {
71 /* nothing to do */
71 /* nothing to do */
72 Py_INCREF(text);
72 Py_INCREF(text);
73 return text;
73 return text;
74 }
74 }
75
75
76 if (PyObject_AsCharBuffer(text, &in, &inlen))
76 if (PyObject_AsCharBuffer(text, &in, &inlen))
77 return NULL;
77 return NULL;
78
78
79 patch = mpatch_fold(bins, cpygetitem, 0, len);
79 patch = mpatch_fold(bins, cpygetitem, 0, len);
80 if (!patch) { /* error already set or memory error */
80 if (!patch) { /* error already set or memory error */
81 if (!PyErr_Occurred())
81 if (!PyErr_Occurred())
82 PyErr_NoMemory();
82 PyErr_NoMemory();
83 return NULL;
83 return NULL;
84 }
84 }
85
85
86 outlen = mpatch_calcsize(inlen, patch);
86 outlen = mpatch_calcsize(inlen, patch);
87 if (outlen < 0) {
87 if (outlen < 0) {
88 r = (int)outlen;
88 r = (int)outlen;
89 result = NULL;
89 result = NULL;
90 goto cleanup;
90 goto cleanup;
91 }
91 }
92 result = PyBytes_FromStringAndSize(NULL, outlen);
92 result = PyBytes_FromStringAndSize(NULL, outlen);
93 if (!result) {
93 if (!result) {
94 result = NULL;
94 result = NULL;
95 goto cleanup;
95 goto cleanup;
96 }
96 }
97 out = PyBytes_AsString(result);
97 out = PyBytes_AsString(result);
98 if ((r = mpatch_apply(out, in, inlen, patch)) < 0) {
98 if ((r = mpatch_apply(out, in, inlen, patch)) < 0) {
99 Py_DECREF(result);
99 Py_DECREF(result);
100 result = NULL;
100 result = NULL;
101 }
101 }
102 cleanup:
102 cleanup:
103 mpatch_lfree(patch);
103 mpatch_lfree(patch);
104 if (!result && !PyErr_Occurred())
104 if (!result && !PyErr_Occurred())
105 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
105 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
106 return result;
106 return result;
107 }
107 }
108
108
109 /* calculate size of a patched file directly */
109 /* calculate size of a patched file directly */
110 static PyObject *
110 static PyObject *
111 patchedsize(PyObject *self, PyObject *args)
111 patchedsize(PyObject *self, PyObject *args)
112 {
112 {
113 long orig, start, end, len, outlen = 0, last = 0, pos = 0;
113 long orig, start, end, len, outlen = 0, last = 0, pos = 0;
114 Py_ssize_t patchlen;
114 Py_ssize_t patchlen;
115 char *bin;
115 char *bin;
116
116
117 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
117 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
118 return NULL;
118 return NULL;
119
119
120 while (pos >= 0 && pos < patchlen) {
120 while (pos >= 0 && pos < patchlen) {
121 start = getbe32(bin + pos);
121 start = getbe32(bin + pos);
122 end = getbe32(bin + pos + 4);
122 end = getbe32(bin + pos + 4);
123 len = getbe32(bin + pos + 8);
123 len = getbe32(bin + pos + 8);
124 if (start > end)
124 if (start > end)
125 break; /* sanity check */
125 break; /* sanity check */
126 pos += 12 + len;
126 pos += 12 + len;
127 outlen += start - last;
127 outlen += start - last;
128 last = end;
128 last = end;
129 outlen += len;
129 outlen += len;
130 }
130 }
131
131
132 if (pos != patchlen) {
132 if (pos != patchlen) {
133 if (!PyErr_Occurred())
133 if (!PyErr_Occurred())
134 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
134 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
135 return NULL;
135 return NULL;
136 }
136 }
137
137
138 outlen += orig - last;
138 outlen += orig - last;
139 return Py_BuildValue("l", outlen);
139 return Py_BuildValue("l", outlen);
140 }
140 }
141
141
142 static PyMethodDef methods[] = {
142 static PyMethodDef methods[] = {
143 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},
143 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},
144 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"},
144 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"},
145 {NULL, NULL}
145 {NULL, NULL}
146 };
146 };
147
147
148 #ifdef IS_PY3K
148 #ifdef IS_PY3K
149 static struct PyModuleDef mpatch_module = {
149 static struct PyModuleDef mpatch_module = {
150 PyModuleDef_HEAD_INIT,
150 PyModuleDef_HEAD_INIT,
151 "mpatch",
151 "mpatch",
152 mpatch_doc,
152 mpatch_doc,
153 -1,
153 -1,
154 methods
154 methods
155 };
155 };
156
156
157 PyMODINIT_FUNC PyInit_mpatch(void)
157 PyMODINIT_FUNC PyInit_mpatch(void)
158 {
158 {
159 PyObject *m;
159 PyObject *m;
160
160
161 m = PyModule_Create(&mpatch_module);
161 m = PyModule_Create(&mpatch_module);
162 if (m == NULL)
162 if (m == NULL)
163 return NULL;
163 return NULL;
164
164
165 mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError",
165 mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError",
166 NULL, NULL);
166 NULL, NULL);
167 Py_INCREF(mpatch_Error);
167 Py_INCREF(mpatch_Error);
168 PyModule_AddObject(m, "mpatchError", mpatch_Error);
168 PyModule_AddObject(m, "mpatchError", mpatch_Error);
169
169
170 return m;
170 return m;
171 }
171 }
172 #else
172 #else
173 PyMODINIT_FUNC
173 PyMODINIT_FUNC
174 initmpatch(void)
174 initmpatch(void)
175 {
175 {
176 Py_InitModule3("mpatch", methods, mpatch_doc);
176 Py_InitModule3("mpatch", methods, mpatch_doc);
177 mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError",
177 mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError",
178 NULL, NULL);
178 NULL, NULL);
179 }
179 }
180 #endif
180 #endif
General Comments 0
You need to be logged in to leave comments. Login now