##// END OF EJS Templates
parsers: remove long-dead parse_manifest method...
Augie Fackler -
r41047:55d6d0ff default
parent child Browse files
Show More
@@ -1,797 +1,717 b''
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <ctype.h>
11 #include <ctype.h>
12 #include <stddef.h>
12 #include <stddef.h>
13 #include <string.h>
13 #include <string.h>
14
14
15 #include "bitmanipulation.h"
15 #include "bitmanipulation.h"
16 #include "charencode.h"
16 #include "charencode.h"
17 #include "util.h"
17 #include "util.h"
18
18
19 #ifdef IS_PY3K
19 #ifdef IS_PY3K
20 /* The mapping of Python types is meant to be temporary to get Python
20 /* The mapping of Python types is meant to be temporary to get Python
21 * 3 to compile. We should remove this once Python 3 support is fully
21 * 3 to compile. We should remove this once Python 3 support is fully
22 * supported and proper types are used in the extensions themselves. */
22 * supported and proper types are used in the extensions themselves. */
23 #define PyInt_Check PyLong_Check
23 #define PyInt_Check PyLong_Check
24 #define PyInt_FromLong PyLong_FromLong
24 #define PyInt_FromLong PyLong_FromLong
25 #define PyInt_FromSsize_t PyLong_FromSsize_t
25 #define PyInt_FromSsize_t PyLong_FromSsize_t
26 #define PyInt_AsLong PyLong_AsLong
26 #define PyInt_AsLong PyLong_AsLong
27 #endif
27 #endif
28
28
29 static const char *const versionerrortext = "Python minor version mismatch";
29 static const char *const versionerrortext = "Python minor version mismatch";
30
30
31 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
31 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
32 {
32 {
33 Py_ssize_t expected_size;
33 Py_ssize_t expected_size;
34
34
35 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size))
35 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size))
36 return NULL;
36 return NULL;
37
37
38 return _dict_new_presized(expected_size);
38 return _dict_new_presized(expected_size);
39 }
39 }
40
40
41 /*
42 * This code assumes that a manifest is stitched together with newline
43 * ('\n') characters.
44 */
45 static PyObject *parse_manifest(PyObject *self, PyObject *args)
46 {
47 PyObject *mfdict, *fdict;
48 char *str, *start, *end;
49 int len;
50
51 if (!PyArg_ParseTuple(
52 args, PY23("O!O!s#:parse_manifest", "O!O!y#:parse_manifest"),
53 &PyDict_Type, &mfdict, &PyDict_Type, &fdict, &str, &len))
54 goto quit;
55
56 start = str;
57 end = str + len;
58 while (start < end) {
59 PyObject *file = NULL, *node = NULL;
60 PyObject *flags = NULL;
61 char *zero = NULL, *newline = NULL;
62 ptrdiff_t nlen;
63
64 zero = memchr(start, '\0', end - start);
65 if (!zero) {
66 PyErr_SetString(PyExc_ValueError,
67 "manifest entry has no separator");
68 goto quit;
69 }
70
71 newline = memchr(zero + 1, '\n', end - (zero + 1));
72 if (!newline) {
73 PyErr_SetString(PyExc_ValueError,
74 "manifest contains trailing garbage");
75 goto quit;
76 }
77
78 file = PyBytes_FromStringAndSize(start, zero - start);
79
80 if (!file)
81 goto bail;
82
83 nlen = newline - zero - 1;
84
85 node = unhexlify(zero + 1, nlen > 40 ? 40 : (Py_ssize_t)nlen);
86 if (!node)
87 goto bail;
88
89 if (nlen > 40) {
90 flags = PyBytes_FromStringAndSize(zero + 41, nlen - 40);
91 if (!flags)
92 goto bail;
93
94 if (PyDict_SetItem(fdict, file, flags) == -1)
95 goto bail;
96 }
97
98 if (PyDict_SetItem(mfdict, file, node) == -1)
99 goto bail;
100
101 start = newline + 1;
102
103 Py_XDECREF(flags);
104 Py_XDECREF(node);
105 Py_XDECREF(file);
106 continue;
107 bail:
108 Py_XDECREF(flags);
109 Py_XDECREF(node);
110 Py_XDECREF(file);
111 goto quit;
112 }
113
114 Py_INCREF(Py_None);
115 return Py_None;
116 quit:
117 return NULL;
118 }
119
120 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
41 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
121 int size, int mtime)
42 int size, int mtime)
122 {
43 {
123 dirstateTupleObject *t =
44 dirstateTupleObject *t =
124 PyObject_New(dirstateTupleObject, &dirstateTupleType);
45 PyObject_New(dirstateTupleObject, &dirstateTupleType);
125 if (!t)
46 if (!t)
126 return NULL;
47 return NULL;
127 t->state = state;
48 t->state = state;
128 t->mode = mode;
49 t->mode = mode;
129 t->size = size;
50 t->size = size;
130 t->mtime = mtime;
51 t->mtime = mtime;
131 return t;
52 return t;
132 }
53 }
133
54
134 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
55 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
135 PyObject *kwds)
56 PyObject *kwds)
136 {
57 {
137 /* We do all the initialization here and not a tp_init function because
58 /* We do all the initialization here and not a tp_init function because
138 * dirstate_tuple is immutable. */
59 * dirstate_tuple is immutable. */
139 dirstateTupleObject *t;
60 dirstateTupleObject *t;
140 char state;
61 char state;
141 int size, mode, mtime;
62 int size, mode, mtime;
142 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
63 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
143 return NULL;
64 return NULL;
144
65
145 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
66 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
146 if (!t)
67 if (!t)
147 return NULL;
68 return NULL;
148 t->state = state;
69 t->state = state;
149 t->mode = mode;
70 t->mode = mode;
150 t->size = size;
71 t->size = size;
151 t->mtime = mtime;
72 t->mtime = mtime;
152
73
153 return (PyObject *)t;
74 return (PyObject *)t;
154 }
75 }
155
76
156 static void dirstate_tuple_dealloc(PyObject *o)
77 static void dirstate_tuple_dealloc(PyObject *o)
157 {
78 {
158 PyObject_Del(o);
79 PyObject_Del(o);
159 }
80 }
160
81
161 static Py_ssize_t dirstate_tuple_length(PyObject *o)
82 static Py_ssize_t dirstate_tuple_length(PyObject *o)
162 {
83 {
163 return 4;
84 return 4;
164 }
85 }
165
86
166 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
87 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
167 {
88 {
168 dirstateTupleObject *t = (dirstateTupleObject *)o;
89 dirstateTupleObject *t = (dirstateTupleObject *)o;
169 switch (i) {
90 switch (i) {
170 case 0:
91 case 0:
171 return PyBytes_FromStringAndSize(&t->state, 1);
92 return PyBytes_FromStringAndSize(&t->state, 1);
172 case 1:
93 case 1:
173 return PyInt_FromLong(t->mode);
94 return PyInt_FromLong(t->mode);
174 case 2:
95 case 2:
175 return PyInt_FromLong(t->size);
96 return PyInt_FromLong(t->size);
176 case 3:
97 case 3:
177 return PyInt_FromLong(t->mtime);
98 return PyInt_FromLong(t->mtime);
178 default:
99 default:
179 PyErr_SetString(PyExc_IndexError, "index out of range");
100 PyErr_SetString(PyExc_IndexError, "index out of range");
180 return NULL;
101 return NULL;
181 }
102 }
182 }
103 }
183
104
184 static PySequenceMethods dirstate_tuple_sq = {
105 static PySequenceMethods dirstate_tuple_sq = {
185 dirstate_tuple_length, /* sq_length */
106 dirstate_tuple_length, /* sq_length */
186 0, /* sq_concat */
107 0, /* sq_concat */
187 0, /* sq_repeat */
108 0, /* sq_repeat */
188 dirstate_tuple_item, /* sq_item */
109 dirstate_tuple_item, /* sq_item */
189 0, /* sq_ass_item */
110 0, /* sq_ass_item */
190 0, /* sq_contains */
111 0, /* sq_contains */
191 0, /* sq_inplace_concat */
112 0, /* sq_inplace_concat */
192 0 /* sq_inplace_repeat */
113 0 /* sq_inplace_repeat */
193 };
114 };
194
115
195 PyTypeObject dirstateTupleType = {
116 PyTypeObject dirstateTupleType = {
196 PyVarObject_HEAD_INIT(NULL, 0) /* header */
117 PyVarObject_HEAD_INIT(NULL, 0) /* header */
197 "dirstate_tuple", /* tp_name */
118 "dirstate_tuple", /* tp_name */
198 sizeof(dirstateTupleObject), /* tp_basicsize */
119 sizeof(dirstateTupleObject), /* tp_basicsize */
199 0, /* tp_itemsize */
120 0, /* tp_itemsize */
200 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
121 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
201 0, /* tp_print */
122 0, /* tp_print */
202 0, /* tp_getattr */
123 0, /* tp_getattr */
203 0, /* tp_setattr */
124 0, /* tp_setattr */
204 0, /* tp_compare */
125 0, /* tp_compare */
205 0, /* tp_repr */
126 0, /* tp_repr */
206 0, /* tp_as_number */
127 0, /* tp_as_number */
207 &dirstate_tuple_sq, /* tp_as_sequence */
128 &dirstate_tuple_sq, /* tp_as_sequence */
208 0, /* tp_as_mapping */
129 0, /* tp_as_mapping */
209 0, /* tp_hash */
130 0, /* tp_hash */
210 0, /* tp_call */
131 0, /* tp_call */
211 0, /* tp_str */
132 0, /* tp_str */
212 0, /* tp_getattro */
133 0, /* tp_getattro */
213 0, /* tp_setattro */
134 0, /* tp_setattro */
214 0, /* tp_as_buffer */
135 0, /* tp_as_buffer */
215 Py_TPFLAGS_DEFAULT, /* tp_flags */
136 Py_TPFLAGS_DEFAULT, /* tp_flags */
216 "dirstate tuple", /* tp_doc */
137 "dirstate tuple", /* tp_doc */
217 0, /* tp_traverse */
138 0, /* tp_traverse */
218 0, /* tp_clear */
139 0, /* tp_clear */
219 0, /* tp_richcompare */
140 0, /* tp_richcompare */
220 0, /* tp_weaklistoffset */
141 0, /* tp_weaklistoffset */
221 0, /* tp_iter */
142 0, /* tp_iter */
222 0, /* tp_iternext */
143 0, /* tp_iternext */
223 0, /* tp_methods */
144 0, /* tp_methods */
224 0, /* tp_members */
145 0, /* tp_members */
225 0, /* tp_getset */
146 0, /* tp_getset */
226 0, /* tp_base */
147 0, /* tp_base */
227 0, /* tp_dict */
148 0, /* tp_dict */
228 0, /* tp_descr_get */
149 0, /* tp_descr_get */
229 0, /* tp_descr_set */
150 0, /* tp_descr_set */
230 0, /* tp_dictoffset */
151 0, /* tp_dictoffset */
231 0, /* tp_init */
152 0, /* tp_init */
232 0, /* tp_alloc */
153 0, /* tp_alloc */
233 dirstate_tuple_new, /* tp_new */
154 dirstate_tuple_new, /* tp_new */
234 };
155 };
235
156
236 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
157 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
237 {
158 {
238 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
159 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
239 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
160 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
240 char state, *cur, *str, *cpos;
161 char state, *cur, *str, *cpos;
241 int mode, size, mtime;
162 int mode, size, mtime;
242 unsigned int flen, len, pos = 40;
163 unsigned int flen, len, pos = 40;
243 int readlen;
164 int readlen;
244
165
245 if (!PyArg_ParseTuple(
166 if (!PyArg_ParseTuple(
246 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
167 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
247 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen))
168 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen))
248 goto quit;
169 goto quit;
249
170
250 len = readlen;
171 len = readlen;
251
172
252 /* read parents */
173 /* read parents */
253 if (len < 40) {
174 if (len < 40) {
254 PyErr_SetString(PyExc_ValueError,
175 PyErr_SetString(PyExc_ValueError,
255 "too little data for parents");
176 "too little data for parents");
256 goto quit;
177 goto quit;
257 }
178 }
258
179
259 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20);
180 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20);
260 if (!parents)
181 if (!parents)
261 goto quit;
182 goto quit;
262
183
263 /* read filenames */
184 /* read filenames */
264 while (pos >= 40 && pos < len) {
185 while (pos >= 40 && pos < len) {
265 if (pos + 17 > len) {
186 if (pos + 17 > len) {
266 PyErr_SetString(PyExc_ValueError,
187 PyErr_SetString(PyExc_ValueError,
267 "overflow in dirstate");
188 "overflow in dirstate");
268 goto quit;
189 goto quit;
269 }
190 }
270 cur = str + pos;
191 cur = str + pos;
271 /* unpack header */
192 /* unpack header */
272 state = *cur;
193 state = *cur;
273 mode = getbe32(cur + 1);
194 mode = getbe32(cur + 1);
274 size = getbe32(cur + 5);
195 size = getbe32(cur + 5);
275 mtime = getbe32(cur + 9);
196 mtime = getbe32(cur + 9);
276 flen = getbe32(cur + 13);
197 flen = getbe32(cur + 13);
277 pos += 17;
198 pos += 17;
278 cur += 17;
199 cur += 17;
279 if (flen > len - pos) {
200 if (flen > len - pos) {
280 PyErr_SetString(PyExc_ValueError,
201 PyErr_SetString(PyExc_ValueError,
281 "overflow in dirstate");
202 "overflow in dirstate");
282 goto quit;
203 goto quit;
283 }
204 }
284
205
285 entry =
206 entry =
286 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
207 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
287 cpos = memchr(cur, 0, flen);
208 cpos = memchr(cur, 0, flen);
288 if (cpos) {
209 if (cpos) {
289 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
210 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
290 cname = PyBytes_FromStringAndSize(
211 cname = PyBytes_FromStringAndSize(
291 cpos + 1, flen - (cpos - cur) - 1);
212 cpos + 1, flen - (cpos - cur) - 1);
292 if (!fname || !cname ||
213 if (!fname || !cname ||
293 PyDict_SetItem(cmap, fname, cname) == -1 ||
214 PyDict_SetItem(cmap, fname, cname) == -1 ||
294 PyDict_SetItem(dmap, fname, entry) == -1)
215 PyDict_SetItem(dmap, fname, entry) == -1)
295 goto quit;
216 goto quit;
296 Py_DECREF(cname);
217 Py_DECREF(cname);
297 } else {
218 } else {
298 fname = PyBytes_FromStringAndSize(cur, flen);
219 fname = PyBytes_FromStringAndSize(cur, flen);
299 if (!fname || PyDict_SetItem(dmap, fname, entry) == -1)
220 if (!fname || PyDict_SetItem(dmap, fname, entry) == -1)
300 goto quit;
221 goto quit;
301 }
222 }
302 Py_DECREF(fname);
223 Py_DECREF(fname);
303 Py_DECREF(entry);
224 Py_DECREF(entry);
304 fname = cname = entry = NULL;
225 fname = cname = entry = NULL;
305 pos += flen;
226 pos += flen;
306 }
227 }
307
228
308 ret = parents;
229 ret = parents;
309 Py_INCREF(ret);
230 Py_INCREF(ret);
310 quit:
231 quit:
311 Py_XDECREF(fname);
232 Py_XDECREF(fname);
312 Py_XDECREF(cname);
233 Py_XDECREF(cname);
313 Py_XDECREF(entry);
234 Py_XDECREF(entry);
314 Py_XDECREF(parents);
235 Py_XDECREF(parents);
315 return ret;
236 return ret;
316 }
237 }
317
238
318 /*
239 /*
319 * Build a set of non-normal and other parent entries from the dirstate dmap
240 * Build a set of non-normal and other parent entries from the dirstate dmap
320 */
241 */
321 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
242 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
322 {
243 {
323 PyObject *dmap, *fname, *v;
244 PyObject *dmap, *fname, *v;
324 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
245 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
325 Py_ssize_t pos;
246 Py_ssize_t pos;
326
247
327 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, &dmap))
248 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, &dmap))
328 goto bail;
249 goto bail;
329
250
330 nonnset = PySet_New(NULL);
251 nonnset = PySet_New(NULL);
331 if (nonnset == NULL)
252 if (nonnset == NULL)
332 goto bail;
253 goto bail;
333
254
334 otherpset = PySet_New(NULL);
255 otherpset = PySet_New(NULL);
335 if (otherpset == NULL)
256 if (otherpset == NULL)
336 goto bail;
257 goto bail;
337
258
338 pos = 0;
259 pos = 0;
339 while (PyDict_Next(dmap, &pos, &fname, &v)) {
260 while (PyDict_Next(dmap, &pos, &fname, &v)) {
340 dirstateTupleObject *t;
261 dirstateTupleObject *t;
341 if (!dirstate_tuple_check(v)) {
262 if (!dirstate_tuple_check(v)) {
342 PyErr_SetString(PyExc_TypeError,
263 PyErr_SetString(PyExc_TypeError,
343 "expected a dirstate tuple");
264 "expected a dirstate tuple");
344 goto bail;
265 goto bail;
345 }
266 }
346 t = (dirstateTupleObject *)v;
267 t = (dirstateTupleObject *)v;
347
268
348 if (t->state == 'n' && t->size == -2) {
269 if (t->state == 'n' && t->size == -2) {
349 if (PySet_Add(otherpset, fname) == -1) {
270 if (PySet_Add(otherpset, fname) == -1) {
350 goto bail;
271 goto bail;
351 }
272 }
352 }
273 }
353
274
354 if (t->state == 'n' && t->mtime != -1)
275 if (t->state == 'n' && t->mtime != -1)
355 continue;
276 continue;
356 if (PySet_Add(nonnset, fname) == -1)
277 if (PySet_Add(nonnset, fname) == -1)
357 goto bail;
278 goto bail;
358 }
279 }
359
280
360 result = Py_BuildValue("(OO)", nonnset, otherpset);
281 result = Py_BuildValue("(OO)", nonnset, otherpset);
361 if (result == NULL)
282 if (result == NULL)
362 goto bail;
283 goto bail;
363 Py_DECREF(nonnset);
284 Py_DECREF(nonnset);
364 Py_DECREF(otherpset);
285 Py_DECREF(otherpset);
365 return result;
286 return result;
366 bail:
287 bail:
367 Py_XDECREF(nonnset);
288 Py_XDECREF(nonnset);
368 Py_XDECREF(otherpset);
289 Py_XDECREF(otherpset);
369 Py_XDECREF(result);
290 Py_XDECREF(result);
370 return NULL;
291 return NULL;
371 }
292 }
372
293
373 /*
294 /*
374 * Efficiently pack a dirstate object into its on-disk format.
295 * Efficiently pack a dirstate object into its on-disk format.
375 */
296 */
376 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
297 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
377 {
298 {
378 PyObject *packobj = NULL;
299 PyObject *packobj = NULL;
379 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
300 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
380 Py_ssize_t nbytes, pos, l;
301 Py_ssize_t nbytes, pos, l;
381 PyObject *k, *v = NULL, *pn;
302 PyObject *k, *v = NULL, *pn;
382 char *p, *s;
303 char *p, *s;
383 int now;
304 int now;
384
305
385 if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
306 if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
386 &PyDict_Type, &copymap, &PyTuple_Type, &pl, &now))
307 &PyDict_Type, &copymap, &PyTuple_Type, &pl, &now))
387 return NULL;
308 return NULL;
388
309
389 if (PyTuple_Size(pl) != 2) {
310 if (PyTuple_Size(pl) != 2) {
390 PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
311 PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
391 return NULL;
312 return NULL;
392 }
313 }
393
314
394 /* Figure out how much we need to allocate. */
315 /* Figure out how much we need to allocate. */
395 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
316 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
396 PyObject *c;
317 PyObject *c;
397 if (!PyBytes_Check(k)) {
318 if (!PyBytes_Check(k)) {
398 PyErr_SetString(PyExc_TypeError, "expected string key");
319 PyErr_SetString(PyExc_TypeError, "expected string key");
399 goto bail;
320 goto bail;
400 }
321 }
401 nbytes += PyBytes_GET_SIZE(k) + 17;
322 nbytes += PyBytes_GET_SIZE(k) + 17;
402 c = PyDict_GetItem(copymap, k);
323 c = PyDict_GetItem(copymap, k);
403 if (c) {
324 if (c) {
404 if (!PyBytes_Check(c)) {
325 if (!PyBytes_Check(c)) {
405 PyErr_SetString(PyExc_TypeError,
326 PyErr_SetString(PyExc_TypeError,
406 "expected string key");
327 "expected string key");
407 goto bail;
328 goto bail;
408 }
329 }
409 nbytes += PyBytes_GET_SIZE(c) + 1;
330 nbytes += PyBytes_GET_SIZE(c) + 1;
410 }
331 }
411 }
332 }
412
333
413 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
334 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
414 if (packobj == NULL)
335 if (packobj == NULL)
415 goto bail;
336 goto bail;
416
337
417 p = PyBytes_AS_STRING(packobj);
338 p = PyBytes_AS_STRING(packobj);
418
339
419 pn = PyTuple_GET_ITEM(pl, 0);
340 pn = PyTuple_GET_ITEM(pl, 0);
420 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
341 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
421 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
342 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
422 goto bail;
343 goto bail;
423 }
344 }
424 memcpy(p, s, l);
345 memcpy(p, s, l);
425 p += 20;
346 p += 20;
426 pn = PyTuple_GET_ITEM(pl, 1);
347 pn = PyTuple_GET_ITEM(pl, 1);
427 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
348 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
428 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
349 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
429 goto bail;
350 goto bail;
430 }
351 }
431 memcpy(p, s, l);
352 memcpy(p, s, l);
432 p += 20;
353 p += 20;
433
354
434 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
355 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
435 dirstateTupleObject *tuple;
356 dirstateTupleObject *tuple;
436 char state;
357 char state;
437 int mode, size, mtime;
358 int mode, size, mtime;
438 Py_ssize_t len, l;
359 Py_ssize_t len, l;
439 PyObject *o;
360 PyObject *o;
440 char *t;
361 char *t;
441
362
442 if (!dirstate_tuple_check(v)) {
363 if (!dirstate_tuple_check(v)) {
443 PyErr_SetString(PyExc_TypeError,
364 PyErr_SetString(PyExc_TypeError,
444 "expected a dirstate tuple");
365 "expected a dirstate tuple");
445 goto bail;
366 goto bail;
446 }
367 }
447 tuple = (dirstateTupleObject *)v;
368 tuple = (dirstateTupleObject *)v;
448
369
449 state = tuple->state;
370 state = tuple->state;
450 mode = tuple->mode;
371 mode = tuple->mode;
451 size = tuple->size;
372 size = tuple->size;
452 mtime = tuple->mtime;
373 mtime = tuple->mtime;
453 if (state == 'n' && mtime == now) {
374 if (state == 'n' && mtime == now) {
454 /* See pure/parsers.py:pack_dirstate for why we do
375 /* See pure/parsers.py:pack_dirstate for why we do
455 * this. */
376 * this. */
456 mtime = -1;
377 mtime = -1;
457 mtime_unset = (PyObject *)make_dirstate_tuple(
378 mtime_unset = (PyObject *)make_dirstate_tuple(
458 state, mode, size, mtime);
379 state, mode, size, mtime);
459 if (!mtime_unset)
380 if (!mtime_unset)
460 goto bail;
381 goto bail;
461 if (PyDict_SetItem(map, k, mtime_unset) == -1)
382 if (PyDict_SetItem(map, k, mtime_unset) == -1)
462 goto bail;
383 goto bail;
463 Py_DECREF(mtime_unset);
384 Py_DECREF(mtime_unset);
464 mtime_unset = NULL;
385 mtime_unset = NULL;
465 }
386 }
466 *p++ = state;
387 *p++ = state;
467 putbe32((uint32_t)mode, p);
388 putbe32((uint32_t)mode, p);
468 putbe32((uint32_t)size, p + 4);
389 putbe32((uint32_t)size, p + 4);
469 putbe32((uint32_t)mtime, p + 8);
390 putbe32((uint32_t)mtime, p + 8);
470 t = p + 12;
391 t = p + 12;
471 p += 16;
392 p += 16;
472 len = PyBytes_GET_SIZE(k);
393 len = PyBytes_GET_SIZE(k);
473 memcpy(p, PyBytes_AS_STRING(k), len);
394 memcpy(p, PyBytes_AS_STRING(k), len);
474 p += len;
395 p += len;
475 o = PyDict_GetItem(copymap, k);
396 o = PyDict_GetItem(copymap, k);
476 if (o) {
397 if (o) {
477 *p++ = '\0';
398 *p++ = '\0';
478 l = PyBytes_GET_SIZE(o);
399 l = PyBytes_GET_SIZE(o);
479 memcpy(p, PyBytes_AS_STRING(o), l);
400 memcpy(p, PyBytes_AS_STRING(o), l);
480 p += l;
401 p += l;
481 len += l + 1;
402 len += l + 1;
482 }
403 }
483 putbe32((uint32_t)len, t);
404 putbe32((uint32_t)len, t);
484 }
405 }
485
406
486 pos = p - PyBytes_AS_STRING(packobj);
407 pos = p - PyBytes_AS_STRING(packobj);
487 if (pos != nbytes) {
408 if (pos != nbytes) {
488 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
409 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
489 (long)pos, (long)nbytes);
410 (long)pos, (long)nbytes);
490 goto bail;
411 goto bail;
491 }
412 }
492
413
493 return packobj;
414 return packobj;
494 bail:
415 bail:
495 Py_XDECREF(mtime_unset);
416 Py_XDECREF(mtime_unset);
496 Py_XDECREF(packobj);
417 Py_XDECREF(packobj);
497 Py_XDECREF(v);
418 Py_XDECREF(v);
498 return NULL;
419 return NULL;
499 }
420 }
500
421
501 #define BUMPED_FIX 1
422 #define BUMPED_FIX 1
502 #define USING_SHA_256 2
423 #define USING_SHA_256 2
503 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
424 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
504
425
505 static PyObject *readshas(const char *source, unsigned char num,
426 static PyObject *readshas(const char *source, unsigned char num,
506 Py_ssize_t hashwidth)
427 Py_ssize_t hashwidth)
507 {
428 {
508 int i;
429 int i;
509 PyObject *list = PyTuple_New(num);
430 PyObject *list = PyTuple_New(num);
510 if (list == NULL) {
431 if (list == NULL) {
511 return NULL;
432 return NULL;
512 }
433 }
513 for (i = 0; i < num; i++) {
434 for (i = 0; i < num; i++) {
514 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
435 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
515 if (hash == NULL) {
436 if (hash == NULL) {
516 Py_DECREF(list);
437 Py_DECREF(list);
517 return NULL;
438 return NULL;
518 }
439 }
519 PyTuple_SET_ITEM(list, i, hash);
440 PyTuple_SET_ITEM(list, i, hash);
520 source += hashwidth;
441 source += hashwidth;
521 }
442 }
522 return list;
443 return list;
523 }
444 }
524
445
525 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
446 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
526 uint32_t *msize)
447 uint32_t *msize)
527 {
448 {
528 const char *data = databegin;
449 const char *data = databegin;
529 const char *meta;
450 const char *meta;
530
451
531 double mtime;
452 double mtime;
532 int16_t tz;
453 int16_t tz;
533 uint16_t flags;
454 uint16_t flags;
534 unsigned char nsuccs, nparents, nmetadata;
455 unsigned char nsuccs, nparents, nmetadata;
535 Py_ssize_t hashwidth = 20;
456 Py_ssize_t hashwidth = 20;
536
457
537 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
458 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
538 PyObject *metadata = NULL, *ret = NULL;
459 PyObject *metadata = NULL, *ret = NULL;
539 int i;
460 int i;
540
461
541 if (data + FM1_HEADER_SIZE > dataend) {
462 if (data + FM1_HEADER_SIZE > dataend) {
542 goto overflow;
463 goto overflow;
543 }
464 }
544
465
545 *msize = getbe32(data);
466 *msize = getbe32(data);
546 data += 4;
467 data += 4;
547 mtime = getbefloat64(data);
468 mtime = getbefloat64(data);
548 data += 8;
469 data += 8;
549 tz = getbeint16(data);
470 tz = getbeint16(data);
550 data += 2;
471 data += 2;
551 flags = getbeuint16(data);
472 flags = getbeuint16(data);
552 data += 2;
473 data += 2;
553
474
554 if (flags & USING_SHA_256) {
475 if (flags & USING_SHA_256) {
555 hashwidth = 32;
476 hashwidth = 32;
556 }
477 }
557
478
558 nsuccs = (unsigned char)(*data++);
479 nsuccs = (unsigned char)(*data++);
559 nparents = (unsigned char)(*data++);
480 nparents = (unsigned char)(*data++);
560 nmetadata = (unsigned char)(*data++);
481 nmetadata = (unsigned char)(*data++);
561
482
562 if (databegin + *msize > dataend) {
483 if (databegin + *msize > dataend) {
563 goto overflow;
484 goto overflow;
564 }
485 }
565 dataend = databegin + *msize; /* narrow down to marker size */
486 dataend = databegin + *msize; /* narrow down to marker size */
566
487
567 if (data + hashwidth > dataend) {
488 if (data + hashwidth > dataend) {
568 goto overflow;
489 goto overflow;
569 }
490 }
570 prec = PyBytes_FromStringAndSize(data, hashwidth);
491 prec = PyBytes_FromStringAndSize(data, hashwidth);
571 data += hashwidth;
492 data += hashwidth;
572 if (prec == NULL) {
493 if (prec == NULL) {
573 goto bail;
494 goto bail;
574 }
495 }
575
496
576 if (data + nsuccs * hashwidth > dataend) {
497 if (data + nsuccs * hashwidth > dataend) {
577 goto overflow;
498 goto overflow;
578 }
499 }
579 succs = readshas(data, nsuccs, hashwidth);
500 succs = readshas(data, nsuccs, hashwidth);
580 if (succs == NULL) {
501 if (succs == NULL) {
581 goto bail;
502 goto bail;
582 }
503 }
583 data += nsuccs * hashwidth;
504 data += nsuccs * hashwidth;
584
505
585 if (nparents == 1 || nparents == 2) {
506 if (nparents == 1 || nparents == 2) {
586 if (data + nparents * hashwidth > dataend) {
507 if (data + nparents * hashwidth > dataend) {
587 goto overflow;
508 goto overflow;
588 }
509 }
589 parents = readshas(data, nparents, hashwidth);
510 parents = readshas(data, nparents, hashwidth);
590 if (parents == NULL) {
511 if (parents == NULL) {
591 goto bail;
512 goto bail;
592 }
513 }
593 data += nparents * hashwidth;
514 data += nparents * hashwidth;
594 } else {
515 } else {
595 parents = Py_None;
516 parents = Py_None;
596 Py_INCREF(parents);
517 Py_INCREF(parents);
597 }
518 }
598
519
599 if (data + 2 * nmetadata > dataend) {
520 if (data + 2 * nmetadata > dataend) {
600 goto overflow;
521 goto overflow;
601 }
522 }
602 meta = data + (2 * nmetadata);
523 meta = data + (2 * nmetadata);
603 metadata = PyTuple_New(nmetadata);
524 metadata = PyTuple_New(nmetadata);
604 if (metadata == NULL) {
525 if (metadata == NULL) {
605 goto bail;
526 goto bail;
606 }
527 }
607 for (i = 0; i < nmetadata; i++) {
528 for (i = 0; i < nmetadata; i++) {
608 PyObject *tmp, *left = NULL, *right = NULL;
529 PyObject *tmp, *left = NULL, *right = NULL;
609 Py_ssize_t leftsize = (unsigned char)(*data++);
530 Py_ssize_t leftsize = (unsigned char)(*data++);
610 Py_ssize_t rightsize = (unsigned char)(*data++);
531 Py_ssize_t rightsize = (unsigned char)(*data++);
611 if (meta + leftsize + rightsize > dataend) {
532 if (meta + leftsize + rightsize > dataend) {
612 goto overflow;
533 goto overflow;
613 }
534 }
614 left = PyBytes_FromStringAndSize(meta, leftsize);
535 left = PyBytes_FromStringAndSize(meta, leftsize);
615 meta += leftsize;
536 meta += leftsize;
616 right = PyBytes_FromStringAndSize(meta, rightsize);
537 right = PyBytes_FromStringAndSize(meta, rightsize);
617 meta += rightsize;
538 meta += rightsize;
618 tmp = PyTuple_New(2);
539 tmp = PyTuple_New(2);
619 if (!left || !right || !tmp) {
540 if (!left || !right || !tmp) {
620 Py_XDECREF(left);
541 Py_XDECREF(left);
621 Py_XDECREF(right);
542 Py_XDECREF(right);
622 Py_XDECREF(tmp);
543 Py_XDECREF(tmp);
623 goto bail;
544 goto bail;
624 }
545 }
625 PyTuple_SET_ITEM(tmp, 0, left);
546 PyTuple_SET_ITEM(tmp, 0, left);
626 PyTuple_SET_ITEM(tmp, 1, right);
547 PyTuple_SET_ITEM(tmp, 1, right);
627 PyTuple_SET_ITEM(metadata, i, tmp);
548 PyTuple_SET_ITEM(metadata, i, tmp);
628 }
549 }
629 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
550 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
630 (int)tz * 60, parents);
551 (int)tz * 60, parents);
631 goto bail; /* return successfully */
552 goto bail; /* return successfully */
632
553
633 overflow:
554 overflow:
634 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
555 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
635 bail:
556 bail:
636 Py_XDECREF(prec);
557 Py_XDECREF(prec);
637 Py_XDECREF(succs);
558 Py_XDECREF(succs);
638 Py_XDECREF(metadata);
559 Py_XDECREF(metadata);
639 Py_XDECREF(parents);
560 Py_XDECREF(parents);
640 return ret;
561 return ret;
641 }
562 }
642
563
643 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
564 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
644 {
565 {
645 const char *data, *dataend;
566 const char *data, *dataend;
646 int datalen;
567 int datalen;
647 Py_ssize_t offset, stop;
568 Py_ssize_t offset, stop;
648 PyObject *markers = NULL;
569 PyObject *markers = NULL;
649
570
650 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
571 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
651 &offset, &stop)) {
572 &offset, &stop)) {
652 return NULL;
573 return NULL;
653 }
574 }
654 dataend = data + datalen;
575 dataend = data + datalen;
655 data += offset;
576 data += offset;
656 markers = PyList_New(0);
577 markers = PyList_New(0);
657 if (!markers) {
578 if (!markers) {
658 return NULL;
579 return NULL;
659 }
580 }
660 while (offset < stop) {
581 while (offset < stop) {
661 uint32_t msize;
582 uint32_t msize;
662 int error;
583 int error;
663 PyObject *record = fm1readmarker(data, dataend, &msize);
584 PyObject *record = fm1readmarker(data, dataend, &msize);
664 if (!record) {
585 if (!record) {
665 goto bail;
586 goto bail;
666 }
587 }
667 error = PyList_Append(markers, record);
588 error = PyList_Append(markers, record);
668 Py_DECREF(record);
589 Py_DECREF(record);
669 if (error) {
590 if (error) {
670 goto bail;
591 goto bail;
671 }
592 }
672 data += msize;
593 data += msize;
673 offset += msize;
594 offset += msize;
674 }
595 }
675 return markers;
596 return markers;
676 bail:
597 bail:
677 Py_DECREF(markers);
598 Py_DECREF(markers);
678 return NULL;
599 return NULL;
679 }
600 }
680
601
681 static char parsers_doc[] = "Efficient content parsing.";
602 static char parsers_doc[] = "Efficient content parsing.";
682
603
683 PyObject *encodedir(PyObject *self, PyObject *args);
604 PyObject *encodedir(PyObject *self, PyObject *args);
684 PyObject *pathencode(PyObject *self, PyObject *args);
605 PyObject *pathencode(PyObject *self, PyObject *args);
685 PyObject *lowerencode(PyObject *self, PyObject *args);
606 PyObject *lowerencode(PyObject *self, PyObject *args);
686 PyObject *parse_index2(PyObject *self, PyObject *args);
607 PyObject *parse_index2(PyObject *self, PyObject *args);
687
608
688 static PyMethodDef methods[] = {
609 static PyMethodDef methods[] = {
689 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
610 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
690 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
611 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
691 "create a set containing non-normal and other parent entries of given "
612 "create a set containing non-normal and other parent entries of given "
692 "dirstate\n"},
613 "dirstate\n"},
693 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
694 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
614 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
695 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
615 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
696 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
616 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
697 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
617 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
698 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
618 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
699 {"dict_new_presized", dict_new_presized, METH_VARARGS,
619 {"dict_new_presized", dict_new_presized, METH_VARARGS,
700 "construct a dict with an expected size\n"},
620 "construct a dict with an expected size\n"},
701 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
621 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
702 "make file foldmap\n"},
622 "make file foldmap\n"},
703 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
623 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
704 "escape a UTF-8 byte string to JSON (fast path)\n"},
624 "escape a UTF-8 byte string to JSON (fast path)\n"},
705 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
625 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
706 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
626 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
707 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
627 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
708 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
628 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
709 "parse v1 obsolete markers\n"},
629 "parse v1 obsolete markers\n"},
710 {NULL, NULL}};
630 {NULL, NULL}};
711
631
712 void dirs_module_init(PyObject *mod);
632 void dirs_module_init(PyObject *mod);
713 void manifest_module_init(PyObject *mod);
633 void manifest_module_init(PyObject *mod);
714 void revlog_module_init(PyObject *mod);
634 void revlog_module_init(PyObject *mod);
715
635
716 static const int version = 12;
636 static const int version = 12;
717
637
718 static void module_init(PyObject *mod)
638 static void module_init(PyObject *mod)
719 {
639 {
720 PyModule_AddIntConstant(mod, "version", version);
640 PyModule_AddIntConstant(mod, "version", version);
721
641
722 /* This module constant has two purposes. First, it lets us unit test
642 /* This module constant has two purposes. First, it lets us unit test
723 * the ImportError raised without hard-coding any error text. This
643 * the ImportError raised without hard-coding any error text. This
724 * means we can change the text in the future without breaking tests,
644 * means we can change the text in the future without breaking tests,
725 * even across changesets without a recompile. Second, its presence
645 * even across changesets without a recompile. Second, its presence
726 * can be used to determine whether the version-checking logic is
646 * can be used to determine whether the version-checking logic is
727 * present, which also helps in testing across changesets without a
647 * present, which also helps in testing across changesets without a
728 * recompile. Note that this means the pure-Python version of parsers
648 * recompile. Note that this means the pure-Python version of parsers
729 * should not have this module constant. */
649 * should not have this module constant. */
730 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
650 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
731
651
732 dirs_module_init(mod);
652 dirs_module_init(mod);
733 manifest_module_init(mod);
653 manifest_module_init(mod);
734 revlog_module_init(mod);
654 revlog_module_init(mod);
735
655
736 if (PyType_Ready(&dirstateTupleType) < 0)
656 if (PyType_Ready(&dirstateTupleType) < 0)
737 return;
657 return;
738 Py_INCREF(&dirstateTupleType);
658 Py_INCREF(&dirstateTupleType);
739 PyModule_AddObject(mod, "dirstatetuple",
659 PyModule_AddObject(mod, "dirstatetuple",
740 (PyObject *)&dirstateTupleType);
660 (PyObject *)&dirstateTupleType);
741 }
661 }
742
662
743 static int check_python_version(void)
663 static int check_python_version(void)
744 {
664 {
745 PyObject *sys = PyImport_ImportModule("sys"), *ver;
665 PyObject *sys = PyImport_ImportModule("sys"), *ver;
746 long hexversion;
666 long hexversion;
747 if (!sys)
667 if (!sys)
748 return -1;
668 return -1;
749 ver = PyObject_GetAttrString(sys, "hexversion");
669 ver = PyObject_GetAttrString(sys, "hexversion");
750 Py_DECREF(sys);
670 Py_DECREF(sys);
751 if (!ver)
671 if (!ver)
752 return -1;
672 return -1;
753 hexversion = PyInt_AsLong(ver);
673 hexversion = PyInt_AsLong(ver);
754 Py_DECREF(ver);
674 Py_DECREF(ver);
755 /* sys.hexversion is a 32-bit number by default, so the -1 case
675 /* sys.hexversion is a 32-bit number by default, so the -1 case
756 * should only occur in unusual circumstances (e.g. if sys.hexversion
676 * should only occur in unusual circumstances (e.g. if sys.hexversion
757 * is manually set to an invalid value). */
677 * is manually set to an invalid value). */
758 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
678 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
759 PyErr_Format(PyExc_ImportError,
679 PyErr_Format(PyExc_ImportError,
760 "%s: The Mercurial extension "
680 "%s: The Mercurial extension "
761 "modules were compiled with Python " PY_VERSION
681 "modules were compiled with Python " PY_VERSION
762 ", but "
682 ", but "
763 "Mercurial is currently using Python with "
683 "Mercurial is currently using Python with "
764 "sys.hexversion=%ld: "
684 "sys.hexversion=%ld: "
765 "Python %s\n at: %s",
685 "Python %s\n at: %s",
766 versionerrortext, hexversion, Py_GetVersion(),
686 versionerrortext, hexversion, Py_GetVersion(),
767 Py_GetProgramFullPath());
687 Py_GetProgramFullPath());
768 return -1;
688 return -1;
769 }
689 }
770 return 0;
690 return 0;
771 }
691 }
772
692
773 #ifdef IS_PY3K
693 #ifdef IS_PY3K
774 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
694 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
775 parsers_doc, -1, methods};
695 parsers_doc, -1, methods};
776
696
777 PyMODINIT_FUNC PyInit_parsers(void)
697 PyMODINIT_FUNC PyInit_parsers(void)
778 {
698 {
779 PyObject *mod;
699 PyObject *mod;
780
700
781 if (check_python_version() == -1)
701 if (check_python_version() == -1)
782 return NULL;
702 return NULL;
783 mod = PyModule_Create(&parsers_module);
703 mod = PyModule_Create(&parsers_module);
784 module_init(mod);
704 module_init(mod);
785 return mod;
705 return mod;
786 }
706 }
787 #else
707 #else
788 PyMODINIT_FUNC initparsers(void)
708 PyMODINIT_FUNC initparsers(void)
789 {
709 {
790 PyObject *mod;
710 PyObject *mod;
791
711
792 if (check_python_version() == -1)
712 if (check_python_version() == -1)
793 return;
713 return;
794 mod = Py_InitModule3("parsers", methods, parsers_doc);
714 mod = Py_InitModule3("parsers", methods, parsers_doc);
795 module_init(mod);
715 module_init(mod);
796 }
716 }
797 #endif
717 #endif
General Comments 0
You need to be logged in to leave comments. Login now