##// END OF EJS Templates
index: make node tree a Python object...
Martin von Zweigbergk -
r39252:b85b377e default
parent child Browse files
Show More
@@ -1,797 +1,797
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 /*
41 /*
42 * This code assumes that a manifest is stitched together with newline
42 * This code assumes that a manifest is stitched together with newline
43 * ('\n') characters.
43 * ('\n') characters.
44 */
44 */
45 static PyObject *parse_manifest(PyObject *self, PyObject *args)
45 static PyObject *parse_manifest(PyObject *self, PyObject *args)
46 {
46 {
47 PyObject *mfdict, *fdict;
47 PyObject *mfdict, *fdict;
48 char *str, *start, *end;
48 char *str, *start, *end;
49 int len;
49 int len;
50
50
51 if (!PyArg_ParseTuple(
51 if (!PyArg_ParseTuple(
52 args, PY23("O!O!s#:parse_manifest", "O!O!y#:parse_manifest"),
52 args, PY23("O!O!s#:parse_manifest", "O!O!y#:parse_manifest"),
53 &PyDict_Type, &mfdict, &PyDict_Type, &fdict, &str, &len))
53 &PyDict_Type, &mfdict, &PyDict_Type, &fdict, &str, &len))
54 goto quit;
54 goto quit;
55
55
56 start = str;
56 start = str;
57 end = str + len;
57 end = str + len;
58 while (start < end) {
58 while (start < end) {
59 PyObject *file = NULL, *node = NULL;
59 PyObject *file = NULL, *node = NULL;
60 PyObject *flags = NULL;
60 PyObject *flags = NULL;
61 char *zero = NULL, *newline = NULL;
61 char *zero = NULL, *newline = NULL;
62 ptrdiff_t nlen;
62 ptrdiff_t nlen;
63
63
64 zero = memchr(start, '\0', end - start);
64 zero = memchr(start, '\0', end - start);
65 if (!zero) {
65 if (!zero) {
66 PyErr_SetString(PyExc_ValueError,
66 PyErr_SetString(PyExc_ValueError,
67 "manifest entry has no separator");
67 "manifest entry has no separator");
68 goto quit;
68 goto quit;
69 }
69 }
70
70
71 newline = memchr(zero + 1, '\n', end - (zero + 1));
71 newline = memchr(zero + 1, '\n', end - (zero + 1));
72 if (!newline) {
72 if (!newline) {
73 PyErr_SetString(PyExc_ValueError,
73 PyErr_SetString(PyExc_ValueError,
74 "manifest contains trailing garbage");
74 "manifest contains trailing garbage");
75 goto quit;
75 goto quit;
76 }
76 }
77
77
78 file = PyBytes_FromStringAndSize(start, zero - start);
78 file = PyBytes_FromStringAndSize(start, zero - start);
79
79
80 if (!file)
80 if (!file)
81 goto bail;
81 goto bail;
82
82
83 nlen = newline - zero - 1;
83 nlen = newline - zero - 1;
84
84
85 node = unhexlify(zero + 1, nlen > 40 ? 40 : (Py_ssize_t)nlen);
85 node = unhexlify(zero + 1, nlen > 40 ? 40 : (Py_ssize_t)nlen);
86 if (!node)
86 if (!node)
87 goto bail;
87 goto bail;
88
88
89 if (nlen > 40) {
89 if (nlen > 40) {
90 flags = PyBytes_FromStringAndSize(zero + 41, nlen - 40);
90 flags = PyBytes_FromStringAndSize(zero + 41, nlen - 40);
91 if (!flags)
91 if (!flags)
92 goto bail;
92 goto bail;
93
93
94 if (PyDict_SetItem(fdict, file, flags) == -1)
94 if (PyDict_SetItem(fdict, file, flags) == -1)
95 goto bail;
95 goto bail;
96 }
96 }
97
97
98 if (PyDict_SetItem(mfdict, file, node) == -1)
98 if (PyDict_SetItem(mfdict, file, node) == -1)
99 goto bail;
99 goto bail;
100
100
101 start = newline + 1;
101 start = newline + 1;
102
102
103 Py_XDECREF(flags);
103 Py_XDECREF(flags);
104 Py_XDECREF(node);
104 Py_XDECREF(node);
105 Py_XDECREF(file);
105 Py_XDECREF(file);
106 continue;
106 continue;
107 bail:
107 bail:
108 Py_XDECREF(flags);
108 Py_XDECREF(flags);
109 Py_XDECREF(node);
109 Py_XDECREF(node);
110 Py_XDECREF(file);
110 Py_XDECREF(file);
111 goto quit;
111 goto quit;
112 }
112 }
113
113
114 Py_INCREF(Py_None);
114 Py_INCREF(Py_None);
115 return Py_None;
115 return Py_None;
116 quit:
116 quit:
117 return NULL;
117 return NULL;
118 }
118 }
119
119
120 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
120 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
121 int size, int mtime)
121 int size, int mtime)
122 {
122 {
123 dirstateTupleObject *t =
123 dirstateTupleObject *t =
124 PyObject_New(dirstateTupleObject, &dirstateTupleType);
124 PyObject_New(dirstateTupleObject, &dirstateTupleType);
125 if (!t)
125 if (!t)
126 return NULL;
126 return NULL;
127 t->state = state;
127 t->state = state;
128 t->mode = mode;
128 t->mode = mode;
129 t->size = size;
129 t->size = size;
130 t->mtime = mtime;
130 t->mtime = mtime;
131 return t;
131 return t;
132 }
132 }
133
133
134 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
134 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
135 PyObject *kwds)
135 PyObject *kwds)
136 {
136 {
137 /* We do all the initialization here and not a tp_init function because
137 /* We do all the initialization here and not a tp_init function because
138 * dirstate_tuple is immutable. */
138 * dirstate_tuple is immutable. */
139 dirstateTupleObject *t;
139 dirstateTupleObject *t;
140 char state;
140 char state;
141 int size, mode, mtime;
141 int size, mode, mtime;
142 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
142 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
143 return NULL;
143 return NULL;
144
144
145 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
145 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
146 if (!t)
146 if (!t)
147 return NULL;
147 return NULL;
148 t->state = state;
148 t->state = state;
149 t->mode = mode;
149 t->mode = mode;
150 t->size = size;
150 t->size = size;
151 t->mtime = mtime;
151 t->mtime = mtime;
152
152
153 return (PyObject *)t;
153 return (PyObject *)t;
154 }
154 }
155
155
156 static void dirstate_tuple_dealloc(PyObject *o)
156 static void dirstate_tuple_dealloc(PyObject *o)
157 {
157 {
158 PyObject_Del(o);
158 PyObject_Del(o);
159 }
159 }
160
160
161 static Py_ssize_t dirstate_tuple_length(PyObject *o)
161 static Py_ssize_t dirstate_tuple_length(PyObject *o)
162 {
162 {
163 return 4;
163 return 4;
164 }
164 }
165
165
166 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
166 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
167 {
167 {
168 dirstateTupleObject *t = (dirstateTupleObject *)o;
168 dirstateTupleObject *t = (dirstateTupleObject *)o;
169 switch (i) {
169 switch (i) {
170 case 0:
170 case 0:
171 return PyBytes_FromStringAndSize(&t->state, 1);
171 return PyBytes_FromStringAndSize(&t->state, 1);
172 case 1:
172 case 1:
173 return PyInt_FromLong(t->mode);
173 return PyInt_FromLong(t->mode);
174 case 2:
174 case 2:
175 return PyInt_FromLong(t->size);
175 return PyInt_FromLong(t->size);
176 case 3:
176 case 3:
177 return PyInt_FromLong(t->mtime);
177 return PyInt_FromLong(t->mtime);
178 default:
178 default:
179 PyErr_SetString(PyExc_IndexError, "index out of range");
179 PyErr_SetString(PyExc_IndexError, "index out of range");
180 return NULL;
180 return NULL;
181 }
181 }
182 }
182 }
183
183
184 static PySequenceMethods dirstate_tuple_sq = {
184 static PySequenceMethods dirstate_tuple_sq = {
185 dirstate_tuple_length, /* sq_length */
185 dirstate_tuple_length, /* sq_length */
186 0, /* sq_concat */
186 0, /* sq_concat */
187 0, /* sq_repeat */
187 0, /* sq_repeat */
188 dirstate_tuple_item, /* sq_item */
188 dirstate_tuple_item, /* sq_item */
189 0, /* sq_ass_item */
189 0, /* sq_ass_item */
190 0, /* sq_contains */
190 0, /* sq_contains */
191 0, /* sq_inplace_concat */
191 0, /* sq_inplace_concat */
192 0 /* sq_inplace_repeat */
192 0 /* sq_inplace_repeat */
193 };
193 };
194
194
195 PyTypeObject dirstateTupleType = {
195 PyTypeObject dirstateTupleType = {
196 PyVarObject_HEAD_INIT(NULL, 0) /* header */
196 PyVarObject_HEAD_INIT(NULL, 0) /* header */
197 "dirstate_tuple", /* tp_name */
197 "dirstate_tuple", /* tp_name */
198 sizeof(dirstateTupleObject), /* tp_basicsize */
198 sizeof(dirstateTupleObject), /* tp_basicsize */
199 0, /* tp_itemsize */
199 0, /* tp_itemsize */
200 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
200 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
201 0, /* tp_print */
201 0, /* tp_print */
202 0, /* tp_getattr */
202 0, /* tp_getattr */
203 0, /* tp_setattr */
203 0, /* tp_setattr */
204 0, /* tp_compare */
204 0, /* tp_compare */
205 0, /* tp_repr */
205 0, /* tp_repr */
206 0, /* tp_as_number */
206 0, /* tp_as_number */
207 &dirstate_tuple_sq, /* tp_as_sequence */
207 &dirstate_tuple_sq, /* tp_as_sequence */
208 0, /* tp_as_mapping */
208 0, /* tp_as_mapping */
209 0, /* tp_hash */
209 0, /* tp_hash */
210 0, /* tp_call */
210 0, /* tp_call */
211 0, /* tp_str */
211 0, /* tp_str */
212 0, /* tp_getattro */
212 0, /* tp_getattro */
213 0, /* tp_setattro */
213 0, /* tp_setattro */
214 0, /* tp_as_buffer */
214 0, /* tp_as_buffer */
215 Py_TPFLAGS_DEFAULT, /* tp_flags */
215 Py_TPFLAGS_DEFAULT, /* tp_flags */
216 "dirstate tuple", /* tp_doc */
216 "dirstate tuple", /* tp_doc */
217 0, /* tp_traverse */
217 0, /* tp_traverse */
218 0, /* tp_clear */
218 0, /* tp_clear */
219 0, /* tp_richcompare */
219 0, /* tp_richcompare */
220 0, /* tp_weaklistoffset */
220 0, /* tp_weaklistoffset */
221 0, /* tp_iter */
221 0, /* tp_iter */
222 0, /* tp_iternext */
222 0, /* tp_iternext */
223 0, /* tp_methods */
223 0, /* tp_methods */
224 0, /* tp_members */
224 0, /* tp_members */
225 0, /* tp_getset */
225 0, /* tp_getset */
226 0, /* tp_base */
226 0, /* tp_base */
227 0, /* tp_dict */
227 0, /* tp_dict */
228 0, /* tp_descr_get */
228 0, /* tp_descr_get */
229 0, /* tp_descr_set */
229 0, /* tp_descr_set */
230 0, /* tp_dictoffset */
230 0, /* tp_dictoffset */
231 0, /* tp_init */
231 0, /* tp_init */
232 0, /* tp_alloc */
232 0, /* tp_alloc */
233 dirstate_tuple_new, /* tp_new */
233 dirstate_tuple_new, /* tp_new */
234 };
234 };
235
235
236 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
236 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
237 {
237 {
238 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
238 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
239 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
239 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
240 char state, *cur, *str, *cpos;
240 char state, *cur, *str, *cpos;
241 int mode, size, mtime;
241 int mode, size, mtime;
242 unsigned int flen, len, pos = 40;
242 unsigned int flen, len, pos = 40;
243 int readlen;
243 int readlen;
244
244
245 if (!PyArg_ParseTuple(
245 if (!PyArg_ParseTuple(
246 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
246 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
247 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen))
247 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen))
248 goto quit;
248 goto quit;
249
249
250 len = readlen;
250 len = readlen;
251
251
252 /* read parents */
252 /* read parents */
253 if (len < 40) {
253 if (len < 40) {
254 PyErr_SetString(PyExc_ValueError,
254 PyErr_SetString(PyExc_ValueError,
255 "too little data for parents");
255 "too little data for parents");
256 goto quit;
256 goto quit;
257 }
257 }
258
258
259 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20);
259 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20);
260 if (!parents)
260 if (!parents)
261 goto quit;
261 goto quit;
262
262
263 /* read filenames */
263 /* read filenames */
264 while (pos >= 40 && pos < len) {
264 while (pos >= 40 && pos < len) {
265 if (pos + 17 > len) {
265 if (pos + 17 > len) {
266 PyErr_SetString(PyExc_ValueError,
266 PyErr_SetString(PyExc_ValueError,
267 "overflow in dirstate");
267 "overflow in dirstate");
268 goto quit;
268 goto quit;
269 }
269 }
270 cur = str + pos;
270 cur = str + pos;
271 /* unpack header */
271 /* unpack header */
272 state = *cur;
272 state = *cur;
273 mode = getbe32(cur + 1);
273 mode = getbe32(cur + 1);
274 size = getbe32(cur + 5);
274 size = getbe32(cur + 5);
275 mtime = getbe32(cur + 9);
275 mtime = getbe32(cur + 9);
276 flen = getbe32(cur + 13);
276 flen = getbe32(cur + 13);
277 pos += 17;
277 pos += 17;
278 cur += 17;
278 cur += 17;
279 if (flen > len - pos) {
279 if (flen > len - pos) {
280 PyErr_SetString(PyExc_ValueError,
280 PyErr_SetString(PyExc_ValueError,
281 "overflow in dirstate");
281 "overflow in dirstate");
282 goto quit;
282 goto quit;
283 }
283 }
284
284
285 entry =
285 entry =
286 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
286 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
287 cpos = memchr(cur, 0, flen);
287 cpos = memchr(cur, 0, flen);
288 if (cpos) {
288 if (cpos) {
289 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
289 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
290 cname = PyBytes_FromStringAndSize(
290 cname = PyBytes_FromStringAndSize(
291 cpos + 1, flen - (cpos - cur) - 1);
291 cpos + 1, flen - (cpos - cur) - 1);
292 if (!fname || !cname ||
292 if (!fname || !cname ||
293 PyDict_SetItem(cmap, fname, cname) == -1 ||
293 PyDict_SetItem(cmap, fname, cname) == -1 ||
294 PyDict_SetItem(dmap, fname, entry) == -1)
294 PyDict_SetItem(dmap, fname, entry) == -1)
295 goto quit;
295 goto quit;
296 Py_DECREF(cname);
296 Py_DECREF(cname);
297 } else {
297 } else {
298 fname = PyBytes_FromStringAndSize(cur, flen);
298 fname = PyBytes_FromStringAndSize(cur, flen);
299 if (!fname || PyDict_SetItem(dmap, fname, entry) == -1)
299 if (!fname || PyDict_SetItem(dmap, fname, entry) == -1)
300 goto quit;
300 goto quit;
301 }
301 }
302 Py_DECREF(fname);
302 Py_DECREF(fname);
303 Py_DECREF(entry);
303 Py_DECREF(entry);
304 fname = cname = entry = NULL;
304 fname = cname = entry = NULL;
305 pos += flen;
305 pos += flen;
306 }
306 }
307
307
308 ret = parents;
308 ret = parents;
309 Py_INCREF(ret);
309 Py_INCREF(ret);
310 quit:
310 quit:
311 Py_XDECREF(fname);
311 Py_XDECREF(fname);
312 Py_XDECREF(cname);
312 Py_XDECREF(cname);
313 Py_XDECREF(entry);
313 Py_XDECREF(entry);
314 Py_XDECREF(parents);
314 Py_XDECREF(parents);
315 return ret;
315 return ret;
316 }
316 }
317
317
318 /*
318 /*
319 * Build a set of non-normal and other parent entries from the dirstate dmap
319 * Build a set of non-normal and other parent entries from the dirstate dmap
320 */
320 */
321 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
321 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
322 {
322 {
323 PyObject *dmap, *fname, *v;
323 PyObject *dmap, *fname, *v;
324 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
324 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
325 Py_ssize_t pos;
325 Py_ssize_t pos;
326
326
327 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, &dmap))
327 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, &dmap))
328 goto bail;
328 goto bail;
329
329
330 nonnset = PySet_New(NULL);
330 nonnset = PySet_New(NULL);
331 if (nonnset == NULL)
331 if (nonnset == NULL)
332 goto bail;
332 goto bail;
333
333
334 otherpset = PySet_New(NULL);
334 otherpset = PySet_New(NULL);
335 if (otherpset == NULL)
335 if (otherpset == NULL)
336 goto bail;
336 goto bail;
337
337
338 pos = 0;
338 pos = 0;
339 while (PyDict_Next(dmap, &pos, &fname, &v)) {
339 while (PyDict_Next(dmap, &pos, &fname, &v)) {
340 dirstateTupleObject *t;
340 dirstateTupleObject *t;
341 if (!dirstate_tuple_check(v)) {
341 if (!dirstate_tuple_check(v)) {
342 PyErr_SetString(PyExc_TypeError,
342 PyErr_SetString(PyExc_TypeError,
343 "expected a dirstate tuple");
343 "expected a dirstate tuple");
344 goto bail;
344 goto bail;
345 }
345 }
346 t = (dirstateTupleObject *)v;
346 t = (dirstateTupleObject *)v;
347
347
348 if (t->state == 'n' && t->size == -2) {
348 if (t->state == 'n' && t->size == -2) {
349 if (PySet_Add(otherpset, fname) == -1) {
349 if (PySet_Add(otherpset, fname) == -1) {
350 goto bail;
350 goto bail;
351 }
351 }
352 }
352 }
353
353
354 if (t->state == 'n' && t->mtime != -1)
354 if (t->state == 'n' && t->mtime != -1)
355 continue;
355 continue;
356 if (PySet_Add(nonnset, fname) == -1)
356 if (PySet_Add(nonnset, fname) == -1)
357 goto bail;
357 goto bail;
358 }
358 }
359
359
360 result = Py_BuildValue("(OO)", nonnset, otherpset);
360 result = Py_BuildValue("(OO)", nonnset, otherpset);
361 if (result == NULL)
361 if (result == NULL)
362 goto bail;
362 goto bail;
363 Py_DECREF(nonnset);
363 Py_DECREF(nonnset);
364 Py_DECREF(otherpset);
364 Py_DECREF(otherpset);
365 return result;
365 return result;
366 bail:
366 bail:
367 Py_XDECREF(nonnset);
367 Py_XDECREF(nonnset);
368 Py_XDECREF(otherpset);
368 Py_XDECREF(otherpset);
369 Py_XDECREF(result);
369 Py_XDECREF(result);
370 return NULL;
370 return NULL;
371 }
371 }
372
372
373 /*
373 /*
374 * Efficiently pack a dirstate object into its on-disk format.
374 * Efficiently pack a dirstate object into its on-disk format.
375 */
375 */
376 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
376 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
377 {
377 {
378 PyObject *packobj = NULL;
378 PyObject *packobj = NULL;
379 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
379 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
380 Py_ssize_t nbytes, pos, l;
380 Py_ssize_t nbytes, pos, l;
381 PyObject *k, *v = NULL, *pn;
381 PyObject *k, *v = NULL, *pn;
382 char *p, *s;
382 char *p, *s;
383 int now;
383 int now;
384
384
385 if (!PyArg_ParseTuple(args, "O!O!Oi:pack_dirstate", &PyDict_Type, &map,
385 if (!PyArg_ParseTuple(args, "O!O!Oi:pack_dirstate", &PyDict_Type, &map,
386 &PyDict_Type, &copymap, &pl, &now))
386 &PyDict_Type, &copymap, &pl, &now))
387 return NULL;
387 return NULL;
388
388
389 if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
389 if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
390 PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
390 PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
391 return NULL;
391 return NULL;
392 }
392 }
393
393
394 /* Figure out how much we need to allocate. */
394 /* Figure out how much we need to allocate. */
395 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
395 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
396 PyObject *c;
396 PyObject *c;
397 if (!PyBytes_Check(k)) {
397 if (!PyBytes_Check(k)) {
398 PyErr_SetString(PyExc_TypeError, "expected string key");
398 PyErr_SetString(PyExc_TypeError, "expected string key");
399 goto bail;
399 goto bail;
400 }
400 }
401 nbytes += PyBytes_GET_SIZE(k) + 17;
401 nbytes += PyBytes_GET_SIZE(k) + 17;
402 c = PyDict_GetItem(copymap, k);
402 c = PyDict_GetItem(copymap, k);
403 if (c) {
403 if (c) {
404 if (!PyBytes_Check(c)) {
404 if (!PyBytes_Check(c)) {
405 PyErr_SetString(PyExc_TypeError,
405 PyErr_SetString(PyExc_TypeError,
406 "expected string key");
406 "expected string key");
407 goto bail;
407 goto bail;
408 }
408 }
409 nbytes += PyBytes_GET_SIZE(c) + 1;
409 nbytes += PyBytes_GET_SIZE(c) + 1;
410 }
410 }
411 }
411 }
412
412
413 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
413 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
414 if (packobj == NULL)
414 if (packobj == NULL)
415 goto bail;
415 goto bail;
416
416
417 p = PyBytes_AS_STRING(packobj);
417 p = PyBytes_AS_STRING(packobj);
418
418
419 pn = PySequence_ITEM(pl, 0);
419 pn = PySequence_ITEM(pl, 0);
420 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
420 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
421 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
421 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
422 goto bail;
422 goto bail;
423 }
423 }
424 memcpy(p, s, l);
424 memcpy(p, s, l);
425 p += 20;
425 p += 20;
426 pn = PySequence_ITEM(pl, 1);
426 pn = PySequence_ITEM(pl, 1);
427 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
427 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
428 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
428 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
429 goto bail;
429 goto bail;
430 }
430 }
431 memcpy(p, s, l);
431 memcpy(p, s, l);
432 p += 20;
432 p += 20;
433
433
434 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
434 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
435 dirstateTupleObject *tuple;
435 dirstateTupleObject *tuple;
436 char state;
436 char state;
437 int mode, size, mtime;
437 int mode, size, mtime;
438 Py_ssize_t len, l;
438 Py_ssize_t len, l;
439 PyObject *o;
439 PyObject *o;
440 char *t;
440 char *t;
441
441
442 if (!dirstate_tuple_check(v)) {
442 if (!dirstate_tuple_check(v)) {
443 PyErr_SetString(PyExc_TypeError,
443 PyErr_SetString(PyExc_TypeError,
444 "expected a dirstate tuple");
444 "expected a dirstate tuple");
445 goto bail;
445 goto bail;
446 }
446 }
447 tuple = (dirstateTupleObject *)v;
447 tuple = (dirstateTupleObject *)v;
448
448
449 state = tuple->state;
449 state = tuple->state;
450 mode = tuple->mode;
450 mode = tuple->mode;
451 size = tuple->size;
451 size = tuple->size;
452 mtime = tuple->mtime;
452 mtime = tuple->mtime;
453 if (state == 'n' && mtime == now) {
453 if (state == 'n' && mtime == now) {
454 /* See pure/parsers.py:pack_dirstate for why we do
454 /* See pure/parsers.py:pack_dirstate for why we do
455 * this. */
455 * this. */
456 mtime = -1;
456 mtime = -1;
457 mtime_unset = (PyObject *)make_dirstate_tuple(
457 mtime_unset = (PyObject *)make_dirstate_tuple(
458 state, mode, size, mtime);
458 state, mode, size, mtime);
459 if (!mtime_unset)
459 if (!mtime_unset)
460 goto bail;
460 goto bail;
461 if (PyDict_SetItem(map, k, mtime_unset) == -1)
461 if (PyDict_SetItem(map, k, mtime_unset) == -1)
462 goto bail;
462 goto bail;
463 Py_DECREF(mtime_unset);
463 Py_DECREF(mtime_unset);
464 mtime_unset = NULL;
464 mtime_unset = NULL;
465 }
465 }
466 *p++ = state;
466 *p++ = state;
467 putbe32((uint32_t)mode, p);
467 putbe32((uint32_t)mode, p);
468 putbe32((uint32_t)size, p + 4);
468 putbe32((uint32_t)size, p + 4);
469 putbe32((uint32_t)mtime, p + 8);
469 putbe32((uint32_t)mtime, p + 8);
470 t = p + 12;
470 t = p + 12;
471 p += 16;
471 p += 16;
472 len = PyBytes_GET_SIZE(k);
472 len = PyBytes_GET_SIZE(k);
473 memcpy(p, PyBytes_AS_STRING(k), len);
473 memcpy(p, PyBytes_AS_STRING(k), len);
474 p += len;
474 p += len;
475 o = PyDict_GetItem(copymap, k);
475 o = PyDict_GetItem(copymap, k);
476 if (o) {
476 if (o) {
477 *p++ = '\0';
477 *p++ = '\0';
478 l = PyBytes_GET_SIZE(o);
478 l = PyBytes_GET_SIZE(o);
479 memcpy(p, PyBytes_AS_STRING(o), l);
479 memcpy(p, PyBytes_AS_STRING(o), l);
480 p += l;
480 p += l;
481 len += l + 1;
481 len += l + 1;
482 }
482 }
483 putbe32((uint32_t)len, t);
483 putbe32((uint32_t)len, t);
484 }
484 }
485
485
486 pos = p - PyBytes_AS_STRING(packobj);
486 pos = p - PyBytes_AS_STRING(packobj);
487 if (pos != nbytes) {
487 if (pos != nbytes) {
488 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
488 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
489 (long)pos, (long)nbytes);
489 (long)pos, (long)nbytes);
490 goto bail;
490 goto bail;
491 }
491 }
492
492
493 return packobj;
493 return packobj;
494 bail:
494 bail:
495 Py_XDECREF(mtime_unset);
495 Py_XDECREF(mtime_unset);
496 Py_XDECREF(packobj);
496 Py_XDECREF(packobj);
497 Py_XDECREF(v);
497 Py_XDECREF(v);
498 return NULL;
498 return NULL;
499 }
499 }
500
500
501 #define BUMPED_FIX 1
501 #define BUMPED_FIX 1
502 #define USING_SHA_256 2
502 #define USING_SHA_256 2
503 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
503 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
504
504
505 static PyObject *readshas(const char *source, unsigned char num,
505 static PyObject *readshas(const char *source, unsigned char num,
506 Py_ssize_t hashwidth)
506 Py_ssize_t hashwidth)
507 {
507 {
508 int i;
508 int i;
509 PyObject *list = PyTuple_New(num);
509 PyObject *list = PyTuple_New(num);
510 if (list == NULL) {
510 if (list == NULL) {
511 return NULL;
511 return NULL;
512 }
512 }
513 for (i = 0; i < num; i++) {
513 for (i = 0; i < num; i++) {
514 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
514 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
515 if (hash == NULL) {
515 if (hash == NULL) {
516 Py_DECREF(list);
516 Py_DECREF(list);
517 return NULL;
517 return NULL;
518 }
518 }
519 PyTuple_SET_ITEM(list, i, hash);
519 PyTuple_SET_ITEM(list, i, hash);
520 source += hashwidth;
520 source += hashwidth;
521 }
521 }
522 return list;
522 return list;
523 }
523 }
524
524
525 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
525 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
526 uint32_t *msize)
526 uint32_t *msize)
527 {
527 {
528 const char *data = databegin;
528 const char *data = databegin;
529 const char *meta;
529 const char *meta;
530
530
531 double mtime;
531 double mtime;
532 int16_t tz;
532 int16_t tz;
533 uint16_t flags;
533 uint16_t flags;
534 unsigned char nsuccs, nparents, nmetadata;
534 unsigned char nsuccs, nparents, nmetadata;
535 Py_ssize_t hashwidth = 20;
535 Py_ssize_t hashwidth = 20;
536
536
537 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
537 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
538 PyObject *metadata = NULL, *ret = NULL;
538 PyObject *metadata = NULL, *ret = NULL;
539 int i;
539 int i;
540
540
541 if (data + FM1_HEADER_SIZE > dataend) {
541 if (data + FM1_HEADER_SIZE > dataend) {
542 goto overflow;
542 goto overflow;
543 }
543 }
544
544
545 *msize = getbe32(data);
545 *msize = getbe32(data);
546 data += 4;
546 data += 4;
547 mtime = getbefloat64(data);
547 mtime = getbefloat64(data);
548 data += 8;
548 data += 8;
549 tz = getbeint16(data);
549 tz = getbeint16(data);
550 data += 2;
550 data += 2;
551 flags = getbeuint16(data);
551 flags = getbeuint16(data);
552 data += 2;
552 data += 2;
553
553
554 if (flags & USING_SHA_256) {
554 if (flags & USING_SHA_256) {
555 hashwidth = 32;
555 hashwidth = 32;
556 }
556 }
557
557
558 nsuccs = (unsigned char)(*data++);
558 nsuccs = (unsigned char)(*data++);
559 nparents = (unsigned char)(*data++);
559 nparents = (unsigned char)(*data++);
560 nmetadata = (unsigned char)(*data++);
560 nmetadata = (unsigned char)(*data++);
561
561
562 if (databegin + *msize > dataend) {
562 if (databegin + *msize > dataend) {
563 goto overflow;
563 goto overflow;
564 }
564 }
565 dataend = databegin + *msize; /* narrow down to marker size */
565 dataend = databegin + *msize; /* narrow down to marker size */
566
566
567 if (data + hashwidth > dataend) {
567 if (data + hashwidth > dataend) {
568 goto overflow;
568 goto overflow;
569 }
569 }
570 prec = PyBytes_FromStringAndSize(data, hashwidth);
570 prec = PyBytes_FromStringAndSize(data, hashwidth);
571 data += hashwidth;
571 data += hashwidth;
572 if (prec == NULL) {
572 if (prec == NULL) {
573 goto bail;
573 goto bail;
574 }
574 }
575
575
576 if (data + nsuccs * hashwidth > dataend) {
576 if (data + nsuccs * hashwidth > dataend) {
577 goto overflow;
577 goto overflow;
578 }
578 }
579 succs = readshas(data, nsuccs, hashwidth);
579 succs = readshas(data, nsuccs, hashwidth);
580 if (succs == NULL) {
580 if (succs == NULL) {
581 goto bail;
581 goto bail;
582 }
582 }
583 data += nsuccs * hashwidth;
583 data += nsuccs * hashwidth;
584
584
585 if (nparents == 1 || nparents == 2) {
585 if (nparents == 1 || nparents == 2) {
586 if (data + nparents * hashwidth > dataend) {
586 if (data + nparents * hashwidth > dataend) {
587 goto overflow;
587 goto overflow;
588 }
588 }
589 parents = readshas(data, nparents, hashwidth);
589 parents = readshas(data, nparents, hashwidth);
590 if (parents == NULL) {
590 if (parents == NULL) {
591 goto bail;
591 goto bail;
592 }
592 }
593 data += nparents * hashwidth;
593 data += nparents * hashwidth;
594 } else {
594 } else {
595 parents = Py_None;
595 parents = Py_None;
596 Py_INCREF(parents);
596 Py_INCREF(parents);
597 }
597 }
598
598
599 if (data + 2 * nmetadata > dataend) {
599 if (data + 2 * nmetadata > dataend) {
600 goto overflow;
600 goto overflow;
601 }
601 }
602 meta = data + (2 * nmetadata);
602 meta = data + (2 * nmetadata);
603 metadata = PyTuple_New(nmetadata);
603 metadata = PyTuple_New(nmetadata);
604 if (metadata == NULL) {
604 if (metadata == NULL) {
605 goto bail;
605 goto bail;
606 }
606 }
607 for (i = 0; i < nmetadata; i++) {
607 for (i = 0; i < nmetadata; i++) {
608 PyObject *tmp, *left = NULL, *right = NULL;
608 PyObject *tmp, *left = NULL, *right = NULL;
609 Py_ssize_t leftsize = (unsigned char)(*data++);
609 Py_ssize_t leftsize = (unsigned char)(*data++);
610 Py_ssize_t rightsize = (unsigned char)(*data++);
610 Py_ssize_t rightsize = (unsigned char)(*data++);
611 if (meta + leftsize + rightsize > dataend) {
611 if (meta + leftsize + rightsize > dataend) {
612 goto overflow;
612 goto overflow;
613 }
613 }
614 left = PyBytes_FromStringAndSize(meta, leftsize);
614 left = PyBytes_FromStringAndSize(meta, leftsize);
615 meta += leftsize;
615 meta += leftsize;
616 right = PyBytes_FromStringAndSize(meta, rightsize);
616 right = PyBytes_FromStringAndSize(meta, rightsize);
617 meta += rightsize;
617 meta += rightsize;
618 tmp = PyTuple_New(2);
618 tmp = PyTuple_New(2);
619 if (!left || !right || !tmp) {
619 if (!left || !right || !tmp) {
620 Py_XDECREF(left);
620 Py_XDECREF(left);
621 Py_XDECREF(right);
621 Py_XDECREF(right);
622 Py_XDECREF(tmp);
622 Py_XDECREF(tmp);
623 goto bail;
623 goto bail;
624 }
624 }
625 PyTuple_SET_ITEM(tmp, 0, left);
625 PyTuple_SET_ITEM(tmp, 0, left);
626 PyTuple_SET_ITEM(tmp, 1, right);
626 PyTuple_SET_ITEM(tmp, 1, right);
627 PyTuple_SET_ITEM(metadata, i, tmp);
627 PyTuple_SET_ITEM(metadata, i, tmp);
628 }
628 }
629 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
629 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
630 (int)tz * 60, parents);
630 (int)tz * 60, parents);
631 goto bail; /* return successfully */
631 goto bail; /* return successfully */
632
632
633 overflow:
633 overflow:
634 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
634 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
635 bail:
635 bail:
636 Py_XDECREF(prec);
636 Py_XDECREF(prec);
637 Py_XDECREF(succs);
637 Py_XDECREF(succs);
638 Py_XDECREF(metadata);
638 Py_XDECREF(metadata);
639 Py_XDECREF(parents);
639 Py_XDECREF(parents);
640 return ret;
640 return ret;
641 }
641 }
642
642
643 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
643 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
644 {
644 {
645 const char *data, *dataend;
645 const char *data, *dataend;
646 int datalen;
646 int datalen;
647 Py_ssize_t offset, stop;
647 Py_ssize_t offset, stop;
648 PyObject *markers = NULL;
648 PyObject *markers = NULL;
649
649
650 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
650 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
651 &offset, &stop)) {
651 &offset, &stop)) {
652 return NULL;
652 return NULL;
653 }
653 }
654 dataend = data + datalen;
654 dataend = data + datalen;
655 data += offset;
655 data += offset;
656 markers = PyList_New(0);
656 markers = PyList_New(0);
657 if (!markers) {
657 if (!markers) {
658 return NULL;
658 return NULL;
659 }
659 }
660 while (offset < stop) {
660 while (offset < stop) {
661 uint32_t msize;
661 uint32_t msize;
662 int error;
662 int error;
663 PyObject *record = fm1readmarker(data, dataend, &msize);
663 PyObject *record = fm1readmarker(data, dataend, &msize);
664 if (!record) {
664 if (!record) {
665 goto bail;
665 goto bail;
666 }
666 }
667 error = PyList_Append(markers, record);
667 error = PyList_Append(markers, record);
668 Py_DECREF(record);
668 Py_DECREF(record);
669 if (error) {
669 if (error) {
670 goto bail;
670 goto bail;
671 }
671 }
672 data += msize;
672 data += msize;
673 offset += msize;
673 offset += msize;
674 }
674 }
675 return markers;
675 return markers;
676 bail:
676 bail:
677 Py_DECREF(markers);
677 Py_DECREF(markers);
678 return NULL;
678 return NULL;
679 }
679 }
680
680
681 static char parsers_doc[] = "Efficient content parsing.";
681 static char parsers_doc[] = "Efficient content parsing.";
682
682
683 PyObject *encodedir(PyObject *self, PyObject *args);
683 PyObject *encodedir(PyObject *self, PyObject *args);
684 PyObject *pathencode(PyObject *self, PyObject *args);
684 PyObject *pathencode(PyObject *self, PyObject *args);
685 PyObject *lowerencode(PyObject *self, PyObject *args);
685 PyObject *lowerencode(PyObject *self, PyObject *args);
686 PyObject *parse_index2(PyObject *self, PyObject *args);
686 PyObject *parse_index2(PyObject *self, PyObject *args);
687
687
688 static PyMethodDef methods[] = {
688 static PyMethodDef methods[] = {
689 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
689 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
690 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
690 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
691 "create a set containing non-normal and other parent entries of given "
691 "create a set containing non-normal and other parent entries of given "
692 "dirstate\n"},
692 "dirstate\n"},
693 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
693 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
694 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
694 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
695 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
695 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
696 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
696 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
697 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
697 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
698 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
698 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
699 {"dict_new_presized", dict_new_presized, METH_VARARGS,
699 {"dict_new_presized", dict_new_presized, METH_VARARGS,
700 "construct a dict with an expected size\n"},
700 "construct a dict with an expected size\n"},
701 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
701 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
702 "make file foldmap\n"},
702 "make file foldmap\n"},
703 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
703 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
704 "escape a UTF-8 byte string to JSON (fast path)\n"},
704 "escape a UTF-8 byte string to JSON (fast path)\n"},
705 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
705 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
706 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
706 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
707 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
707 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
708 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
708 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
709 "parse v1 obsolete markers\n"},
709 "parse v1 obsolete markers\n"},
710 {NULL, NULL}};
710 {NULL, NULL}};
711
711
712 void dirs_module_init(PyObject *mod);
712 void dirs_module_init(PyObject *mod);
713 void manifest_module_init(PyObject *mod);
713 void manifest_module_init(PyObject *mod);
714 void revlog_module_init(PyObject *mod);
714 void revlog_module_init(PyObject *mod);
715
715
716 static const int version = 7;
716 static const int version = 8;
717
717
718 static void module_init(PyObject *mod)
718 static void module_init(PyObject *mod)
719 {
719 {
720 PyModule_AddIntConstant(mod, "version", version);
720 PyModule_AddIntConstant(mod, "version", version);
721
721
722 /* This module constant has two purposes. First, it lets us unit test
722 /* This module constant has two purposes. First, it lets us unit test
723 * the ImportError raised without hard-coding any error text. This
723 * the ImportError raised without hard-coding any error text. This
724 * means we can change the text in the future without breaking tests,
724 * means we can change the text in the future without breaking tests,
725 * even across changesets without a recompile. Second, its presence
725 * even across changesets without a recompile. Second, its presence
726 * can be used to determine whether the version-checking logic is
726 * can be used to determine whether the version-checking logic is
727 * present, which also helps in testing across changesets without a
727 * present, which also helps in testing across changesets without a
728 * recompile. Note that this means the pure-Python version of parsers
728 * recompile. Note that this means the pure-Python version of parsers
729 * should not have this module constant. */
729 * should not have this module constant. */
730 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
730 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
731
731
732 dirs_module_init(mod);
732 dirs_module_init(mod);
733 manifest_module_init(mod);
733 manifest_module_init(mod);
734 revlog_module_init(mod);
734 revlog_module_init(mod);
735
735
736 if (PyType_Ready(&dirstateTupleType) < 0)
736 if (PyType_Ready(&dirstateTupleType) < 0)
737 return;
737 return;
738 Py_INCREF(&dirstateTupleType);
738 Py_INCREF(&dirstateTupleType);
739 PyModule_AddObject(mod, "dirstatetuple",
739 PyModule_AddObject(mod, "dirstatetuple",
740 (PyObject *)&dirstateTupleType);
740 (PyObject *)&dirstateTupleType);
741 }
741 }
742
742
743 static int check_python_version(void)
743 static int check_python_version(void)
744 {
744 {
745 PyObject *sys = PyImport_ImportModule("sys"), *ver;
745 PyObject *sys = PyImport_ImportModule("sys"), *ver;
746 long hexversion;
746 long hexversion;
747 if (!sys)
747 if (!sys)
748 return -1;
748 return -1;
749 ver = PyObject_GetAttrString(sys, "hexversion");
749 ver = PyObject_GetAttrString(sys, "hexversion");
750 Py_DECREF(sys);
750 Py_DECREF(sys);
751 if (!ver)
751 if (!ver)
752 return -1;
752 return -1;
753 hexversion = PyInt_AsLong(ver);
753 hexversion = PyInt_AsLong(ver);
754 Py_DECREF(ver);
754 Py_DECREF(ver);
755 /* sys.hexversion is a 32-bit number by default, so the -1 case
755 /* 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
756 * should only occur in unusual circumstances (e.g. if sys.hexversion
757 * is manually set to an invalid value). */
757 * is manually set to an invalid value). */
758 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
758 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
759 PyErr_Format(PyExc_ImportError,
759 PyErr_Format(PyExc_ImportError,
760 "%s: The Mercurial extension "
760 "%s: The Mercurial extension "
761 "modules were compiled with Python " PY_VERSION
761 "modules were compiled with Python " PY_VERSION
762 ", but "
762 ", but "
763 "Mercurial is currently using Python with "
763 "Mercurial is currently using Python with "
764 "sys.hexversion=%ld: "
764 "sys.hexversion=%ld: "
765 "Python %s\n at: %s",
765 "Python %s\n at: %s",
766 versionerrortext, hexversion, Py_GetVersion(),
766 versionerrortext, hexversion, Py_GetVersion(),
767 Py_GetProgramFullPath());
767 Py_GetProgramFullPath());
768 return -1;
768 return -1;
769 }
769 }
770 return 0;
770 return 0;
771 }
771 }
772
772
773 #ifdef IS_PY3K
773 #ifdef IS_PY3K
774 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
774 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
775 parsers_doc, -1, methods};
775 parsers_doc, -1, methods};
776
776
777 PyMODINIT_FUNC PyInit_parsers(void)
777 PyMODINIT_FUNC PyInit_parsers(void)
778 {
778 {
779 PyObject *mod;
779 PyObject *mod;
780
780
781 if (check_python_version() == -1)
781 if (check_python_version() == -1)
782 return NULL;
782 return NULL;
783 mod = PyModule_Create(&parsers_module);
783 mod = PyModule_Create(&parsers_module);
784 module_init(mod);
784 module_init(mod);
785 return mod;
785 return mod;
786 }
786 }
787 #else
787 #else
788 PyMODINIT_FUNC initparsers(void)
788 PyMODINIT_FUNC initparsers(void)
789 {
789 {
790 PyObject *mod;
790 PyObject *mod;
791
791
792 if (check_python_version() == -1)
792 if (check_python_version() == -1)
793 return;
793 return;
794 mod = Py_InitModule3("parsers", methods, parsers_doc);
794 mod = Py_InitModule3("parsers", methods, parsers_doc);
795 module_init(mod);
795 module_init(mod);
796 }
796 }
797 #endif
797 #endif
@@ -1,2190 +1,2259
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 <assert.h>
11 #include <assert.h>
12 #include <ctype.h>
12 #include <ctype.h>
13 #include <stddef.h>
13 #include <stddef.h>
14 #include <string.h>
14 #include <string.h>
15
15
16 #include "bitmanipulation.h"
16 #include "bitmanipulation.h"
17 #include "charencode.h"
17 #include "charencode.h"
18 #include "util.h"
18 #include "util.h"
19
19
20 #ifdef IS_PY3K
20 #ifdef IS_PY3K
21 /* The mapping of Python types is meant to be temporary to get Python
21 /* The mapping of Python types is meant to be temporary to get Python
22 * 3 to compile. We should remove this once Python 3 support is fully
22 * 3 to compile. We should remove this once Python 3 support is fully
23 * supported and proper types are used in the extensions themselves. */
23 * supported and proper types are used in the extensions themselves. */
24 #define PyInt_Check PyLong_Check
24 #define PyInt_Check PyLong_Check
25 #define PyInt_FromLong PyLong_FromLong
25 #define PyInt_FromLong PyLong_FromLong
26 #define PyInt_FromSsize_t PyLong_FromSsize_t
26 #define PyInt_FromSsize_t PyLong_FromSsize_t
27 #define PyInt_AS_LONG PyLong_AS_LONG
27 #define PyInt_AS_LONG PyLong_AS_LONG
28 #define PyInt_AsLong PyLong_AsLong
28 #define PyInt_AsLong PyLong_AsLong
29 #endif
29 #endif
30
30
31 typedef struct indexObjectStruct indexObject;
31 typedef struct indexObjectStruct indexObject;
32
32
33 typedef struct {
33 typedef struct {
34 int children[16];
34 int children[16];
35 } nodetreenode;
35 } nodetreenode;
36
36
37 /*
37 /*
38 * A base-16 trie for fast node->rev mapping.
38 * A base-16 trie for fast node->rev mapping.
39 *
39 *
40 * Positive value is index of the next node in the trie
40 * Positive value is index of the next node in the trie
41 * Negative value is a leaf: -(rev + 2)
41 * Negative value is a leaf: -(rev + 2)
42 * Zero is empty
42 * Zero is empty
43 */
43 */
44 typedef struct {
44 typedef struct {
45 PyObject_HEAD
45 indexObject *index;
46 indexObject *index;
46 nodetreenode *nodes;
47 nodetreenode *nodes;
47 unsigned length; /* # nodes in use */
48 unsigned length; /* # nodes in use */
48 unsigned capacity; /* # nodes allocated */
49 unsigned capacity; /* # nodes allocated */
49 int depth; /* maximum depth of tree */
50 int depth; /* maximum depth of tree */
50 int splits; /* # splits performed */
51 int splits; /* # splits performed */
51 } nodetree;
52 } nodetree;
52
53
53 /*
54 /*
54 * This class has two behaviors.
55 * This class has two behaviors.
55 *
56 *
56 * When used in a list-like way (with integer keys), we decode an
57 * When used in a list-like way (with integer keys), we decode an
57 * entry in a RevlogNG index file on demand. Our last entry is a
58 * entry in a RevlogNG index file on demand. Our last entry is a
58 * sentinel, always a nullid. We have limited support for
59 * sentinel, always a nullid. We have limited support for
59 * integer-keyed insert and delete, only at elements right before the
60 * integer-keyed insert and delete, only at elements right before the
60 * sentinel.
61 * sentinel.
61 *
62 *
62 * With string keys, we lazily perform a reverse mapping from node to
63 * With string keys, we lazily perform a reverse mapping from node to
63 * rev, using a base-16 trie.
64 * rev, using a base-16 trie.
64 */
65 */
65 struct indexObjectStruct {
66 struct indexObjectStruct {
66 PyObject_HEAD
67 PyObject_HEAD
67 /* Type-specific fields go here. */
68 /* Type-specific fields go here. */
68 PyObject *data; /* raw bytes of index */
69 PyObject *data; /* raw bytes of index */
69 Py_buffer buf; /* buffer of data */
70 Py_buffer buf; /* buffer of data */
70 PyObject **cache; /* cached tuples */
71 PyObject **cache; /* cached tuples */
71 const char **offsets; /* populated on demand */
72 const char **offsets; /* populated on demand */
72 Py_ssize_t raw_length; /* original number of elements */
73 Py_ssize_t raw_length; /* original number of elements */
73 Py_ssize_t length; /* current number of elements */
74 Py_ssize_t length; /* current number of elements */
74 PyObject *added; /* populated on demand */
75 PyObject *added; /* populated on demand */
75 PyObject *headrevs; /* cache, invalidated on changes */
76 PyObject *headrevs; /* cache, invalidated on changes */
76 PyObject *filteredrevs;/* filtered revs set */
77 PyObject *filteredrevs;/* filtered revs set */
77 nodetree *nt; /* base-16 trie */
78 nodetree *nt; /* base-16 trie */
78 int ntrev; /* last rev scanned */
79 int ntrev; /* last rev scanned */
79 int ntlookups; /* # lookups */
80 int ntlookups; /* # lookups */
80 int ntmisses; /* # lookups that miss the cache */
81 int ntmisses; /* # lookups that miss the cache */
81 int inlined;
82 int inlined;
82 };
83 };
83
84
84 static Py_ssize_t index_length(const indexObject *self)
85 static Py_ssize_t index_length(const indexObject *self)
85 {
86 {
86 if (self->added == NULL)
87 if (self->added == NULL)
87 return self->length;
88 return self->length;
88 return self->length + PyList_GET_SIZE(self->added);
89 return self->length + PyList_GET_SIZE(self->added);
89 }
90 }
90
91
91 static PyObject *nullentry;
92 static PyObject *nullentry;
92 static const char nullid[20];
93 static const char nullid[20];
93
94
94 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
95 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
95
96
96 #if LONG_MAX == 0x7fffffffL
97 #if LONG_MAX == 0x7fffffffL
97 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
98 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
98 #else
99 #else
99 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
100 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
100 #endif
101 #endif
101
102
102 /* A RevlogNG v1 index entry is 64 bytes long. */
103 /* A RevlogNG v1 index entry is 64 bytes long. */
103 static const long v1_hdrsize = 64;
104 static const long v1_hdrsize = 64;
104
105
105 /*
106 /*
106 * Return a pointer to the beginning of a RevlogNG record.
107 * Return a pointer to the beginning of a RevlogNG record.
107 */
108 */
108 static const char *index_deref(indexObject *self, Py_ssize_t pos)
109 static const char *index_deref(indexObject *self, Py_ssize_t pos)
109 {
110 {
110 if (self->inlined && pos > 0) {
111 if (self->inlined && pos > 0) {
111 if (self->offsets == NULL) {
112 if (self->offsets == NULL) {
112 self->offsets = PyMem_Malloc(self->raw_length *
113 self->offsets = PyMem_Malloc(self->raw_length *
113 sizeof(*self->offsets));
114 sizeof(*self->offsets));
114 if (self->offsets == NULL)
115 if (self->offsets == NULL)
115 return (const char *)PyErr_NoMemory();
116 return (const char *)PyErr_NoMemory();
116 inline_scan(self, self->offsets);
117 inline_scan(self, self->offsets);
117 }
118 }
118 return self->offsets[pos];
119 return self->offsets[pos];
119 }
120 }
120
121
121 return (const char *)(self->buf.buf) + pos * v1_hdrsize;
122 return (const char *)(self->buf.buf) + pos * v1_hdrsize;
122 }
123 }
123
124
124 static inline int index_get_parents(indexObject *self, Py_ssize_t rev,
125 static inline int index_get_parents(indexObject *self, Py_ssize_t rev,
125 int *ps, int maxrev)
126 int *ps, int maxrev)
126 {
127 {
127 if (rev >= self->length) {
128 if (rev >= self->length) {
128 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
129 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
129 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5));
130 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5));
130 ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6));
131 ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6));
131 } else {
132 } else {
132 const char *data = index_deref(self, rev);
133 const char *data = index_deref(self, rev);
133 ps[0] = getbe32(data + 24);
134 ps[0] = getbe32(data + 24);
134 ps[1] = getbe32(data + 28);
135 ps[1] = getbe32(data + 28);
135 }
136 }
136 /* If index file is corrupted, ps[] may point to invalid revisions. So
137 /* If index file is corrupted, ps[] may point to invalid revisions. So
137 * there is a risk of buffer overflow to trust them unconditionally. */
138 * there is a risk of buffer overflow to trust them unconditionally. */
138 if (ps[0] > maxrev || ps[1] > maxrev) {
139 if (ps[0] > maxrev || ps[1] > maxrev) {
139 PyErr_SetString(PyExc_ValueError, "parent out of range");
140 PyErr_SetString(PyExc_ValueError, "parent out of range");
140 return -1;
141 return -1;
141 }
142 }
142 return 0;
143 return 0;
143 }
144 }
144
145
145
146
146 /*
147 /*
147 * RevlogNG format (all in big endian, data may be inlined):
148 * RevlogNG format (all in big endian, data may be inlined):
148 * 6 bytes: offset
149 * 6 bytes: offset
149 * 2 bytes: flags
150 * 2 bytes: flags
150 * 4 bytes: compressed length
151 * 4 bytes: compressed length
151 * 4 bytes: uncompressed length
152 * 4 bytes: uncompressed length
152 * 4 bytes: base revision
153 * 4 bytes: base revision
153 * 4 bytes: link revision
154 * 4 bytes: link revision
154 * 4 bytes: parent 1 revision
155 * 4 bytes: parent 1 revision
155 * 4 bytes: parent 2 revision
156 * 4 bytes: parent 2 revision
156 * 32 bytes: nodeid (only 20 bytes used)
157 * 32 bytes: nodeid (only 20 bytes used)
157 */
158 */
158 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
159 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
159 {
160 {
160 uint64_t offset_flags;
161 uint64_t offset_flags;
161 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
162 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
162 const char *c_node_id;
163 const char *c_node_id;
163 const char *data;
164 const char *data;
164 Py_ssize_t length = index_length(self);
165 Py_ssize_t length = index_length(self);
165 PyObject *entry;
166 PyObject *entry;
166
167
167 if (pos == -1) {
168 if (pos == -1) {
168 Py_INCREF(nullentry);
169 Py_INCREF(nullentry);
169 return nullentry;
170 return nullentry;
170 }
171 }
171
172
172 if (pos < 0 || pos >= length) {
173 if (pos < 0 || pos >= length) {
173 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
174 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
174 return NULL;
175 return NULL;
175 }
176 }
176
177
177 if (pos >= self->length) {
178 if (pos >= self->length) {
178 PyObject *obj;
179 PyObject *obj;
179 obj = PyList_GET_ITEM(self->added, pos - self->length);
180 obj = PyList_GET_ITEM(self->added, pos - self->length);
180 Py_INCREF(obj);
181 Py_INCREF(obj);
181 return obj;
182 return obj;
182 }
183 }
183
184
184 if (self->cache) {
185 if (self->cache) {
185 if (self->cache[pos]) {
186 if (self->cache[pos]) {
186 Py_INCREF(self->cache[pos]);
187 Py_INCREF(self->cache[pos]);
187 return self->cache[pos];
188 return self->cache[pos];
188 }
189 }
189 } else {
190 } else {
190 self->cache = calloc(self->raw_length, sizeof(PyObject *));
191 self->cache = calloc(self->raw_length, sizeof(PyObject *));
191 if (self->cache == NULL)
192 if (self->cache == NULL)
192 return PyErr_NoMemory();
193 return PyErr_NoMemory();
193 }
194 }
194
195
195 data = index_deref(self, pos);
196 data = index_deref(self, pos);
196 if (data == NULL)
197 if (data == NULL)
197 return NULL;
198 return NULL;
198
199
199 offset_flags = getbe32(data + 4);
200 offset_flags = getbe32(data + 4);
200 if (pos == 0) /* mask out version number for the first entry */
201 if (pos == 0) /* mask out version number for the first entry */
201 offset_flags &= 0xFFFF;
202 offset_flags &= 0xFFFF;
202 else {
203 else {
203 uint32_t offset_high = getbe32(data);
204 uint32_t offset_high = getbe32(data);
204 offset_flags |= ((uint64_t)offset_high) << 32;
205 offset_flags |= ((uint64_t)offset_high) << 32;
205 }
206 }
206
207
207 comp_len = getbe32(data + 8);
208 comp_len = getbe32(data + 8);
208 uncomp_len = getbe32(data + 12);
209 uncomp_len = getbe32(data + 12);
209 base_rev = getbe32(data + 16);
210 base_rev = getbe32(data + 16);
210 link_rev = getbe32(data + 20);
211 link_rev = getbe32(data + 20);
211 parent_1 = getbe32(data + 24);
212 parent_1 = getbe32(data + 24);
212 parent_2 = getbe32(data + 28);
213 parent_2 = getbe32(data + 28);
213 c_node_id = data + 32;
214 c_node_id = data + 32;
214
215
215 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
216 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
216 uncomp_len, base_rev, link_rev,
217 uncomp_len, base_rev, link_rev,
217 parent_1, parent_2, c_node_id, 20);
218 parent_1, parent_2, c_node_id, 20);
218
219
219 if (entry) {
220 if (entry) {
220 PyObject_GC_UnTrack(entry);
221 PyObject_GC_UnTrack(entry);
221 Py_INCREF(entry);
222 Py_INCREF(entry);
222 }
223 }
223
224
224 self->cache[pos] = entry;
225 self->cache[pos] = entry;
225
226
226 return entry;
227 return entry;
227 }
228 }
228
229
229 /*
230 /*
230 * Return the 20-byte SHA of the node corresponding to the given rev.
231 * Return the 20-byte SHA of the node corresponding to the given rev.
231 */
232 */
232 static const char *index_node(indexObject *self, Py_ssize_t pos)
233 static const char *index_node(indexObject *self, Py_ssize_t pos)
233 {
234 {
234 Py_ssize_t length = index_length(self);
235 Py_ssize_t length = index_length(self);
235 const char *data;
236 const char *data;
236
237
237 if (pos == -1)
238 if (pos == -1)
238 return nullid;
239 return nullid;
239
240
240 if (pos >= length)
241 if (pos >= length)
241 return NULL;
242 return NULL;
242
243
243 if (pos >= self->length) {
244 if (pos >= self->length) {
244 PyObject *tuple, *str;
245 PyObject *tuple, *str;
245 tuple = PyList_GET_ITEM(self->added, pos - self->length);
246 tuple = PyList_GET_ITEM(self->added, pos - self->length);
246 str = PyTuple_GetItem(tuple, 7);
247 str = PyTuple_GetItem(tuple, 7);
247 return str ? PyBytes_AS_STRING(str) : NULL;
248 return str ? PyBytes_AS_STRING(str) : NULL;
248 }
249 }
249
250
250 data = index_deref(self, pos);
251 data = index_deref(self, pos);
251 return data ? data + 32 : NULL;
252 return data ? data + 32 : NULL;
252 }
253 }
253
254
254 /*
255 /*
255 * Return the 20-byte SHA of the node corresponding to the given rev. The
256 * Return the 20-byte SHA of the node corresponding to the given rev. The
256 * rev is assumed to be existing. If not, an exception is set.
257 * rev is assumed to be existing. If not, an exception is set.
257 */
258 */
258 static const char *index_node_existing(indexObject *self, Py_ssize_t pos)
259 static const char *index_node_existing(indexObject *self, Py_ssize_t pos)
259 {
260 {
260 const char *node = index_node(self, pos);
261 const char *node = index_node(self, pos);
261 if (node == NULL) {
262 if (node == NULL) {
262 PyErr_Format(PyExc_IndexError, "could not access rev %d",
263 PyErr_Format(PyExc_IndexError, "could not access rev %d",
263 (int)pos);
264 (int)pos);
264 }
265 }
265 return node;
266 return node;
266 }
267 }
267
268
268 static int nt_insert(nodetree *self, const char *node, int rev);
269 static int nt_insert(nodetree *self, const char *node, int rev);
269
270
270 static int node_check(PyObject *obj, char **node)
271 static int node_check(PyObject *obj, char **node)
271 {
272 {
272 Py_ssize_t nodelen;
273 Py_ssize_t nodelen;
273 if (PyBytes_AsStringAndSize(obj, node, &nodelen) == -1)
274 if (PyBytes_AsStringAndSize(obj, node, &nodelen) == -1)
274 return -1;
275 return -1;
275 if (nodelen == 20)
276 if (nodelen == 20)
276 return 0;
277 return 0;
277 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
278 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
278 return -1;
279 return -1;
279 }
280 }
280
281
281 static PyObject *index_append(indexObject *self, PyObject *obj)
282 static PyObject *index_append(indexObject *self, PyObject *obj)
282 {
283 {
283 char *node;
284 char *node;
284 Py_ssize_t len;
285 Py_ssize_t len;
285
286
286 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
287 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
287 PyErr_SetString(PyExc_TypeError, "8-tuple required");
288 PyErr_SetString(PyExc_TypeError, "8-tuple required");
288 return NULL;
289 return NULL;
289 }
290 }
290
291
291 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
292 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
292 return NULL;
293 return NULL;
293
294
294 len = index_length(self);
295 len = index_length(self);
295
296
296 if (self->added == NULL) {
297 if (self->added == NULL) {
297 self->added = PyList_New(0);
298 self->added = PyList_New(0);
298 if (self->added == NULL)
299 if (self->added == NULL)
299 return NULL;
300 return NULL;
300 }
301 }
301
302
302 if (PyList_Append(self->added, obj) == -1)
303 if (PyList_Append(self->added, obj) == -1)
303 return NULL;
304 return NULL;
304
305
305 if (self->nt)
306 if (self->nt)
306 nt_insert(self->nt, node, (int)len);
307 nt_insert(self->nt, node, (int)len);
307
308
308 Py_CLEAR(self->headrevs);
309 Py_CLEAR(self->headrevs);
309 Py_RETURN_NONE;
310 Py_RETURN_NONE;
310 }
311 }
311
312
312 static PyObject *index_stats(indexObject *self)
313 static PyObject *index_stats(indexObject *self)
313 {
314 {
314 PyObject *obj = PyDict_New();
315 PyObject *obj = PyDict_New();
315 PyObject *t = NULL;
316 PyObject *t = NULL;
316
317
317 if (obj == NULL)
318 if (obj == NULL)
318 return NULL;
319 return NULL;
319
320
320 #define istat(__n, __d) \
321 #define istat(__n, __d) \
321 do { \
322 do { \
322 t = PyInt_FromSsize_t(self->__n); \
323 t = PyInt_FromSsize_t(self->__n); \
323 if (!t) \
324 if (!t) \
324 goto bail; \
325 goto bail; \
325 if (PyDict_SetItemString(obj, __d, t) == -1) \
326 if (PyDict_SetItemString(obj, __d, t) == -1) \
326 goto bail; \
327 goto bail; \
327 Py_DECREF(t); \
328 Py_DECREF(t); \
328 } while (0)
329 } while (0)
329
330
330 if (self->added) {
331 if (self->added) {
331 Py_ssize_t len = PyList_GET_SIZE(self->added);
332 Py_ssize_t len = PyList_GET_SIZE(self->added);
332 t = PyInt_FromSsize_t(len);
333 t = PyInt_FromSsize_t(len);
333 if (!t)
334 if (!t)
334 goto bail;
335 goto bail;
335 if (PyDict_SetItemString(obj, "index entries added", t) == -1)
336 if (PyDict_SetItemString(obj, "index entries added", t) == -1)
336 goto bail;
337 goto bail;
337 Py_DECREF(t);
338 Py_DECREF(t);
338 }
339 }
339
340
340 if (self->raw_length != self->length)
341 if (self->raw_length != self->length)
341 istat(raw_length, "revs on disk");
342 istat(raw_length, "revs on disk");
342 istat(length, "revs in memory");
343 istat(length, "revs in memory");
343 istat(ntlookups, "node trie lookups");
344 istat(ntlookups, "node trie lookups");
344 istat(ntmisses, "node trie misses");
345 istat(ntmisses, "node trie misses");
345 istat(ntrev, "node trie last rev scanned");
346 istat(ntrev, "node trie last rev scanned");
346 if (self->nt) {
347 if (self->nt) {
347 istat(nt->capacity, "node trie capacity");
348 istat(nt->capacity, "node trie capacity");
348 istat(nt->depth, "node trie depth");
349 istat(nt->depth, "node trie depth");
349 istat(nt->length, "node trie count");
350 istat(nt->length, "node trie count");
350 istat(nt->splits, "node trie splits");
351 istat(nt->splits, "node trie splits");
351 }
352 }
352
353
353 #undef istat
354 #undef istat
354
355
355 return obj;
356 return obj;
356
357
357 bail:
358 bail:
358 Py_XDECREF(obj);
359 Py_XDECREF(obj);
359 Py_XDECREF(t);
360 Py_XDECREF(t);
360 return NULL;
361 return NULL;
361 }
362 }
362
363
363 /*
364 /*
364 * When we cache a list, we want to be sure the caller can't mutate
365 * When we cache a list, we want to be sure the caller can't mutate
365 * the cached copy.
366 * the cached copy.
366 */
367 */
367 static PyObject *list_copy(PyObject *list)
368 static PyObject *list_copy(PyObject *list)
368 {
369 {
369 Py_ssize_t len = PyList_GET_SIZE(list);
370 Py_ssize_t len = PyList_GET_SIZE(list);
370 PyObject *newlist = PyList_New(len);
371 PyObject *newlist = PyList_New(len);
371 Py_ssize_t i;
372 Py_ssize_t i;
372
373
373 if (newlist == NULL)
374 if (newlist == NULL)
374 return NULL;
375 return NULL;
375
376
376 for (i = 0; i < len; i++) {
377 for (i = 0; i < len; i++) {
377 PyObject *obj = PyList_GET_ITEM(list, i);
378 PyObject *obj = PyList_GET_ITEM(list, i);
378 Py_INCREF(obj);
379 Py_INCREF(obj);
379 PyList_SET_ITEM(newlist, i, obj);
380 PyList_SET_ITEM(newlist, i, obj);
380 }
381 }
381
382
382 return newlist;
383 return newlist;
383 }
384 }
384
385
385 static int check_filter(PyObject *filter, Py_ssize_t arg)
386 static int check_filter(PyObject *filter, Py_ssize_t arg)
386 {
387 {
387 if (filter) {
388 if (filter) {
388 PyObject *arglist, *result;
389 PyObject *arglist, *result;
389 int isfiltered;
390 int isfiltered;
390
391
391 arglist = Py_BuildValue("(n)", arg);
392 arglist = Py_BuildValue("(n)", arg);
392 if (!arglist) {
393 if (!arglist) {
393 return -1;
394 return -1;
394 }
395 }
395
396
396 result = PyEval_CallObject(filter, arglist);
397 result = PyEval_CallObject(filter, arglist);
397 Py_DECREF(arglist);
398 Py_DECREF(arglist);
398 if (!result) {
399 if (!result) {
399 return -1;
400 return -1;
400 }
401 }
401
402
402 /* PyObject_IsTrue returns 1 if true, 0 if false, -1 if error,
403 /* PyObject_IsTrue returns 1 if true, 0 if false, -1 if error,
403 * same as this function, so we can just return it directly.*/
404 * same as this function, so we can just return it directly.*/
404 isfiltered = PyObject_IsTrue(result);
405 isfiltered = PyObject_IsTrue(result);
405 Py_DECREF(result);
406 Py_DECREF(result);
406 return isfiltered;
407 return isfiltered;
407 } else {
408 } else {
408 return 0;
409 return 0;
409 }
410 }
410 }
411 }
411
412
412 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
413 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
413 Py_ssize_t marker, char *phases)
414 Py_ssize_t marker, char *phases)
414 {
415 {
415 PyObject *iter = NULL;
416 PyObject *iter = NULL;
416 PyObject *iter_item = NULL;
417 PyObject *iter_item = NULL;
417 Py_ssize_t min_idx = index_length(self) + 2;
418 Py_ssize_t min_idx = index_length(self) + 2;
418 long iter_item_long;
419 long iter_item_long;
419
420
420 if (PyList_GET_SIZE(list) != 0) {
421 if (PyList_GET_SIZE(list) != 0) {
421 iter = PyObject_GetIter(list);
422 iter = PyObject_GetIter(list);
422 if (iter == NULL)
423 if (iter == NULL)
423 return -2;
424 return -2;
424 while ((iter_item = PyIter_Next(iter))) {
425 while ((iter_item = PyIter_Next(iter))) {
425 iter_item_long = PyInt_AS_LONG(iter_item);
426 iter_item_long = PyInt_AS_LONG(iter_item);
426 Py_DECREF(iter_item);
427 Py_DECREF(iter_item);
427 if (iter_item_long < min_idx)
428 if (iter_item_long < min_idx)
428 min_idx = iter_item_long;
429 min_idx = iter_item_long;
429 phases[iter_item_long] = marker;
430 phases[iter_item_long] = marker;
430 }
431 }
431 Py_DECREF(iter);
432 Py_DECREF(iter);
432 }
433 }
433
434
434 return min_idx;
435 return min_idx;
435 }
436 }
436
437
437 static inline void set_phase_from_parents(char *phases, int parent_1,
438 static inline void set_phase_from_parents(char *phases, int parent_1,
438 int parent_2, Py_ssize_t i)
439 int parent_2, Py_ssize_t i)
439 {
440 {
440 if (parent_1 >= 0 && phases[parent_1] > phases[i])
441 if (parent_1 >= 0 && phases[parent_1] > phases[i])
441 phases[i] = phases[parent_1];
442 phases[i] = phases[parent_1];
442 if (parent_2 >= 0 && phases[parent_2] > phases[i])
443 if (parent_2 >= 0 && phases[parent_2] > phases[i])
443 phases[i] = phases[parent_2];
444 phases[i] = phases[parent_2];
444 }
445 }
445
446
446 static PyObject *reachableroots2(indexObject *self, PyObject *args)
447 static PyObject *reachableroots2(indexObject *self, PyObject *args)
447 {
448 {
448
449
449 /* Input */
450 /* Input */
450 long minroot;
451 long minroot;
451 PyObject *includepatharg = NULL;
452 PyObject *includepatharg = NULL;
452 int includepath = 0;
453 int includepath = 0;
453 /* heads and roots are lists */
454 /* heads and roots are lists */
454 PyObject *heads = NULL;
455 PyObject *heads = NULL;
455 PyObject *roots = NULL;
456 PyObject *roots = NULL;
456 PyObject *reachable = NULL;
457 PyObject *reachable = NULL;
457
458
458 PyObject *val;
459 PyObject *val;
459 Py_ssize_t len = index_length(self);
460 Py_ssize_t len = index_length(self);
460 long revnum;
461 long revnum;
461 Py_ssize_t k;
462 Py_ssize_t k;
462 Py_ssize_t i;
463 Py_ssize_t i;
463 Py_ssize_t l;
464 Py_ssize_t l;
464 int r;
465 int r;
465 int parents[2];
466 int parents[2];
466
467
467 /* Internal data structure:
468 /* Internal data structure:
468 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit
469 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit
469 * revstates: array of length len+1 (all revs + nullrev) */
470 * revstates: array of length len+1 (all revs + nullrev) */
470 int *tovisit = NULL;
471 int *tovisit = NULL;
471 long lentovisit = 0;
472 long lentovisit = 0;
472 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
473 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
473 char *revstates = NULL;
474 char *revstates = NULL;
474
475
475 /* Get arguments */
476 /* Get arguments */
476 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
477 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
477 &PyList_Type, &roots,
478 &PyList_Type, &roots,
478 &PyBool_Type, &includepatharg))
479 &PyBool_Type, &includepatharg))
479 goto bail;
480 goto bail;
480
481
481 if (includepatharg == Py_True)
482 if (includepatharg == Py_True)
482 includepath = 1;
483 includepath = 1;
483
484
484 /* Initialize return set */
485 /* Initialize return set */
485 reachable = PyList_New(0);
486 reachable = PyList_New(0);
486 if (reachable == NULL)
487 if (reachable == NULL)
487 goto bail;
488 goto bail;
488
489
489 /* Initialize internal datastructures */
490 /* Initialize internal datastructures */
490 tovisit = (int *)malloc((len + 1) * sizeof(int));
491 tovisit = (int *)malloc((len + 1) * sizeof(int));
491 if (tovisit == NULL) {
492 if (tovisit == NULL) {
492 PyErr_NoMemory();
493 PyErr_NoMemory();
493 goto bail;
494 goto bail;
494 }
495 }
495
496
496 revstates = (char *)calloc(len + 1, 1);
497 revstates = (char *)calloc(len + 1, 1);
497 if (revstates == NULL) {
498 if (revstates == NULL) {
498 PyErr_NoMemory();
499 PyErr_NoMemory();
499 goto bail;
500 goto bail;
500 }
501 }
501
502
502 l = PyList_GET_SIZE(roots);
503 l = PyList_GET_SIZE(roots);
503 for (i = 0; i < l; i++) {
504 for (i = 0; i < l; i++) {
504 revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i));
505 revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i));
505 if (revnum == -1 && PyErr_Occurred())
506 if (revnum == -1 && PyErr_Occurred())
506 goto bail;
507 goto bail;
507 /* If root is out of range, e.g. wdir(), it must be unreachable
508 /* If root is out of range, e.g. wdir(), it must be unreachable
508 * from heads. So we can just ignore it. */
509 * from heads. So we can just ignore it. */
509 if (revnum + 1 < 0 || revnum + 1 >= len + 1)
510 if (revnum + 1 < 0 || revnum + 1 >= len + 1)
510 continue;
511 continue;
511 revstates[revnum + 1] |= RS_ROOT;
512 revstates[revnum + 1] |= RS_ROOT;
512 }
513 }
513
514
514 /* Populate tovisit with all the heads */
515 /* Populate tovisit with all the heads */
515 l = PyList_GET_SIZE(heads);
516 l = PyList_GET_SIZE(heads);
516 for (i = 0; i < l; i++) {
517 for (i = 0; i < l; i++) {
517 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i));
518 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i));
518 if (revnum == -1 && PyErr_Occurred())
519 if (revnum == -1 && PyErr_Occurred())
519 goto bail;
520 goto bail;
520 if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
521 if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
521 PyErr_SetString(PyExc_IndexError, "head out of range");
522 PyErr_SetString(PyExc_IndexError, "head out of range");
522 goto bail;
523 goto bail;
523 }
524 }
524 if (!(revstates[revnum + 1] & RS_SEEN)) {
525 if (!(revstates[revnum + 1] & RS_SEEN)) {
525 tovisit[lentovisit++] = (int)revnum;
526 tovisit[lentovisit++] = (int)revnum;
526 revstates[revnum + 1] |= RS_SEEN;
527 revstates[revnum + 1] |= RS_SEEN;
527 }
528 }
528 }
529 }
529
530
530 /* Visit the tovisit list and find the reachable roots */
531 /* Visit the tovisit list and find the reachable roots */
531 k = 0;
532 k = 0;
532 while (k < lentovisit) {
533 while (k < lentovisit) {
533 /* Add the node to reachable if it is a root*/
534 /* Add the node to reachable if it is a root*/
534 revnum = tovisit[k++];
535 revnum = tovisit[k++];
535 if (revstates[revnum + 1] & RS_ROOT) {
536 if (revstates[revnum + 1] & RS_ROOT) {
536 revstates[revnum + 1] |= RS_REACHABLE;
537 revstates[revnum + 1] |= RS_REACHABLE;
537 val = PyInt_FromLong(revnum);
538 val = PyInt_FromLong(revnum);
538 if (val == NULL)
539 if (val == NULL)
539 goto bail;
540 goto bail;
540 r = PyList_Append(reachable, val);
541 r = PyList_Append(reachable, val);
541 Py_DECREF(val);
542 Py_DECREF(val);
542 if (r < 0)
543 if (r < 0)
543 goto bail;
544 goto bail;
544 if (includepath == 0)
545 if (includepath == 0)
545 continue;
546 continue;
546 }
547 }
547
548
548 /* Add its parents to the list of nodes to visit */
549 /* Add its parents to the list of nodes to visit */
549 if (revnum == -1)
550 if (revnum == -1)
550 continue;
551 continue;
551 r = index_get_parents(self, revnum, parents, (int)len - 1);
552 r = index_get_parents(self, revnum, parents, (int)len - 1);
552 if (r < 0)
553 if (r < 0)
553 goto bail;
554 goto bail;
554 for (i = 0; i < 2; i++) {
555 for (i = 0; i < 2; i++) {
555 if (!(revstates[parents[i] + 1] & RS_SEEN)
556 if (!(revstates[parents[i] + 1] & RS_SEEN)
556 && parents[i] >= minroot) {
557 && parents[i] >= minroot) {
557 tovisit[lentovisit++] = parents[i];
558 tovisit[lentovisit++] = parents[i];
558 revstates[parents[i] + 1] |= RS_SEEN;
559 revstates[parents[i] + 1] |= RS_SEEN;
559 }
560 }
560 }
561 }
561 }
562 }
562
563
563 /* Find all the nodes in between the roots we found and the heads
564 /* Find all the nodes in between the roots we found and the heads
564 * and add them to the reachable set */
565 * and add them to the reachable set */
565 if (includepath == 1) {
566 if (includepath == 1) {
566 long minidx = minroot;
567 long minidx = minroot;
567 if (minidx < 0)
568 if (minidx < 0)
568 minidx = 0;
569 minidx = 0;
569 for (i = minidx; i < len; i++) {
570 for (i = minidx; i < len; i++) {
570 if (!(revstates[i + 1] & RS_SEEN))
571 if (!(revstates[i + 1] & RS_SEEN))
571 continue;
572 continue;
572 r = index_get_parents(self, i, parents, (int)len - 1);
573 r = index_get_parents(self, i, parents, (int)len - 1);
573 /* Corrupted index file, error is set from
574 /* Corrupted index file, error is set from
574 * index_get_parents */
575 * index_get_parents */
575 if (r < 0)
576 if (r < 0)
576 goto bail;
577 goto bail;
577 if (((revstates[parents[0] + 1] |
578 if (((revstates[parents[0] + 1] |
578 revstates[parents[1] + 1]) & RS_REACHABLE)
579 revstates[parents[1] + 1]) & RS_REACHABLE)
579 && !(revstates[i + 1] & RS_REACHABLE)) {
580 && !(revstates[i + 1] & RS_REACHABLE)) {
580 revstates[i + 1] |= RS_REACHABLE;
581 revstates[i + 1] |= RS_REACHABLE;
581 val = PyInt_FromSsize_t(i);
582 val = PyInt_FromSsize_t(i);
582 if (val == NULL)
583 if (val == NULL)
583 goto bail;
584 goto bail;
584 r = PyList_Append(reachable, val);
585 r = PyList_Append(reachable, val);
585 Py_DECREF(val);
586 Py_DECREF(val);
586 if (r < 0)
587 if (r < 0)
587 goto bail;
588 goto bail;
588 }
589 }
589 }
590 }
590 }
591 }
591
592
592 free(revstates);
593 free(revstates);
593 free(tovisit);
594 free(tovisit);
594 return reachable;
595 return reachable;
595 bail:
596 bail:
596 Py_XDECREF(reachable);
597 Py_XDECREF(reachable);
597 free(revstates);
598 free(revstates);
598 free(tovisit);
599 free(tovisit);
599 return NULL;
600 return NULL;
600 }
601 }
601
602
602 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
603 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
603 {
604 {
604 PyObject *roots = Py_None;
605 PyObject *roots = Py_None;
605 PyObject *ret = NULL;
606 PyObject *ret = NULL;
606 PyObject *phasessize = NULL;
607 PyObject *phasessize = NULL;
607 PyObject *phaseroots = NULL;
608 PyObject *phaseroots = NULL;
608 PyObject *phaseset = NULL;
609 PyObject *phaseset = NULL;
609 PyObject *phasessetlist = NULL;
610 PyObject *phasessetlist = NULL;
610 PyObject *rev = NULL;
611 PyObject *rev = NULL;
611 Py_ssize_t len = index_length(self);
612 Py_ssize_t len = index_length(self);
612 Py_ssize_t numphase = 0;
613 Py_ssize_t numphase = 0;
613 Py_ssize_t minrevallphases = 0;
614 Py_ssize_t minrevallphases = 0;
614 Py_ssize_t minrevphase = 0;
615 Py_ssize_t minrevphase = 0;
615 Py_ssize_t i = 0;
616 Py_ssize_t i = 0;
616 char *phases = NULL;
617 char *phases = NULL;
617 long phase;
618 long phase;
618
619
619 if (!PyArg_ParseTuple(args, "O", &roots))
620 if (!PyArg_ParseTuple(args, "O", &roots))
620 goto done;
621 goto done;
621 if (roots == NULL || !PyList_Check(roots)) {
622 if (roots == NULL || !PyList_Check(roots)) {
622 PyErr_SetString(PyExc_TypeError, "roots must be a list");
623 PyErr_SetString(PyExc_TypeError, "roots must be a list");
623 goto done;
624 goto done;
624 }
625 }
625
626
626 phases = calloc(len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
627 phases = calloc(len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
627 if (phases == NULL) {
628 if (phases == NULL) {
628 PyErr_NoMemory();
629 PyErr_NoMemory();
629 goto done;
630 goto done;
630 }
631 }
631 /* Put the phase information of all the roots in phases */
632 /* Put the phase information of all the roots in phases */
632 numphase = PyList_GET_SIZE(roots)+1;
633 numphase = PyList_GET_SIZE(roots)+1;
633 minrevallphases = len + 1;
634 minrevallphases = len + 1;
634 phasessetlist = PyList_New(numphase);
635 phasessetlist = PyList_New(numphase);
635 if (phasessetlist == NULL)
636 if (phasessetlist == NULL)
636 goto done;
637 goto done;
637
638
638 PyList_SET_ITEM(phasessetlist, 0, Py_None);
639 PyList_SET_ITEM(phasessetlist, 0, Py_None);
639 Py_INCREF(Py_None);
640 Py_INCREF(Py_None);
640
641
641 for (i = 0; i < numphase-1; i++) {
642 for (i = 0; i < numphase-1; i++) {
642 phaseroots = PyList_GET_ITEM(roots, i);
643 phaseroots = PyList_GET_ITEM(roots, i);
643 phaseset = PySet_New(NULL);
644 phaseset = PySet_New(NULL);
644 if (phaseset == NULL)
645 if (phaseset == NULL)
645 goto release;
646 goto release;
646 PyList_SET_ITEM(phasessetlist, i+1, phaseset);
647 PyList_SET_ITEM(phasessetlist, i+1, phaseset);
647 if (!PyList_Check(phaseroots)) {
648 if (!PyList_Check(phaseroots)) {
648 PyErr_SetString(PyExc_TypeError,
649 PyErr_SetString(PyExc_TypeError,
649 "roots item must be a list");
650 "roots item must be a list");
650 goto release;
651 goto release;
651 }
652 }
652 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases);
653 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases);
653 if (minrevphase == -2) /* Error from add_roots_get_min */
654 if (minrevphase == -2) /* Error from add_roots_get_min */
654 goto release;
655 goto release;
655 minrevallphases = MIN(minrevallphases, minrevphase);
656 minrevallphases = MIN(minrevallphases, minrevphase);
656 }
657 }
657 /* Propagate the phase information from the roots to the revs */
658 /* Propagate the phase information from the roots to the revs */
658 if (minrevallphases != -1) {
659 if (minrevallphases != -1) {
659 int parents[2];
660 int parents[2];
660 for (i = minrevallphases; i < len; i++) {
661 for (i = minrevallphases; i < len; i++) {
661 if (index_get_parents(self, i, parents,
662 if (index_get_parents(self, i, parents,
662 (int)len - 1) < 0)
663 (int)len - 1) < 0)
663 goto release;
664 goto release;
664 set_phase_from_parents(phases, parents[0], parents[1], i);
665 set_phase_from_parents(phases, parents[0], parents[1], i);
665 }
666 }
666 }
667 }
667 /* Transform phase list to a python list */
668 /* Transform phase list to a python list */
668 phasessize = PyInt_FromSsize_t(len);
669 phasessize = PyInt_FromSsize_t(len);
669 if (phasessize == NULL)
670 if (phasessize == NULL)
670 goto release;
671 goto release;
671 for (i = 0; i < len; i++) {
672 for (i = 0; i < len; i++) {
672 phase = phases[i];
673 phase = phases[i];
673 /* We only store the sets of phase for non public phase, the public phase
674 /* We only store the sets of phase for non public phase, the public phase
674 * is computed as a difference */
675 * is computed as a difference */
675 if (phase != 0) {
676 if (phase != 0) {
676 phaseset = PyList_GET_ITEM(phasessetlist, phase);
677 phaseset = PyList_GET_ITEM(phasessetlist, phase);
677 rev = PyInt_FromSsize_t(i);
678 rev = PyInt_FromSsize_t(i);
678 if (rev == NULL)
679 if (rev == NULL)
679 goto release;
680 goto release;
680 PySet_Add(phaseset, rev);
681 PySet_Add(phaseset, rev);
681 Py_XDECREF(rev);
682 Py_XDECREF(rev);
682 }
683 }
683 }
684 }
684 ret = PyTuple_Pack(2, phasessize, phasessetlist);
685 ret = PyTuple_Pack(2, phasessize, phasessetlist);
685
686
686 release:
687 release:
687 Py_XDECREF(phasessize);
688 Py_XDECREF(phasessize);
688 Py_XDECREF(phasessetlist);
689 Py_XDECREF(phasessetlist);
689 done:
690 done:
690 free(phases);
691 free(phases);
691 return ret;
692 return ret;
692 }
693 }
693
694
694 static PyObject *index_headrevs(indexObject *self, PyObject *args)
695 static PyObject *index_headrevs(indexObject *self, PyObject *args)
695 {
696 {
696 Py_ssize_t i, j, len;
697 Py_ssize_t i, j, len;
697 char *nothead = NULL;
698 char *nothead = NULL;
698 PyObject *heads = NULL;
699 PyObject *heads = NULL;
699 PyObject *filter = NULL;
700 PyObject *filter = NULL;
700 PyObject *filteredrevs = Py_None;
701 PyObject *filteredrevs = Py_None;
701
702
702 if (!PyArg_ParseTuple(args, "|O", &filteredrevs)) {
703 if (!PyArg_ParseTuple(args, "|O", &filteredrevs)) {
703 return NULL;
704 return NULL;
704 }
705 }
705
706
706 if (self->headrevs && filteredrevs == self->filteredrevs)
707 if (self->headrevs && filteredrevs == self->filteredrevs)
707 return list_copy(self->headrevs);
708 return list_copy(self->headrevs);
708
709
709 Py_DECREF(self->filteredrevs);
710 Py_DECREF(self->filteredrevs);
710 self->filteredrevs = filteredrevs;
711 self->filteredrevs = filteredrevs;
711 Py_INCREF(filteredrevs);
712 Py_INCREF(filteredrevs);
712
713
713 if (filteredrevs != Py_None) {
714 if (filteredrevs != Py_None) {
714 filter = PyObject_GetAttrString(filteredrevs, "__contains__");
715 filter = PyObject_GetAttrString(filteredrevs, "__contains__");
715 if (!filter) {
716 if (!filter) {
716 PyErr_SetString(PyExc_TypeError,
717 PyErr_SetString(PyExc_TypeError,
717 "filteredrevs has no attribute __contains__");
718 "filteredrevs has no attribute __contains__");
718 goto bail;
719 goto bail;
719 }
720 }
720 }
721 }
721
722
722 len = index_length(self);
723 len = index_length(self);
723 heads = PyList_New(0);
724 heads = PyList_New(0);
724 if (heads == NULL)
725 if (heads == NULL)
725 goto bail;
726 goto bail;
726 if (len == 0) {
727 if (len == 0) {
727 PyObject *nullid = PyInt_FromLong(-1);
728 PyObject *nullid = PyInt_FromLong(-1);
728 if (nullid == NULL || PyList_Append(heads, nullid) == -1) {
729 if (nullid == NULL || PyList_Append(heads, nullid) == -1) {
729 Py_XDECREF(nullid);
730 Py_XDECREF(nullid);
730 goto bail;
731 goto bail;
731 }
732 }
732 goto done;
733 goto done;
733 }
734 }
734
735
735 nothead = calloc(len, 1);
736 nothead = calloc(len, 1);
736 if (nothead == NULL) {
737 if (nothead == NULL) {
737 PyErr_NoMemory();
738 PyErr_NoMemory();
738 goto bail;
739 goto bail;
739 }
740 }
740
741
741 for (i = len - 1; i >= 0; i--) {
742 for (i = len - 1; i >= 0; i--) {
742 int isfiltered;
743 int isfiltered;
743 int parents[2];
744 int parents[2];
744
745
745 /* If nothead[i] == 1, it means we've seen an unfiltered child of this
746 /* If nothead[i] == 1, it means we've seen an unfiltered child of this
746 * node already, and therefore this node is not filtered. So we can skip
747 * node already, and therefore this node is not filtered. So we can skip
747 * the expensive check_filter step.
748 * the expensive check_filter step.
748 */
749 */
749 if (nothead[i] != 1) {
750 if (nothead[i] != 1) {
750 isfiltered = check_filter(filter, i);
751 isfiltered = check_filter(filter, i);
751 if (isfiltered == -1) {
752 if (isfiltered == -1) {
752 PyErr_SetString(PyExc_TypeError,
753 PyErr_SetString(PyExc_TypeError,
753 "unable to check filter");
754 "unable to check filter");
754 goto bail;
755 goto bail;
755 }
756 }
756
757
757 if (isfiltered) {
758 if (isfiltered) {
758 nothead[i] = 1;
759 nothead[i] = 1;
759 continue;
760 continue;
760 }
761 }
761 }
762 }
762
763
763 if (index_get_parents(self, i, parents, (int)len - 1) < 0)
764 if (index_get_parents(self, i, parents, (int)len - 1) < 0)
764 goto bail;
765 goto bail;
765 for (j = 0; j < 2; j++) {
766 for (j = 0; j < 2; j++) {
766 if (parents[j] >= 0)
767 if (parents[j] >= 0)
767 nothead[parents[j]] = 1;
768 nothead[parents[j]] = 1;
768 }
769 }
769 }
770 }
770
771
771 for (i = 0; i < len; i++) {
772 for (i = 0; i < len; i++) {
772 PyObject *head;
773 PyObject *head;
773
774
774 if (nothead[i])
775 if (nothead[i])
775 continue;
776 continue;
776 head = PyInt_FromSsize_t(i);
777 head = PyInt_FromSsize_t(i);
777 if (head == NULL || PyList_Append(heads, head) == -1) {
778 if (head == NULL || PyList_Append(heads, head) == -1) {
778 Py_XDECREF(head);
779 Py_XDECREF(head);
779 goto bail;
780 goto bail;
780 }
781 }
781 }
782 }
782
783
783 done:
784 done:
784 self->headrevs = heads;
785 self->headrevs = heads;
785 Py_XDECREF(filter);
786 Py_XDECREF(filter);
786 free(nothead);
787 free(nothead);
787 return list_copy(self->headrevs);
788 return list_copy(self->headrevs);
788 bail:
789 bail:
789 Py_XDECREF(filter);
790 Py_XDECREF(filter);
790 Py_XDECREF(heads);
791 Py_XDECREF(heads);
791 free(nothead);
792 free(nothead);
792 return NULL;
793 return NULL;
793 }
794 }
794
795
795 /**
796 /**
796 * Obtain the base revision index entry.
797 * Obtain the base revision index entry.
797 *
798 *
798 * Callers must ensure that rev >= 0 or illegal memory access may occur.
799 * Callers must ensure that rev >= 0 or illegal memory access may occur.
799 */
800 */
800 static inline int index_baserev(indexObject *self, int rev)
801 static inline int index_baserev(indexObject *self, int rev)
801 {
802 {
802 const char *data;
803 const char *data;
803
804
804 if (rev >= self->length) {
805 if (rev >= self->length) {
805 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
806 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
806 return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
807 return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
807 }
808 }
808 else {
809 else {
809 data = index_deref(self, rev);
810 data = index_deref(self, rev);
810 if (data == NULL) {
811 if (data == NULL) {
811 return -2;
812 return -2;
812 }
813 }
813
814
814 return getbe32(data + 16);
815 return getbe32(data + 16);
815 }
816 }
816 }
817 }
817
818
818 static PyObject *index_deltachain(indexObject *self, PyObject *args)
819 static PyObject *index_deltachain(indexObject *self, PyObject *args)
819 {
820 {
820 int rev, generaldelta;
821 int rev, generaldelta;
821 PyObject *stoparg;
822 PyObject *stoparg;
822 int stoprev, iterrev, baserev = -1;
823 int stoprev, iterrev, baserev = -1;
823 int stopped;
824 int stopped;
824 PyObject *chain = NULL, *result = NULL;
825 PyObject *chain = NULL, *result = NULL;
825 const Py_ssize_t length = index_length(self);
826 const Py_ssize_t length = index_length(self);
826
827
827 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
828 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
828 return NULL;
829 return NULL;
829 }
830 }
830
831
831 if (PyInt_Check(stoparg)) {
832 if (PyInt_Check(stoparg)) {
832 stoprev = (int)PyInt_AsLong(stoparg);
833 stoprev = (int)PyInt_AsLong(stoparg);
833 if (stoprev == -1 && PyErr_Occurred()) {
834 if (stoprev == -1 && PyErr_Occurred()) {
834 return NULL;
835 return NULL;
835 }
836 }
836 }
837 }
837 else if (stoparg == Py_None) {
838 else if (stoparg == Py_None) {
838 stoprev = -2;
839 stoprev = -2;
839 }
840 }
840 else {
841 else {
841 PyErr_SetString(PyExc_ValueError,
842 PyErr_SetString(PyExc_ValueError,
842 "stoprev must be integer or None");
843 "stoprev must be integer or None");
843 return NULL;
844 return NULL;
844 }
845 }
845
846
846 if (rev < 0 || rev >= length) {
847 if (rev < 0 || rev >= length) {
847 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
848 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
848 return NULL;
849 return NULL;
849 }
850 }
850
851
851 chain = PyList_New(0);
852 chain = PyList_New(0);
852 if (chain == NULL) {
853 if (chain == NULL) {
853 return NULL;
854 return NULL;
854 }
855 }
855
856
856 baserev = index_baserev(self, rev);
857 baserev = index_baserev(self, rev);
857
858
858 /* This should never happen. */
859 /* This should never happen. */
859 if (baserev <= -2) {
860 if (baserev <= -2) {
860 /* Error should be set by index_deref() */
861 /* Error should be set by index_deref() */
861 assert(PyErr_Occurred());
862 assert(PyErr_Occurred());
862 goto bail;
863 goto bail;
863 }
864 }
864
865
865 iterrev = rev;
866 iterrev = rev;
866
867
867 while (iterrev != baserev && iterrev != stoprev) {
868 while (iterrev != baserev && iterrev != stoprev) {
868 PyObject *value = PyInt_FromLong(iterrev);
869 PyObject *value = PyInt_FromLong(iterrev);
869 if (value == NULL) {
870 if (value == NULL) {
870 goto bail;
871 goto bail;
871 }
872 }
872 if (PyList_Append(chain, value)) {
873 if (PyList_Append(chain, value)) {
873 Py_DECREF(value);
874 Py_DECREF(value);
874 goto bail;
875 goto bail;
875 }
876 }
876 Py_DECREF(value);
877 Py_DECREF(value);
877
878
878 if (generaldelta) {
879 if (generaldelta) {
879 iterrev = baserev;
880 iterrev = baserev;
880 }
881 }
881 else {
882 else {
882 iterrev--;
883 iterrev--;
883 }
884 }
884
885
885 if (iterrev < 0) {
886 if (iterrev < 0) {
886 break;
887 break;
887 }
888 }
888
889
889 if (iterrev >= length) {
890 if (iterrev >= length) {
890 PyErr_SetString(PyExc_IndexError, "revision outside index");
891 PyErr_SetString(PyExc_IndexError, "revision outside index");
891 return NULL;
892 return NULL;
892 }
893 }
893
894
894 baserev = index_baserev(self, iterrev);
895 baserev = index_baserev(self, iterrev);
895
896
896 /* This should never happen. */
897 /* This should never happen. */
897 if (baserev <= -2) {
898 if (baserev <= -2) {
898 /* Error should be set by index_deref() */
899 /* Error should be set by index_deref() */
899 assert(PyErr_Occurred());
900 assert(PyErr_Occurred());
900 goto bail;
901 goto bail;
901 }
902 }
902 }
903 }
903
904
904 if (iterrev == stoprev) {
905 if (iterrev == stoprev) {
905 stopped = 1;
906 stopped = 1;
906 }
907 }
907 else {
908 else {
908 PyObject *value = PyInt_FromLong(iterrev);
909 PyObject *value = PyInt_FromLong(iterrev);
909 if (value == NULL) {
910 if (value == NULL) {
910 goto bail;
911 goto bail;
911 }
912 }
912 if (PyList_Append(chain, value)) {
913 if (PyList_Append(chain, value)) {
913 Py_DECREF(value);
914 Py_DECREF(value);
914 goto bail;
915 goto bail;
915 }
916 }
916 Py_DECREF(value);
917 Py_DECREF(value);
917
918
918 stopped = 0;
919 stopped = 0;
919 }
920 }
920
921
921 if (PyList_Reverse(chain)) {
922 if (PyList_Reverse(chain)) {
922 goto bail;
923 goto bail;
923 }
924 }
924
925
925 result = Py_BuildValue("OO", chain, stopped ? Py_True : Py_False);
926 result = Py_BuildValue("OO", chain, stopped ? Py_True : Py_False);
926 Py_DECREF(chain);
927 Py_DECREF(chain);
927 return result;
928 return result;
928
929
929 bail:
930 bail:
930 Py_DECREF(chain);
931 Py_DECREF(chain);
931 return NULL;
932 return NULL;
932 }
933 }
933
934
934 static inline int nt_level(const char *node, Py_ssize_t level)
935 static inline int nt_level(const char *node, Py_ssize_t level)
935 {
936 {
936 int v = node[level>>1];
937 int v = node[level>>1];
937 if (!(level & 1))
938 if (!(level & 1))
938 v >>= 4;
939 v >>= 4;
939 return v & 0xf;
940 return v & 0xf;
940 }
941 }
941
942
942 /*
943 /*
943 * Return values:
944 * Return values:
944 *
945 *
945 * -4: match is ambiguous (multiple candidates)
946 * -4: match is ambiguous (multiple candidates)
946 * -2: not found
947 * -2: not found
947 * rest: valid rev
948 * rest: valid rev
948 */
949 */
949 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
950 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
950 int hex)
951 int hex)
951 {
952 {
952 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
953 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
953 int level, maxlevel, off;
954 int level, maxlevel, off;
954
955
955 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
956 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
956 return -1;
957 return -1;
957
958
958 if (hex)
959 if (hex)
959 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
960 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
960 else
961 else
961 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
962 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
962
963
963 for (level = off = 0; level < maxlevel; level++) {
964 for (level = off = 0; level < maxlevel; level++) {
964 int k = getnybble(node, level);
965 int k = getnybble(node, level);
965 nodetreenode *n = &self->nodes[off];
966 nodetreenode *n = &self->nodes[off];
966 int v = n->children[k];
967 int v = n->children[k];
967
968
968 if (v < 0) {
969 if (v < 0) {
969 const char *n;
970 const char *n;
970 Py_ssize_t i;
971 Py_ssize_t i;
971
972
972 v = -(v + 2);
973 v = -(v + 2);
973 n = index_node(self->index, v);
974 n = index_node(self->index, v);
974 if (n == NULL)
975 if (n == NULL)
975 return -2;
976 return -2;
976 for (i = level; i < maxlevel; i++)
977 for (i = level; i < maxlevel; i++)
977 if (getnybble(node, i) != nt_level(n, i))
978 if (getnybble(node, i) != nt_level(n, i))
978 return -2;
979 return -2;
979 return v;
980 return v;
980 }
981 }
981 if (v == 0)
982 if (v == 0)
982 return -2;
983 return -2;
983 off = v;
984 off = v;
984 }
985 }
985 /* multiple matches against an ambiguous prefix */
986 /* multiple matches against an ambiguous prefix */
986 return -4;
987 return -4;
987 }
988 }
988
989
989 static int nt_new(nodetree *self)
990 static int nt_new(nodetree *self)
990 {
991 {
991 if (self->length == self->capacity) {
992 if (self->length == self->capacity) {
992 unsigned newcapacity;
993 unsigned newcapacity;
993 nodetreenode *newnodes;
994 nodetreenode *newnodes;
994 newcapacity = self->capacity * 2;
995 newcapacity = self->capacity * 2;
995 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
996 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
996 PyErr_SetString(PyExc_MemoryError, "overflow in nt_new");
997 PyErr_SetString(PyExc_MemoryError, "overflow in nt_new");
997 return -1;
998 return -1;
998 }
999 }
999 newnodes = realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1000 newnodes = realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1000 if (newnodes == NULL) {
1001 if (newnodes == NULL) {
1001 PyErr_SetString(PyExc_MemoryError, "out of memory");
1002 PyErr_SetString(PyExc_MemoryError, "out of memory");
1002 return -1;
1003 return -1;
1003 }
1004 }
1004 self->capacity = newcapacity;
1005 self->capacity = newcapacity;
1005 self->nodes = newnodes;
1006 self->nodes = newnodes;
1006 memset(&self->nodes[self->length], 0,
1007 memset(&self->nodes[self->length], 0,
1007 sizeof(nodetreenode) * (self->capacity - self->length));
1008 sizeof(nodetreenode) * (self->capacity - self->length));
1008 }
1009 }
1009 return self->length++;
1010 return self->length++;
1010 }
1011 }
1011
1012
1012 static int nt_insert(nodetree *self, const char *node, int rev)
1013 static int nt_insert(nodetree *self, const char *node, int rev)
1013 {
1014 {
1014 int level = 0;
1015 int level = 0;
1015 int off = 0;
1016 int off = 0;
1016
1017
1017 while (level < 40) {
1018 while (level < 40) {
1018 int k = nt_level(node, level);
1019 int k = nt_level(node, level);
1019 nodetreenode *n;
1020 nodetreenode *n;
1020 int v;
1021 int v;
1021
1022
1022 n = &self->nodes[off];
1023 n = &self->nodes[off];
1023 v = n->children[k];
1024 v = n->children[k];
1024
1025
1025 if (v == 0) {
1026 if (v == 0) {
1026 n->children[k] = -rev - 2;
1027 n->children[k] = -rev - 2;
1027 return 0;
1028 return 0;
1028 }
1029 }
1029 if (v < 0) {
1030 if (v < 0) {
1030 const char *oldnode = index_node_existing(self->index, -(v + 2));
1031 const char *oldnode = index_node_existing(self->index, -(v + 2));
1031 int noff;
1032 int noff;
1032
1033
1033 if (oldnode == NULL)
1034 if (oldnode == NULL)
1034 return -1;
1035 return -1;
1035 if (!memcmp(oldnode, node, 20)) {
1036 if (!memcmp(oldnode, node, 20)) {
1036 n->children[k] = -rev - 2;
1037 n->children[k] = -rev - 2;
1037 return 0;
1038 return 0;
1038 }
1039 }
1039 noff = nt_new(self);
1040 noff = nt_new(self);
1040 if (noff == -1)
1041 if (noff == -1)
1041 return -1;
1042 return -1;
1042 /* self->nodes may have been changed by realloc */
1043 /* self->nodes may have been changed by realloc */
1043 self->nodes[off].children[k] = noff;
1044 self->nodes[off].children[k] = noff;
1044 off = noff;
1045 off = noff;
1045 n = &self->nodes[off];
1046 n = &self->nodes[off];
1046 n->children[nt_level(oldnode, ++level)] = v;
1047 n->children[nt_level(oldnode, ++level)] = v;
1047 if (level > self->depth)
1048 if (level > self->depth)
1048 self->depth = level;
1049 self->depth = level;
1049 self->splits += 1;
1050 self->splits += 1;
1050 } else {
1051 } else {
1051 level += 1;
1052 level += 1;
1052 off = v;
1053 off = v;
1053 }
1054 }
1054 }
1055 }
1055
1056
1056 return -1;
1057 return -1;
1057 }
1058 }
1058
1059
1059 static int nt_delete_node(nodetree *self, const char *node)
1060 static int nt_delete_node(nodetree *self, const char *node)
1060 {
1061 {
1061 /* rev==-2 happens to get encoded as 0, which is interpreted as not set */
1062 /* rev==-2 happens to get encoded as 0, which is interpreted as not set */
1062 return nt_insert(self, node, -2);
1063 return nt_insert(self, node, -2);
1063 }
1064 }
1064
1065
1065 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1066 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1066 {
1067 {
1068 /* Initialize before argument-checking to avoid nt_dealloc() crash. */
1069 self->nodes = NULL;
1070
1067 self->index = index;
1071 self->index = index;
1072 Py_INCREF(index);
1068 /* The input capacity is in terms of revisions, while the field is in
1073 /* The input capacity is in terms of revisions, while the field is in
1069 * terms of nodetree nodes. */
1074 * terms of nodetree nodes. */
1070 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1075 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1071 self->depth = 0;
1076 self->depth = 0;
1072 self->splits = 0;
1077 self->splits = 0;
1073 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1078 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1074 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1079 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1075 return -1;
1080 return -1;
1076 }
1081 }
1077 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1082 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1078 if (self->nodes == NULL) {
1083 if (self->nodes == NULL) {
1079 PyErr_NoMemory();
1084 PyErr_NoMemory();
1080 return -1;
1085 return -1;
1081 }
1086 }
1082 self->length = 1;
1087 self->length = 1;
1083 return 0;
1088 return 0;
1084 }
1089 }
1085
1090
1091 static PyTypeObject indexType;
1092
1093 static int nt_init_py(nodetree *self, PyObject *args)
1094 {
1095 PyObject *index;
1096 unsigned capacity;
1097 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1098 return -1;
1099 return nt_init(self, (indexObject*)index, capacity);
1100 }
1101
1086 static int nt_partialmatch(nodetree *self, const char *node,
1102 static int nt_partialmatch(nodetree *self, const char *node,
1087 Py_ssize_t nodelen)
1103 Py_ssize_t nodelen)
1088 {
1104 {
1089 return nt_find(self, node, nodelen, 1);
1105 return nt_find(self, node, nodelen, 1);
1090 }
1106 }
1091
1107
1092 /*
1108 /*
1093 * Find the length of the shortest unique prefix of node.
1109 * Find the length of the shortest unique prefix of node.
1094 *
1110 *
1095 * Return values:
1111 * Return values:
1096 *
1112 *
1097 * -3: error (exception set)
1113 * -3: error (exception set)
1098 * -2: not found (no exception set)
1114 * -2: not found (no exception set)
1099 * rest: length of shortest prefix
1115 * rest: length of shortest prefix
1100 */
1116 */
1101 static int nt_shortest(nodetree *self, const char *node)
1117 static int nt_shortest(nodetree *self, const char *node)
1102 {
1118 {
1103 int level, off;
1119 int level, off;
1104
1120
1105 for (level = off = 0; level < 40; level++) {
1121 for (level = off = 0; level < 40; level++) {
1106 int k, v;
1122 int k, v;
1107 nodetreenode *n = &self->nodes[off];
1123 nodetreenode *n = &self->nodes[off];
1108 k = nt_level(node, level);
1124 k = nt_level(node, level);
1109 v = n->children[k];
1125 v = n->children[k];
1110 if (v < 0) {
1126 if (v < 0) {
1111 const char *n;
1127 const char *n;
1112 v = -(v + 2);
1128 v = -(v + 2);
1113 n = index_node_existing(self->index, v);
1129 n = index_node_existing(self->index, v);
1114 if (n == NULL)
1130 if (n == NULL)
1115 return -3;
1131 return -3;
1116 if (memcmp(node, n, 20) != 0)
1132 if (memcmp(node, n, 20) != 0)
1117 /*
1133 /*
1118 * Found a unique prefix, but it wasn't for the
1134 * Found a unique prefix, but it wasn't for the
1119 * requested node (i.e the requested node does
1135 * requested node (i.e the requested node does
1120 * not exist).
1136 * not exist).
1121 */
1137 */
1122 return -2;
1138 return -2;
1123 return level + 1;
1139 return level + 1;
1124 }
1140 }
1125 if (v == 0)
1141 if (v == 0)
1126 return -2;
1142 return -2;
1127 off = v;
1143 off = v;
1128 }
1144 }
1129 /*
1145 /*
1130 * The node was still not unique after 40 hex digits, so this won't
1146 * The node was still not unique after 40 hex digits, so this won't
1131 * happen. Also, if we get here, then there's a programming error in
1147 * happen. Also, if we get here, then there's a programming error in
1132 * this file that made us insert a node longer than 40 hex digits.
1148 * this file that made us insert a node longer than 40 hex digits.
1133 */
1149 */
1134 PyErr_SetString(PyExc_Exception, "broken node tree");
1150 PyErr_SetString(PyExc_Exception, "broken node tree");
1135 return -3;
1151 return -3;
1136 }
1152 }
1137
1153
1154 static void nt_dealloc(nodetree *self)
1155 {
1156 Py_XDECREF(self->index);
1157 free(self->nodes);
1158 self->nodes = NULL;
1159 PyObject_Del(self);
1160 }
1161
1162 static PyTypeObject nodetreeType = {
1163 PyVarObject_HEAD_INIT(NULL, 0) /* header */
1164 "parsers.nodetree", /* tp_name */
1165 sizeof(nodetree) , /* tp_basicsize */
1166 0, /* tp_itemsize */
1167 (destructor)nt_dealloc, /* tp_dealloc */
1168 0, /* tp_print */
1169 0, /* tp_getattr */
1170 0, /* tp_setattr */
1171 0, /* tp_compare */
1172 0, /* tp_repr */
1173 0, /* tp_as_number */
1174 0, /* tp_as_sequence */
1175 0, /* tp_as_mapping */
1176 0, /* tp_hash */
1177 0, /* tp_call */
1178 0, /* tp_str */
1179 0, /* tp_getattro */
1180 0, /* tp_setattro */
1181 0, /* tp_as_buffer */
1182 Py_TPFLAGS_DEFAULT, /* tp_flags */
1183 "nodetree", /* tp_doc */
1184 0, /* tp_traverse */
1185 0, /* tp_clear */
1186 0, /* tp_richcompare */
1187 0, /* tp_weaklistoffset */
1188 0, /* tp_iter */
1189 0, /* tp_iternext */
1190 0, /* tp_methods */
1191 0, /* tp_members */
1192 0, /* tp_getset */
1193 0, /* tp_base */
1194 0, /* tp_dict */
1195 0, /* tp_descr_get */
1196 0, /* tp_descr_set */
1197 0, /* tp_dictoffset */
1198 (initproc)nt_init_py, /* tp_init */
1199 0, /* tp_alloc */
1200 };
1201
1138 static int index_init_nt(indexObject *self)
1202 static int index_init_nt(indexObject *self)
1139 {
1203 {
1140 if (self->nt == NULL) {
1204 if (self->nt == NULL) {
1141 self->nt = PyMem_Malloc(sizeof(nodetree));
1205 self->nt = PyObject_New(nodetree, &nodetreeType);
1142 if (self->nt == NULL) {
1206 if (self->nt == NULL) {
1143 PyErr_NoMemory();
1144 return -1;
1207 return -1;
1145 }
1208 }
1146 if (nt_init(self->nt, self, self->raw_length) == -1) {
1209 if (nt_init(self->nt, self, self->raw_length) == -1) {
1147 PyMem_Free(self->nt);
1210 nt_dealloc(self->nt);
1148 self->nt = NULL;
1211 self->nt = NULL;
1149 return -1;
1212 return -1;
1150 }
1213 }
1151 if (nt_insert(self->nt, nullid, -1) == -1) {
1214 if (nt_insert(self->nt, nullid, -1) == -1) {
1152 PyMem_Free(self->nt);
1215 nt_dealloc(self->nt);
1153 self->nt = NULL;
1216 self->nt = NULL;
1154 return -1;
1217 return -1;
1155 }
1218 }
1156 self->ntrev = (int)index_length(self);
1219 self->ntrev = (int)index_length(self);
1157 self->ntlookups = 1;
1220 self->ntlookups = 1;
1158 self->ntmisses = 0;
1221 self->ntmisses = 0;
1159 }
1222 }
1160 return 0;
1223 return 0;
1161 }
1224 }
1162
1225
1163 /*
1226 /*
1164 * Return values:
1227 * Return values:
1165 *
1228 *
1166 * -3: error (exception set)
1229 * -3: error (exception set)
1167 * -2: not found (no exception set)
1230 * -2: not found (no exception set)
1168 * rest: valid rev
1231 * rest: valid rev
1169 */
1232 */
1170 static int index_find_node(indexObject *self,
1233 static int index_find_node(indexObject *self,
1171 const char *node, Py_ssize_t nodelen)
1234 const char *node, Py_ssize_t nodelen)
1172 {
1235 {
1173 int rev;
1236 int rev;
1174
1237
1175 if (index_init_nt(self) == -1)
1238 if (index_init_nt(self) == -1)
1176 return -3;
1239 return -3;
1177
1240
1178 self->ntlookups++;
1241 self->ntlookups++;
1179 rev = nt_find(self->nt, node, nodelen, 0);
1242 rev = nt_find(self->nt, node, nodelen, 0);
1180 if (rev >= -1)
1243 if (rev >= -1)
1181 return rev;
1244 return rev;
1182
1245
1183 /*
1246 /*
1184 * For the first handful of lookups, we scan the entire index,
1247 * For the first handful of lookups, we scan the entire index,
1185 * and cache only the matching nodes. This optimizes for cases
1248 * and cache only the matching nodes. This optimizes for cases
1186 * like "hg tip", where only a few nodes are accessed.
1249 * like "hg tip", where only a few nodes are accessed.
1187 *
1250 *
1188 * After that, we cache every node we visit, using a single
1251 * After that, we cache every node we visit, using a single
1189 * scan amortized over multiple lookups. This gives the best
1252 * scan amortized over multiple lookups. This gives the best
1190 * bulk performance, e.g. for "hg log".
1253 * bulk performance, e.g. for "hg log".
1191 */
1254 */
1192 if (self->ntmisses++ < 4) {
1255 if (self->ntmisses++ < 4) {
1193 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1256 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1194 const char *n = index_node_existing(self, rev);
1257 const char *n = index_node_existing(self, rev);
1195 if (n == NULL)
1258 if (n == NULL)
1196 return -3;
1259 return -3;
1197 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1260 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1198 if (nt_insert(self->nt, n, rev) == -1)
1261 if (nt_insert(self->nt, n, rev) == -1)
1199 return -3;
1262 return -3;
1200 break;
1263 break;
1201 }
1264 }
1202 }
1265 }
1203 } else {
1266 } else {
1204 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1267 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1205 const char *n = index_node_existing(self, rev);
1268 const char *n = index_node_existing(self, rev);
1206 if (n == NULL)
1269 if (n == NULL)
1207 return -3;
1270 return -3;
1208 if (nt_insert(self->nt, n, rev) == -1) {
1271 if (nt_insert(self->nt, n, rev) == -1) {
1209 self->ntrev = rev + 1;
1272 self->ntrev = rev + 1;
1210 return -3;
1273 return -3;
1211 }
1274 }
1212 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1275 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1213 break;
1276 break;
1214 }
1277 }
1215 }
1278 }
1216 self->ntrev = rev;
1279 self->ntrev = rev;
1217 }
1280 }
1218
1281
1219 if (rev >= 0)
1282 if (rev >= 0)
1220 return rev;
1283 return rev;
1221 return -2;
1284 return -2;
1222 }
1285 }
1223
1286
1224 static void raise_revlog_error(void)
1287 static void raise_revlog_error(void)
1225 {
1288 {
1226 PyObject *mod = NULL, *dict = NULL, *errclass = NULL;
1289 PyObject *mod = NULL, *dict = NULL, *errclass = NULL;
1227
1290
1228 mod = PyImport_ImportModule("mercurial.error");
1291 mod = PyImport_ImportModule("mercurial.error");
1229 if (mod == NULL) {
1292 if (mod == NULL) {
1230 goto cleanup;
1293 goto cleanup;
1231 }
1294 }
1232
1295
1233 dict = PyModule_GetDict(mod);
1296 dict = PyModule_GetDict(mod);
1234 if (dict == NULL) {
1297 if (dict == NULL) {
1235 goto cleanup;
1298 goto cleanup;
1236 }
1299 }
1237 Py_INCREF(dict);
1300 Py_INCREF(dict);
1238
1301
1239 errclass = PyDict_GetItemString(dict, "RevlogError");
1302 errclass = PyDict_GetItemString(dict, "RevlogError");
1240 if (errclass == NULL) {
1303 if (errclass == NULL) {
1241 PyErr_SetString(PyExc_SystemError,
1304 PyErr_SetString(PyExc_SystemError,
1242 "could not find RevlogError");
1305 "could not find RevlogError");
1243 goto cleanup;
1306 goto cleanup;
1244 }
1307 }
1245
1308
1246 /* value of exception is ignored by callers */
1309 /* value of exception is ignored by callers */
1247 PyErr_SetString(errclass, "RevlogError");
1310 PyErr_SetString(errclass, "RevlogError");
1248
1311
1249 cleanup:
1312 cleanup:
1250 Py_XDECREF(dict);
1313 Py_XDECREF(dict);
1251 Py_XDECREF(mod);
1314 Py_XDECREF(mod);
1252 }
1315 }
1253
1316
1254 static PyObject *index_getitem(indexObject *self, PyObject *value)
1317 static PyObject *index_getitem(indexObject *self, PyObject *value)
1255 {
1318 {
1256 char *node;
1319 char *node;
1257 int rev;
1320 int rev;
1258
1321
1259 if (PyInt_Check(value))
1322 if (PyInt_Check(value))
1260 return index_get(self, PyInt_AS_LONG(value));
1323 return index_get(self, PyInt_AS_LONG(value));
1261
1324
1262 if (node_check(value, &node) == -1)
1325 if (node_check(value, &node) == -1)
1263 return NULL;
1326 return NULL;
1264 rev = index_find_node(self, node, 20);
1327 rev = index_find_node(self, node, 20);
1265 if (rev >= -1)
1328 if (rev >= -1)
1266 return PyInt_FromLong(rev);
1329 return PyInt_FromLong(rev);
1267 if (rev == -2)
1330 if (rev == -2)
1268 raise_revlog_error();
1331 raise_revlog_error();
1269 return NULL;
1332 return NULL;
1270 }
1333 }
1271
1334
1272 /*
1335 /*
1273 * Fully populate the radix tree.
1336 * Fully populate the radix tree.
1274 */
1337 */
1275 static int index_populate_nt(indexObject *self) {
1338 static int index_populate_nt(indexObject *self) {
1276 int rev;
1339 int rev;
1277 if (self->ntrev > 0) {
1340 if (self->ntrev > 0) {
1278 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1341 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1279 const char *n = index_node_existing(self, rev);
1342 const char *n = index_node_existing(self, rev);
1280 if (n == NULL)
1343 if (n == NULL)
1281 return -1;
1344 return -1;
1282 if (nt_insert(self->nt, n, rev) == -1)
1345 if (nt_insert(self->nt, n, rev) == -1)
1283 return -1;
1346 return -1;
1284 }
1347 }
1285 self->ntrev = -1;
1348 self->ntrev = -1;
1286 }
1349 }
1287 return 0;
1350 return 0;
1288 }
1351 }
1289
1352
1290 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1353 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1291 {
1354 {
1292 const char *fullnode;
1355 const char *fullnode;
1293 int nodelen;
1356 int nodelen;
1294 char *node;
1357 char *node;
1295 int rev, i;
1358 int rev, i;
1296
1359
1297 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1360 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1298 return NULL;
1361 return NULL;
1299
1362
1300 if (nodelen < 1) {
1363 if (nodelen < 1) {
1301 PyErr_SetString(PyExc_ValueError, "key too short");
1364 PyErr_SetString(PyExc_ValueError, "key too short");
1302 return NULL;
1365 return NULL;
1303 }
1366 }
1304
1367
1305 if (nodelen > 40) {
1368 if (nodelen > 40) {
1306 PyErr_SetString(PyExc_ValueError, "key too long");
1369 PyErr_SetString(PyExc_ValueError, "key too long");
1307 return NULL;
1370 return NULL;
1308 }
1371 }
1309
1372
1310 for (i = 0; i < nodelen; i++)
1373 for (i = 0; i < nodelen; i++)
1311 hexdigit(node, i);
1374 hexdigit(node, i);
1312 if (PyErr_Occurred()) {
1375 if (PyErr_Occurred()) {
1313 /* input contains non-hex characters */
1376 /* input contains non-hex characters */
1314 PyErr_Clear();
1377 PyErr_Clear();
1315 Py_RETURN_NONE;
1378 Py_RETURN_NONE;
1316 }
1379 }
1317
1380
1318 if (index_init_nt(self) == -1)
1381 if (index_init_nt(self) == -1)
1319 return NULL;
1382 return NULL;
1320 if (index_populate_nt(self) == -1)
1383 if (index_populate_nt(self) == -1)
1321 return NULL;
1384 return NULL;
1322 rev = nt_partialmatch(self->nt, node, nodelen);
1385 rev = nt_partialmatch(self->nt, node, nodelen);
1323
1386
1324 switch (rev) {
1387 switch (rev) {
1325 case -4:
1388 case -4:
1326 raise_revlog_error();
1389 raise_revlog_error();
1327 return NULL;
1390 return NULL;
1328 case -2:
1391 case -2:
1329 Py_RETURN_NONE;
1392 Py_RETURN_NONE;
1330 case -1:
1393 case -1:
1331 return PyBytes_FromStringAndSize(nullid, 20);
1394 return PyBytes_FromStringAndSize(nullid, 20);
1332 }
1395 }
1333
1396
1334 fullnode = index_node_existing(self, rev);
1397 fullnode = index_node_existing(self, rev);
1335 if (fullnode == NULL) {
1398 if (fullnode == NULL) {
1336 return NULL;
1399 return NULL;
1337 }
1400 }
1338 return PyBytes_FromStringAndSize(fullnode, 20);
1401 return PyBytes_FromStringAndSize(fullnode, 20);
1339 }
1402 }
1340
1403
1341 static PyObject *index_shortest(indexObject *self, PyObject *args)
1404 static PyObject *index_shortest(indexObject *self, PyObject *args)
1342 {
1405 {
1343 PyObject *val;
1406 PyObject *val;
1344 char *node;
1407 char *node;
1345 int length;
1408 int length;
1346
1409
1347 if (!PyArg_ParseTuple(args, "O", &val))
1410 if (!PyArg_ParseTuple(args, "O", &val))
1348 return NULL;
1411 return NULL;
1349 if (node_check(val, &node) == -1)
1412 if (node_check(val, &node) == -1)
1350 return NULL;
1413 return NULL;
1351
1414
1352 self->ntlookups++;
1415 self->ntlookups++;
1353 if (index_init_nt(self) == -1)
1416 if (index_init_nt(self) == -1)
1354 return NULL;
1417 return NULL;
1355 if (index_populate_nt(self) == -1)
1418 if (index_populate_nt(self) == -1)
1356 return NULL;
1419 return NULL;
1357 length = nt_shortest(self->nt, node);
1420 length = nt_shortest(self->nt, node);
1358 if (length == -3)
1421 if (length == -3)
1359 return NULL;
1422 return NULL;
1360 if (length == -2) {
1423 if (length == -2) {
1361 raise_revlog_error();
1424 raise_revlog_error();
1362 return NULL;
1425 return NULL;
1363 }
1426 }
1364 return PyInt_FromLong(length);
1427 return PyInt_FromLong(length);
1365 }
1428 }
1366
1429
1367 static PyObject *index_m_get(indexObject *self, PyObject *args)
1430 static PyObject *index_m_get(indexObject *self, PyObject *args)
1368 {
1431 {
1369 PyObject *val;
1432 PyObject *val;
1370 char *node;
1433 char *node;
1371 int rev;
1434 int rev;
1372
1435
1373 if (!PyArg_ParseTuple(args, "O", &val))
1436 if (!PyArg_ParseTuple(args, "O", &val))
1374 return NULL;
1437 return NULL;
1375 if (node_check(val, &node) == -1)
1438 if (node_check(val, &node) == -1)
1376 return NULL;
1439 return NULL;
1377 rev = index_find_node(self, node, 20);
1440 rev = index_find_node(self, node, 20);
1378 if (rev == -3)
1441 if (rev == -3)
1379 return NULL;
1442 return NULL;
1380 if (rev == -2)
1443 if (rev == -2)
1381 Py_RETURN_NONE;
1444 Py_RETURN_NONE;
1382 return PyInt_FromLong(rev);
1445 return PyInt_FromLong(rev);
1383 }
1446 }
1384
1447
1385 static int index_contains(indexObject *self, PyObject *value)
1448 static int index_contains(indexObject *self, PyObject *value)
1386 {
1449 {
1387 char *node;
1450 char *node;
1388
1451
1389 if (PyInt_Check(value)) {
1452 if (PyInt_Check(value)) {
1390 long rev = PyInt_AS_LONG(value);
1453 long rev = PyInt_AS_LONG(value);
1391 return rev >= -1 && rev < index_length(self);
1454 return rev >= -1 && rev < index_length(self);
1392 }
1455 }
1393
1456
1394 if (node_check(value, &node) == -1)
1457 if (node_check(value, &node) == -1)
1395 return -1;
1458 return -1;
1396
1459
1397 switch (index_find_node(self, node, 20)) {
1460 switch (index_find_node(self, node, 20)) {
1398 case -3:
1461 case -3:
1399 return -1;
1462 return -1;
1400 case -2:
1463 case -2:
1401 return 0;
1464 return 0;
1402 default:
1465 default:
1403 return 1;
1466 return 1;
1404 }
1467 }
1405 }
1468 }
1406
1469
1407 typedef uint64_t bitmask;
1470 typedef uint64_t bitmask;
1408
1471
1409 /*
1472 /*
1410 * Given a disjoint set of revs, return all candidates for the
1473 * Given a disjoint set of revs, return all candidates for the
1411 * greatest common ancestor. In revset notation, this is the set
1474 * greatest common ancestor. In revset notation, this is the set
1412 * "heads(::a and ::b and ...)"
1475 * "heads(::a and ::b and ...)"
1413 */
1476 */
1414 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1477 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1415 int revcount)
1478 int revcount)
1416 {
1479 {
1417 const bitmask allseen = (1ull << revcount) - 1;
1480 const bitmask allseen = (1ull << revcount) - 1;
1418 const bitmask poison = 1ull << revcount;
1481 const bitmask poison = 1ull << revcount;
1419 PyObject *gca = PyList_New(0);
1482 PyObject *gca = PyList_New(0);
1420 int i, v, interesting;
1483 int i, v, interesting;
1421 int maxrev = -1;
1484 int maxrev = -1;
1422 bitmask sp;
1485 bitmask sp;
1423 bitmask *seen;
1486 bitmask *seen;
1424
1487
1425 if (gca == NULL)
1488 if (gca == NULL)
1426 return PyErr_NoMemory();
1489 return PyErr_NoMemory();
1427
1490
1428 for (i = 0; i < revcount; i++) {
1491 for (i = 0; i < revcount; i++) {
1429 if (revs[i] > maxrev)
1492 if (revs[i] > maxrev)
1430 maxrev = revs[i];
1493 maxrev = revs[i];
1431 }
1494 }
1432
1495
1433 seen = calloc(sizeof(*seen), maxrev + 1);
1496 seen = calloc(sizeof(*seen), maxrev + 1);
1434 if (seen == NULL) {
1497 if (seen == NULL) {
1435 Py_DECREF(gca);
1498 Py_DECREF(gca);
1436 return PyErr_NoMemory();
1499 return PyErr_NoMemory();
1437 }
1500 }
1438
1501
1439 for (i = 0; i < revcount; i++)
1502 for (i = 0; i < revcount; i++)
1440 seen[revs[i]] = 1ull << i;
1503 seen[revs[i]] = 1ull << i;
1441
1504
1442 interesting = revcount;
1505 interesting = revcount;
1443
1506
1444 for (v = maxrev; v >= 0 && interesting; v--) {
1507 for (v = maxrev; v >= 0 && interesting; v--) {
1445 bitmask sv = seen[v];
1508 bitmask sv = seen[v];
1446 int parents[2];
1509 int parents[2];
1447
1510
1448 if (!sv)
1511 if (!sv)
1449 continue;
1512 continue;
1450
1513
1451 if (sv < poison) {
1514 if (sv < poison) {
1452 interesting -= 1;
1515 interesting -= 1;
1453 if (sv == allseen) {
1516 if (sv == allseen) {
1454 PyObject *obj = PyInt_FromLong(v);
1517 PyObject *obj = PyInt_FromLong(v);
1455 if (obj == NULL)
1518 if (obj == NULL)
1456 goto bail;
1519 goto bail;
1457 if (PyList_Append(gca, obj) == -1) {
1520 if (PyList_Append(gca, obj) == -1) {
1458 Py_DECREF(obj);
1521 Py_DECREF(obj);
1459 goto bail;
1522 goto bail;
1460 }
1523 }
1461 sv |= poison;
1524 sv |= poison;
1462 for (i = 0; i < revcount; i++) {
1525 for (i = 0; i < revcount; i++) {
1463 if (revs[i] == v)
1526 if (revs[i] == v)
1464 goto done;
1527 goto done;
1465 }
1528 }
1466 }
1529 }
1467 }
1530 }
1468 if (index_get_parents(self, v, parents, maxrev) < 0)
1531 if (index_get_parents(self, v, parents, maxrev) < 0)
1469 goto bail;
1532 goto bail;
1470
1533
1471 for (i = 0; i < 2; i++) {
1534 for (i = 0; i < 2; i++) {
1472 int p = parents[i];
1535 int p = parents[i];
1473 if (p == -1)
1536 if (p == -1)
1474 continue;
1537 continue;
1475 sp = seen[p];
1538 sp = seen[p];
1476 if (sv < poison) {
1539 if (sv < poison) {
1477 if (sp == 0) {
1540 if (sp == 0) {
1478 seen[p] = sv;
1541 seen[p] = sv;
1479 interesting++;
1542 interesting++;
1480 }
1543 }
1481 else if (sp != sv)
1544 else if (sp != sv)
1482 seen[p] |= sv;
1545 seen[p] |= sv;
1483 } else {
1546 } else {
1484 if (sp && sp < poison)
1547 if (sp && sp < poison)
1485 interesting--;
1548 interesting--;
1486 seen[p] = sv;
1549 seen[p] = sv;
1487 }
1550 }
1488 }
1551 }
1489 }
1552 }
1490
1553
1491 done:
1554 done:
1492 free(seen);
1555 free(seen);
1493 return gca;
1556 return gca;
1494 bail:
1557 bail:
1495 free(seen);
1558 free(seen);
1496 Py_XDECREF(gca);
1559 Py_XDECREF(gca);
1497 return NULL;
1560 return NULL;
1498 }
1561 }
1499
1562
1500 /*
1563 /*
1501 * Given a disjoint set of revs, return the subset with the longest
1564 * Given a disjoint set of revs, return the subset with the longest
1502 * path to the root.
1565 * path to the root.
1503 */
1566 */
1504 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1567 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1505 {
1568 {
1506 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1569 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1507 static const Py_ssize_t capacity = 24;
1570 static const Py_ssize_t capacity = 24;
1508 int *depth, *interesting = NULL;
1571 int *depth, *interesting = NULL;
1509 int i, j, v, ninteresting;
1572 int i, j, v, ninteresting;
1510 PyObject *dict = NULL, *keys = NULL;
1573 PyObject *dict = NULL, *keys = NULL;
1511 long *seen = NULL;
1574 long *seen = NULL;
1512 int maxrev = -1;
1575 int maxrev = -1;
1513 long final;
1576 long final;
1514
1577
1515 if (revcount > capacity) {
1578 if (revcount > capacity) {
1516 PyErr_Format(PyExc_OverflowError,
1579 PyErr_Format(PyExc_OverflowError,
1517 "bitset size (%ld) > capacity (%ld)",
1580 "bitset size (%ld) > capacity (%ld)",
1518 (long)revcount, (long)capacity);
1581 (long)revcount, (long)capacity);
1519 return NULL;
1582 return NULL;
1520 }
1583 }
1521
1584
1522 for (i = 0; i < revcount; i++) {
1585 for (i = 0; i < revcount; i++) {
1523 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1586 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1524 if (n > maxrev)
1587 if (n > maxrev)
1525 maxrev = n;
1588 maxrev = n;
1526 }
1589 }
1527
1590
1528 depth = calloc(sizeof(*depth), maxrev + 1);
1591 depth = calloc(sizeof(*depth), maxrev + 1);
1529 if (depth == NULL)
1592 if (depth == NULL)
1530 return PyErr_NoMemory();
1593 return PyErr_NoMemory();
1531
1594
1532 seen = calloc(sizeof(*seen), maxrev + 1);
1595 seen = calloc(sizeof(*seen), maxrev + 1);
1533 if (seen == NULL) {
1596 if (seen == NULL) {
1534 PyErr_NoMemory();
1597 PyErr_NoMemory();
1535 goto bail;
1598 goto bail;
1536 }
1599 }
1537
1600
1538 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1601 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1539 if (interesting == NULL) {
1602 if (interesting == NULL) {
1540 PyErr_NoMemory();
1603 PyErr_NoMemory();
1541 goto bail;
1604 goto bail;
1542 }
1605 }
1543
1606
1544 if (PyList_Sort(revs) == -1)
1607 if (PyList_Sort(revs) == -1)
1545 goto bail;
1608 goto bail;
1546
1609
1547 for (i = 0; i < revcount; i++) {
1610 for (i = 0; i < revcount; i++) {
1548 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1611 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1549 long b = 1l << i;
1612 long b = 1l << i;
1550 depth[n] = 1;
1613 depth[n] = 1;
1551 seen[n] = b;
1614 seen[n] = b;
1552 interesting[b] = 1;
1615 interesting[b] = 1;
1553 }
1616 }
1554
1617
1555 /* invariant: ninteresting is the number of non-zero entries in
1618 /* invariant: ninteresting is the number of non-zero entries in
1556 * interesting. */
1619 * interesting. */
1557 ninteresting = (int)revcount;
1620 ninteresting = (int)revcount;
1558
1621
1559 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1622 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1560 int dv = depth[v];
1623 int dv = depth[v];
1561 int parents[2];
1624 int parents[2];
1562 long sv;
1625 long sv;
1563
1626
1564 if (dv == 0)
1627 if (dv == 0)
1565 continue;
1628 continue;
1566
1629
1567 sv = seen[v];
1630 sv = seen[v];
1568 if (index_get_parents(self, v, parents, maxrev) < 0)
1631 if (index_get_parents(self, v, parents, maxrev) < 0)
1569 goto bail;
1632 goto bail;
1570
1633
1571 for (i = 0; i < 2; i++) {
1634 for (i = 0; i < 2; i++) {
1572 int p = parents[i];
1635 int p = parents[i];
1573 long sp;
1636 long sp;
1574 int dp;
1637 int dp;
1575
1638
1576 if (p == -1)
1639 if (p == -1)
1577 continue;
1640 continue;
1578
1641
1579 dp = depth[p];
1642 dp = depth[p];
1580 sp = seen[p];
1643 sp = seen[p];
1581 if (dp <= dv) {
1644 if (dp <= dv) {
1582 depth[p] = dv + 1;
1645 depth[p] = dv + 1;
1583 if (sp != sv) {
1646 if (sp != sv) {
1584 interesting[sv] += 1;
1647 interesting[sv] += 1;
1585 seen[p] = sv;
1648 seen[p] = sv;
1586 if (sp) {
1649 if (sp) {
1587 interesting[sp] -= 1;
1650 interesting[sp] -= 1;
1588 if (interesting[sp] == 0)
1651 if (interesting[sp] == 0)
1589 ninteresting -= 1;
1652 ninteresting -= 1;
1590 }
1653 }
1591 }
1654 }
1592 }
1655 }
1593 else if (dv == dp - 1) {
1656 else if (dv == dp - 1) {
1594 long nsp = sp | sv;
1657 long nsp = sp | sv;
1595 if (nsp == sp)
1658 if (nsp == sp)
1596 continue;
1659 continue;
1597 seen[p] = nsp;
1660 seen[p] = nsp;
1598 interesting[sp] -= 1;
1661 interesting[sp] -= 1;
1599 if (interesting[sp] == 0)
1662 if (interesting[sp] == 0)
1600 ninteresting -= 1;
1663 ninteresting -= 1;
1601 if (interesting[nsp] == 0)
1664 if (interesting[nsp] == 0)
1602 ninteresting += 1;
1665 ninteresting += 1;
1603 interesting[nsp] += 1;
1666 interesting[nsp] += 1;
1604 }
1667 }
1605 }
1668 }
1606 interesting[sv] -= 1;
1669 interesting[sv] -= 1;
1607 if (interesting[sv] == 0)
1670 if (interesting[sv] == 0)
1608 ninteresting -= 1;
1671 ninteresting -= 1;
1609 }
1672 }
1610
1673
1611 final = 0;
1674 final = 0;
1612 j = ninteresting;
1675 j = ninteresting;
1613 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1676 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1614 if (interesting[i] == 0)
1677 if (interesting[i] == 0)
1615 continue;
1678 continue;
1616 final |= i;
1679 final |= i;
1617 j -= 1;
1680 j -= 1;
1618 }
1681 }
1619 if (final == 0) {
1682 if (final == 0) {
1620 keys = PyList_New(0);
1683 keys = PyList_New(0);
1621 goto bail;
1684 goto bail;
1622 }
1685 }
1623
1686
1624 dict = PyDict_New();
1687 dict = PyDict_New();
1625 if (dict == NULL)
1688 if (dict == NULL)
1626 goto bail;
1689 goto bail;
1627
1690
1628 for (i = 0; i < revcount; i++) {
1691 for (i = 0; i < revcount; i++) {
1629 PyObject *key;
1692 PyObject *key;
1630
1693
1631 if ((final & (1 << i)) == 0)
1694 if ((final & (1 << i)) == 0)
1632 continue;
1695 continue;
1633
1696
1634 key = PyList_GET_ITEM(revs, i);
1697 key = PyList_GET_ITEM(revs, i);
1635 Py_INCREF(key);
1698 Py_INCREF(key);
1636 Py_INCREF(Py_None);
1699 Py_INCREF(Py_None);
1637 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1700 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1638 Py_DECREF(key);
1701 Py_DECREF(key);
1639 Py_DECREF(Py_None);
1702 Py_DECREF(Py_None);
1640 goto bail;
1703 goto bail;
1641 }
1704 }
1642 }
1705 }
1643
1706
1644 keys = PyDict_Keys(dict);
1707 keys = PyDict_Keys(dict);
1645
1708
1646 bail:
1709 bail:
1647 free(depth);
1710 free(depth);
1648 free(seen);
1711 free(seen);
1649 free(interesting);
1712 free(interesting);
1650 Py_XDECREF(dict);
1713 Py_XDECREF(dict);
1651
1714
1652 return keys;
1715 return keys;
1653 }
1716 }
1654
1717
1655 /*
1718 /*
1656 * Given a (possibly overlapping) set of revs, return all the
1719 * Given a (possibly overlapping) set of revs, return all the
1657 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1720 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1658 */
1721 */
1659 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1722 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1660 {
1723 {
1661 PyObject *ret = NULL;
1724 PyObject *ret = NULL;
1662 Py_ssize_t argcount, i, len;
1725 Py_ssize_t argcount, i, len;
1663 bitmask repeat = 0;
1726 bitmask repeat = 0;
1664 int revcount = 0;
1727 int revcount = 0;
1665 int *revs;
1728 int *revs;
1666
1729
1667 argcount = PySequence_Length(args);
1730 argcount = PySequence_Length(args);
1668 revs = PyMem_Malloc(argcount * sizeof(*revs));
1731 revs = PyMem_Malloc(argcount * sizeof(*revs));
1669 if (argcount > 0 && revs == NULL)
1732 if (argcount > 0 && revs == NULL)
1670 return PyErr_NoMemory();
1733 return PyErr_NoMemory();
1671 len = index_length(self);
1734 len = index_length(self);
1672
1735
1673 for (i = 0; i < argcount; i++) {
1736 for (i = 0; i < argcount; i++) {
1674 static const int capacity = 24;
1737 static const int capacity = 24;
1675 PyObject *obj = PySequence_GetItem(args, i);
1738 PyObject *obj = PySequence_GetItem(args, i);
1676 bitmask x;
1739 bitmask x;
1677 long val;
1740 long val;
1678
1741
1679 if (!PyInt_Check(obj)) {
1742 if (!PyInt_Check(obj)) {
1680 PyErr_SetString(PyExc_TypeError,
1743 PyErr_SetString(PyExc_TypeError,
1681 "arguments must all be ints");
1744 "arguments must all be ints");
1682 Py_DECREF(obj);
1745 Py_DECREF(obj);
1683 goto bail;
1746 goto bail;
1684 }
1747 }
1685 val = PyInt_AsLong(obj);
1748 val = PyInt_AsLong(obj);
1686 Py_DECREF(obj);
1749 Py_DECREF(obj);
1687 if (val == -1) {
1750 if (val == -1) {
1688 ret = PyList_New(0);
1751 ret = PyList_New(0);
1689 goto done;
1752 goto done;
1690 }
1753 }
1691 if (val < 0 || val >= len) {
1754 if (val < 0 || val >= len) {
1692 PyErr_SetString(PyExc_IndexError,
1755 PyErr_SetString(PyExc_IndexError,
1693 "index out of range");
1756 "index out of range");
1694 goto bail;
1757 goto bail;
1695 }
1758 }
1696 /* this cheesy bloom filter lets us avoid some more
1759 /* this cheesy bloom filter lets us avoid some more
1697 * expensive duplicate checks in the common set-is-disjoint
1760 * expensive duplicate checks in the common set-is-disjoint
1698 * case */
1761 * case */
1699 x = 1ull << (val & 0x3f);
1762 x = 1ull << (val & 0x3f);
1700 if (repeat & x) {
1763 if (repeat & x) {
1701 int k;
1764 int k;
1702 for (k = 0; k < revcount; k++) {
1765 for (k = 0; k < revcount; k++) {
1703 if (val == revs[k])
1766 if (val == revs[k])
1704 goto duplicate;
1767 goto duplicate;
1705 }
1768 }
1706 }
1769 }
1707 else repeat |= x;
1770 else repeat |= x;
1708 if (revcount >= capacity) {
1771 if (revcount >= capacity) {
1709 PyErr_Format(PyExc_OverflowError,
1772 PyErr_Format(PyExc_OverflowError,
1710 "bitset size (%d) > capacity (%d)",
1773 "bitset size (%d) > capacity (%d)",
1711 revcount, capacity);
1774 revcount, capacity);
1712 goto bail;
1775 goto bail;
1713 }
1776 }
1714 revs[revcount++] = (int)val;
1777 revs[revcount++] = (int)val;
1715 duplicate:;
1778 duplicate:;
1716 }
1779 }
1717
1780
1718 if (revcount == 0) {
1781 if (revcount == 0) {
1719 ret = PyList_New(0);
1782 ret = PyList_New(0);
1720 goto done;
1783 goto done;
1721 }
1784 }
1722 if (revcount == 1) {
1785 if (revcount == 1) {
1723 PyObject *obj;
1786 PyObject *obj;
1724 ret = PyList_New(1);
1787 ret = PyList_New(1);
1725 if (ret == NULL)
1788 if (ret == NULL)
1726 goto bail;
1789 goto bail;
1727 obj = PyInt_FromLong(revs[0]);
1790 obj = PyInt_FromLong(revs[0]);
1728 if (obj == NULL)
1791 if (obj == NULL)
1729 goto bail;
1792 goto bail;
1730 PyList_SET_ITEM(ret, 0, obj);
1793 PyList_SET_ITEM(ret, 0, obj);
1731 goto done;
1794 goto done;
1732 }
1795 }
1733
1796
1734 ret = find_gca_candidates(self, revs, revcount);
1797 ret = find_gca_candidates(self, revs, revcount);
1735 if (ret == NULL)
1798 if (ret == NULL)
1736 goto bail;
1799 goto bail;
1737
1800
1738 done:
1801 done:
1739 PyMem_Free(revs);
1802 PyMem_Free(revs);
1740 return ret;
1803 return ret;
1741
1804
1742 bail:
1805 bail:
1743 PyMem_Free(revs);
1806 PyMem_Free(revs);
1744 Py_XDECREF(ret);
1807 Py_XDECREF(ret);
1745 return NULL;
1808 return NULL;
1746 }
1809 }
1747
1810
1748 /*
1811 /*
1749 * Given a (possibly overlapping) set of revs, return the greatest
1812 * Given a (possibly overlapping) set of revs, return the greatest
1750 * common ancestors: those with the longest path to the root.
1813 * common ancestors: those with the longest path to the root.
1751 */
1814 */
1752 static PyObject *index_ancestors(indexObject *self, PyObject *args)
1815 static PyObject *index_ancestors(indexObject *self, PyObject *args)
1753 {
1816 {
1754 PyObject *ret;
1817 PyObject *ret;
1755 PyObject *gca = index_commonancestorsheads(self, args);
1818 PyObject *gca = index_commonancestorsheads(self, args);
1756 if (gca == NULL)
1819 if (gca == NULL)
1757 return NULL;
1820 return NULL;
1758
1821
1759 if (PyList_GET_SIZE(gca) <= 1) {
1822 if (PyList_GET_SIZE(gca) <= 1) {
1760 return gca;
1823 return gca;
1761 }
1824 }
1762
1825
1763 ret = find_deepest(self, gca);
1826 ret = find_deepest(self, gca);
1764 Py_DECREF(gca);
1827 Py_DECREF(gca);
1765 return ret;
1828 return ret;
1766 }
1829 }
1767
1830
1768 /*
1831 /*
1769 * Invalidate any trie entries introduced by added revs.
1832 * Invalidate any trie entries introduced by added revs.
1770 */
1833 */
1771 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
1834 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
1772 {
1835 {
1773 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
1836 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
1774
1837
1775 for (i = start; i < len; i++) {
1838 for (i = start; i < len; i++) {
1776 PyObject *tuple = PyList_GET_ITEM(self->added, i);
1839 PyObject *tuple = PyList_GET_ITEM(self->added, i);
1777 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
1840 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
1778
1841
1779 nt_delete_node(self->nt, PyBytes_AS_STRING(node));
1842 nt_delete_node(self->nt, PyBytes_AS_STRING(node));
1780 }
1843 }
1781
1844
1782 if (start == 0)
1845 if (start == 0)
1783 Py_CLEAR(self->added);
1846 Py_CLEAR(self->added);
1784 }
1847 }
1785
1848
1786 /*
1849 /*
1787 * Delete a numeric range of revs, which must be at the end of the
1850 * Delete a numeric range of revs, which must be at the end of the
1788 * range, but exclude the sentinel nullid entry.
1851 * range, but exclude the sentinel nullid entry.
1789 */
1852 */
1790 static int index_slice_del(indexObject *self, PyObject *item)
1853 static int index_slice_del(indexObject *self, PyObject *item)
1791 {
1854 {
1792 Py_ssize_t start, stop, step, slicelength;
1855 Py_ssize_t start, stop, step, slicelength;
1793 Py_ssize_t length = index_length(self) + 1;
1856 Py_ssize_t length = index_length(self) + 1;
1794 int ret = 0;
1857 int ret = 0;
1795
1858
1796 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
1859 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
1797 #ifdef IS_PY3K
1860 #ifdef IS_PY3K
1798 if (PySlice_GetIndicesEx(item, length,
1861 if (PySlice_GetIndicesEx(item, length,
1799 #else
1862 #else
1800 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
1863 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
1801 #endif
1864 #endif
1802 &start, &stop, &step, &slicelength) < 0)
1865 &start, &stop, &step, &slicelength) < 0)
1803 return -1;
1866 return -1;
1804
1867
1805 if (slicelength <= 0)
1868 if (slicelength <= 0)
1806 return 0;
1869 return 0;
1807
1870
1808 if ((step < 0 && start < stop) || (step > 0 && start > stop))
1871 if ((step < 0 && start < stop) || (step > 0 && start > stop))
1809 stop = start;
1872 stop = start;
1810
1873
1811 if (step < 0) {
1874 if (step < 0) {
1812 stop = start + 1;
1875 stop = start + 1;
1813 start = stop + step*(slicelength - 1) - 1;
1876 start = stop + step*(slicelength - 1) - 1;
1814 step = -step;
1877 step = -step;
1815 }
1878 }
1816
1879
1817 if (step != 1) {
1880 if (step != 1) {
1818 PyErr_SetString(PyExc_ValueError,
1881 PyErr_SetString(PyExc_ValueError,
1819 "revlog index delete requires step size of 1");
1882 "revlog index delete requires step size of 1");
1820 return -1;
1883 return -1;
1821 }
1884 }
1822
1885
1823 if (stop != length - 1) {
1886 if (stop != length - 1) {
1824 PyErr_SetString(PyExc_IndexError,
1887 PyErr_SetString(PyExc_IndexError,
1825 "revlog index deletion indices are invalid");
1888 "revlog index deletion indices are invalid");
1826 return -1;
1889 return -1;
1827 }
1890 }
1828
1891
1829 if (start < self->length) {
1892 if (start < self->length) {
1830 if (self->nt) {
1893 if (self->nt) {
1831 Py_ssize_t i;
1894 Py_ssize_t i;
1832
1895
1833 for (i = start + 1; i < self->length; i++) {
1896 for (i = start + 1; i < self->length; i++) {
1834 const char *node = index_node_existing(self, i);
1897 const char *node = index_node_existing(self, i);
1835 if (node == NULL)
1898 if (node == NULL)
1836 return -1;
1899 return -1;
1837
1900
1838 nt_delete_node(self->nt, node);
1901 nt_delete_node(self->nt, node);
1839 }
1902 }
1840 if (self->added)
1903 if (self->added)
1841 index_invalidate_added(self, 0);
1904 index_invalidate_added(self, 0);
1842 if (self->ntrev > start)
1905 if (self->ntrev > start)
1843 self->ntrev = (int)start;
1906 self->ntrev = (int)start;
1844 }
1907 }
1845 self->length = start;
1908 self->length = start;
1846 if (start < self->raw_length) {
1909 if (start < self->raw_length) {
1847 if (self->cache) {
1910 if (self->cache) {
1848 Py_ssize_t i;
1911 Py_ssize_t i;
1849 for (i = start; i < self->raw_length; i++)
1912 for (i = start; i < self->raw_length; i++)
1850 Py_CLEAR(self->cache[i]);
1913 Py_CLEAR(self->cache[i]);
1851 }
1914 }
1852 self->raw_length = start;
1915 self->raw_length = start;
1853 }
1916 }
1854 goto done;
1917 goto done;
1855 }
1918 }
1856
1919
1857 if (self->nt) {
1920 if (self->nt) {
1858 index_invalidate_added(self, start - self->length);
1921 index_invalidate_added(self, start - self->length);
1859 if (self->ntrev > start)
1922 if (self->ntrev > start)
1860 self->ntrev = (int)start;
1923 self->ntrev = (int)start;
1861 }
1924 }
1862 if (self->added)
1925 if (self->added)
1863 ret = PyList_SetSlice(self->added, start - self->length,
1926 ret = PyList_SetSlice(self->added, start - self->length,
1864 PyList_GET_SIZE(self->added), NULL);
1927 PyList_GET_SIZE(self->added), NULL);
1865 done:
1928 done:
1866 Py_CLEAR(self->headrevs);
1929 Py_CLEAR(self->headrevs);
1867 return ret;
1930 return ret;
1868 }
1931 }
1869
1932
1870 /*
1933 /*
1871 * Supported ops:
1934 * Supported ops:
1872 *
1935 *
1873 * slice deletion
1936 * slice deletion
1874 * string assignment (extend node->rev mapping)
1937 * string assignment (extend node->rev mapping)
1875 * string deletion (shrink node->rev mapping)
1938 * string deletion (shrink node->rev mapping)
1876 */
1939 */
1877 static int index_assign_subscript(indexObject *self, PyObject *item,
1940 static int index_assign_subscript(indexObject *self, PyObject *item,
1878 PyObject *value)
1941 PyObject *value)
1879 {
1942 {
1880 char *node;
1943 char *node;
1881 long rev;
1944 long rev;
1882
1945
1883 if (PySlice_Check(item) && value == NULL)
1946 if (PySlice_Check(item) && value == NULL)
1884 return index_slice_del(self, item);
1947 return index_slice_del(self, item);
1885
1948
1886 if (node_check(item, &node) == -1)
1949 if (node_check(item, &node) == -1)
1887 return -1;
1950 return -1;
1888
1951
1889 if (value == NULL)
1952 if (value == NULL)
1890 return self->nt ? nt_delete_node(self->nt, node) : 0;
1953 return self->nt ? nt_delete_node(self->nt, node) : 0;
1891 rev = PyInt_AsLong(value);
1954 rev = PyInt_AsLong(value);
1892 if (rev > INT_MAX || rev < 0) {
1955 if (rev > INT_MAX || rev < 0) {
1893 if (!PyErr_Occurred())
1956 if (!PyErr_Occurred())
1894 PyErr_SetString(PyExc_ValueError, "rev out of range");
1957 PyErr_SetString(PyExc_ValueError, "rev out of range");
1895 return -1;
1958 return -1;
1896 }
1959 }
1897
1960
1898 if (index_init_nt(self) == -1)
1961 if (index_init_nt(self) == -1)
1899 return -1;
1962 return -1;
1900 return nt_insert(self->nt, node, (int)rev);
1963 return nt_insert(self->nt, node, (int)rev);
1901 }
1964 }
1902
1965
1903 /*
1966 /*
1904 * Find all RevlogNG entries in an index that has inline data. Update
1967 * Find all RevlogNG entries in an index that has inline data. Update
1905 * the optional "offsets" table with those entries.
1968 * the optional "offsets" table with those entries.
1906 */
1969 */
1907 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
1970 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
1908 {
1971 {
1909 const char *data = (const char *)self->buf.buf;
1972 const char *data = (const char *)self->buf.buf;
1910 Py_ssize_t pos = 0;
1973 Py_ssize_t pos = 0;
1911 Py_ssize_t end = self->buf.len;
1974 Py_ssize_t end = self->buf.len;
1912 long incr = v1_hdrsize;
1975 long incr = v1_hdrsize;
1913 Py_ssize_t len = 0;
1976 Py_ssize_t len = 0;
1914
1977
1915 while (pos + v1_hdrsize <= end && pos >= 0) {
1978 while (pos + v1_hdrsize <= end && pos >= 0) {
1916 uint32_t comp_len;
1979 uint32_t comp_len;
1917 /* 3rd element of header is length of compressed inline data */
1980 /* 3rd element of header is length of compressed inline data */
1918 comp_len = getbe32(data + pos + 8);
1981 comp_len = getbe32(data + pos + 8);
1919 incr = v1_hdrsize + comp_len;
1982 incr = v1_hdrsize + comp_len;
1920 if (offsets)
1983 if (offsets)
1921 offsets[len] = data + pos;
1984 offsets[len] = data + pos;
1922 len++;
1985 len++;
1923 pos += incr;
1986 pos += incr;
1924 }
1987 }
1925
1988
1926 if (pos != end) {
1989 if (pos != end) {
1927 if (!PyErr_Occurred())
1990 if (!PyErr_Occurred())
1928 PyErr_SetString(PyExc_ValueError, "corrupt index file");
1991 PyErr_SetString(PyExc_ValueError, "corrupt index file");
1929 return -1;
1992 return -1;
1930 }
1993 }
1931
1994
1932 return len;
1995 return len;
1933 }
1996 }
1934
1997
1935 static int index_init(indexObject *self, PyObject *args)
1998 static int index_init(indexObject *self, PyObject *args)
1936 {
1999 {
1937 PyObject *data_obj, *inlined_obj;
2000 PyObject *data_obj, *inlined_obj;
1938 Py_ssize_t size;
2001 Py_ssize_t size;
1939
2002
1940 /* Initialize before argument-checking to avoid index_dealloc() crash. */
2003 /* Initialize before argument-checking to avoid index_dealloc() crash. */
1941 self->raw_length = 0;
2004 self->raw_length = 0;
1942 self->added = NULL;
2005 self->added = NULL;
1943 self->cache = NULL;
2006 self->cache = NULL;
1944 self->data = NULL;
2007 self->data = NULL;
1945 memset(&self->buf, 0, sizeof(self->buf));
2008 memset(&self->buf, 0, sizeof(self->buf));
1946 self->headrevs = NULL;
2009 self->headrevs = NULL;
1947 self->filteredrevs = Py_None;
2010 self->filteredrevs = Py_None;
1948 Py_INCREF(Py_None);
2011 Py_INCREF(Py_None);
1949 self->nt = NULL;
2012 self->nt = NULL;
1950 self->offsets = NULL;
2013 self->offsets = NULL;
1951
2014
1952 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2015 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
1953 return -1;
2016 return -1;
1954 if (!PyObject_CheckBuffer(data_obj)) {
2017 if (!PyObject_CheckBuffer(data_obj)) {
1955 PyErr_SetString(PyExc_TypeError,
2018 PyErr_SetString(PyExc_TypeError,
1956 "data does not support buffer interface");
2019 "data does not support buffer interface");
1957 return -1;
2020 return -1;
1958 }
2021 }
1959
2022
1960 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2023 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
1961 return -1;
2024 return -1;
1962 size = self->buf.len;
2025 size = self->buf.len;
1963
2026
1964 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
2027 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
1965 self->data = data_obj;
2028 self->data = data_obj;
1966
2029
1967 self->ntlookups = self->ntmisses = 0;
2030 self->ntlookups = self->ntmisses = 0;
1968 self->ntrev = -1;
2031 self->ntrev = -1;
1969 Py_INCREF(self->data);
2032 Py_INCREF(self->data);
1970
2033
1971 if (self->inlined) {
2034 if (self->inlined) {
1972 Py_ssize_t len = inline_scan(self, NULL);
2035 Py_ssize_t len = inline_scan(self, NULL);
1973 if (len == -1)
2036 if (len == -1)
1974 goto bail;
2037 goto bail;
1975 self->raw_length = len;
2038 self->raw_length = len;
1976 self->length = len;
2039 self->length = len;
1977 } else {
2040 } else {
1978 if (size % v1_hdrsize) {
2041 if (size % v1_hdrsize) {
1979 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2042 PyErr_SetString(PyExc_ValueError, "corrupt index file");
1980 goto bail;
2043 goto bail;
1981 }
2044 }
1982 self->raw_length = size / v1_hdrsize;
2045 self->raw_length = size / v1_hdrsize;
1983 self->length = self->raw_length;
2046 self->length = self->raw_length;
1984 }
2047 }
1985
2048
1986 return 0;
2049 return 0;
1987 bail:
2050 bail:
1988 return -1;
2051 return -1;
1989 }
2052 }
1990
2053
1991 static PyObject *index_nodemap(indexObject *self)
2054 static PyObject *index_nodemap(indexObject *self)
1992 {
2055 {
1993 Py_INCREF(self);
2056 Py_INCREF(self);
1994 return (PyObject *)self;
2057 return (PyObject *)self;
1995 }
2058 }
1996
2059
1997 static void _index_clearcaches(indexObject *self)
2060 static void _index_clearcaches(indexObject *self)
1998 {
2061 {
1999 if (self->cache) {
2062 if (self->cache) {
2000 Py_ssize_t i;
2063 Py_ssize_t i;
2001
2064
2002 for (i = 0; i < self->raw_length; i++)
2065 for (i = 0; i < self->raw_length; i++)
2003 Py_CLEAR(self->cache[i]);
2066 Py_CLEAR(self->cache[i]);
2004 free(self->cache);
2067 free(self->cache);
2005 self->cache = NULL;
2068 self->cache = NULL;
2006 }
2069 }
2007 if (self->offsets) {
2070 if (self->offsets) {
2008 PyMem_Free((void *)self->offsets);
2071 PyMem_Free((void *)self->offsets);
2009 self->offsets = NULL;
2072 self->offsets = NULL;
2010 }
2073 }
2011 if (self->nt != NULL) {
2074 if (self->nt != NULL) {
2012 free(self->nt->nodes);
2075 nt_dealloc(self->nt);
2013 PyMem_Free(self->nt);
2014 }
2076 }
2015 self->nt = NULL;
2077 self->nt = NULL;
2016 Py_CLEAR(self->headrevs);
2078 Py_CLEAR(self->headrevs);
2017 }
2079 }
2018
2080
2019 static PyObject *index_clearcaches(indexObject *self)
2081 static PyObject *index_clearcaches(indexObject *self)
2020 {
2082 {
2021 _index_clearcaches(self);
2083 _index_clearcaches(self);
2022 self->ntrev = -1;
2084 self->ntrev = -1;
2023 self->ntlookups = self->ntmisses = 0;
2085 self->ntlookups = self->ntmisses = 0;
2024 Py_RETURN_NONE;
2086 Py_RETURN_NONE;
2025 }
2087 }
2026
2088
2027 static void index_dealloc(indexObject *self)
2089 static void index_dealloc(indexObject *self)
2028 {
2090 {
2029 _index_clearcaches(self);
2091 _index_clearcaches(self);
2030 Py_XDECREF(self->filteredrevs);
2092 Py_XDECREF(self->filteredrevs);
2031 if (self->buf.buf) {
2093 if (self->buf.buf) {
2032 PyBuffer_Release(&self->buf);
2094 PyBuffer_Release(&self->buf);
2033 memset(&self->buf, 0, sizeof(self->buf));
2095 memset(&self->buf, 0, sizeof(self->buf));
2034 }
2096 }
2035 Py_XDECREF(self->data);
2097 Py_XDECREF(self->data);
2036 Py_XDECREF(self->added);
2098 Py_XDECREF(self->added);
2099 Py_XDECREF(self->nt);
2037 PyObject_Del(self);
2100 PyObject_Del(self);
2038 }
2101 }
2039
2102
2040 static PySequenceMethods index_sequence_methods = {
2103 static PySequenceMethods index_sequence_methods = {
2041 (lenfunc)index_length, /* sq_length */
2104 (lenfunc)index_length, /* sq_length */
2042 0, /* sq_concat */
2105 0, /* sq_concat */
2043 0, /* sq_repeat */
2106 0, /* sq_repeat */
2044 (ssizeargfunc)index_get, /* sq_item */
2107 (ssizeargfunc)index_get, /* sq_item */
2045 0, /* sq_slice */
2108 0, /* sq_slice */
2046 0, /* sq_ass_item */
2109 0, /* sq_ass_item */
2047 0, /* sq_ass_slice */
2110 0, /* sq_ass_slice */
2048 (objobjproc)index_contains, /* sq_contains */
2111 (objobjproc)index_contains, /* sq_contains */
2049 };
2112 };
2050
2113
2051 static PyMappingMethods index_mapping_methods = {
2114 static PyMappingMethods index_mapping_methods = {
2052 (lenfunc)index_length, /* mp_length */
2115 (lenfunc)index_length, /* mp_length */
2053 (binaryfunc)index_getitem, /* mp_subscript */
2116 (binaryfunc)index_getitem, /* mp_subscript */
2054 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2117 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2055 };
2118 };
2056
2119
2057 static PyMethodDef index_methods[] = {
2120 static PyMethodDef index_methods[] = {
2058 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2121 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2059 "return the gca set of the given revs"},
2122 "return the gca set of the given revs"},
2060 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2123 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2061 METH_VARARGS,
2124 METH_VARARGS,
2062 "return the heads of the common ancestors of the given revs"},
2125 "return the heads of the common ancestors of the given revs"},
2063 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2126 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2064 "clear the index caches"},
2127 "clear the index caches"},
2065 {"get", (PyCFunction)index_m_get, METH_VARARGS,
2128 {"get", (PyCFunction)index_m_get, METH_VARARGS,
2066 "get an index entry"},
2129 "get an index entry"},
2067 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets,
2130 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets,
2068 METH_VARARGS, "compute phases"},
2131 METH_VARARGS, "compute phases"},
2069 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2132 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2070 "reachableroots"},
2133 "reachableroots"},
2071 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2134 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2072 "get head revisions"}, /* Can do filtering since 3.2 */
2135 "get head revisions"}, /* Can do filtering since 3.2 */
2073 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2136 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2074 "get filtered head revisions"}, /* Can always do filtering */
2137 "get filtered head revisions"}, /* Can always do filtering */
2075 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2138 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2076 "determine revisions with deltas to reconstruct fulltext"},
2139 "determine revisions with deltas to reconstruct fulltext"},
2077 {"append", (PyCFunction)index_append, METH_O,
2140 {"append", (PyCFunction)index_append, METH_O,
2078 "append an index entry"},
2141 "append an index entry"},
2079 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2142 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2080 "match a potentially ambiguous node ID"},
2143 "match a potentially ambiguous node ID"},
2081 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2144 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2082 "find length of shortest hex nodeid of a binary ID"},
2145 "find length of shortest hex nodeid of a binary ID"},
2083 {"stats", (PyCFunction)index_stats, METH_NOARGS,
2146 {"stats", (PyCFunction)index_stats, METH_NOARGS,
2084 "stats for the index"},
2147 "stats for the index"},
2085 {NULL} /* Sentinel */
2148 {NULL} /* Sentinel */
2086 };
2149 };
2087
2150
2088 static PyGetSetDef index_getset[] = {
2151 static PyGetSetDef index_getset[] = {
2089 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2152 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2090 {NULL} /* Sentinel */
2153 {NULL} /* Sentinel */
2091 };
2154 };
2092
2155
2093 static PyTypeObject indexType = {
2156 static PyTypeObject indexType = {
2094 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2157 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2095 "parsers.index", /* tp_name */
2158 "parsers.index", /* tp_name */
2096 sizeof(indexObject), /* tp_basicsize */
2159 sizeof(indexObject), /* tp_basicsize */
2097 0, /* tp_itemsize */
2160 0, /* tp_itemsize */
2098 (destructor)index_dealloc, /* tp_dealloc */
2161 (destructor)index_dealloc, /* tp_dealloc */
2099 0, /* tp_print */
2162 0, /* tp_print */
2100 0, /* tp_getattr */
2163 0, /* tp_getattr */
2101 0, /* tp_setattr */
2164 0, /* tp_setattr */
2102 0, /* tp_compare */
2165 0, /* tp_compare */
2103 0, /* tp_repr */
2166 0, /* tp_repr */
2104 0, /* tp_as_number */
2167 0, /* tp_as_number */
2105 &index_sequence_methods, /* tp_as_sequence */
2168 &index_sequence_methods, /* tp_as_sequence */
2106 &index_mapping_methods, /* tp_as_mapping */
2169 &index_mapping_methods, /* tp_as_mapping */
2107 0, /* tp_hash */
2170 0, /* tp_hash */
2108 0, /* tp_call */
2171 0, /* tp_call */
2109 0, /* tp_str */
2172 0, /* tp_str */
2110 0, /* tp_getattro */
2173 0, /* tp_getattro */
2111 0, /* tp_setattro */
2174 0, /* tp_setattro */
2112 0, /* tp_as_buffer */
2175 0, /* tp_as_buffer */
2113 Py_TPFLAGS_DEFAULT, /* tp_flags */
2176 Py_TPFLAGS_DEFAULT, /* tp_flags */
2114 "revlog index", /* tp_doc */
2177 "revlog index", /* tp_doc */
2115 0, /* tp_traverse */
2178 0, /* tp_traverse */
2116 0, /* tp_clear */
2179 0, /* tp_clear */
2117 0, /* tp_richcompare */
2180 0, /* tp_richcompare */
2118 0, /* tp_weaklistoffset */
2181 0, /* tp_weaklistoffset */
2119 0, /* tp_iter */
2182 0, /* tp_iter */
2120 0, /* tp_iternext */
2183 0, /* tp_iternext */
2121 index_methods, /* tp_methods */
2184 index_methods, /* tp_methods */
2122 0, /* tp_members */
2185 0, /* tp_members */
2123 index_getset, /* tp_getset */
2186 index_getset, /* tp_getset */
2124 0, /* tp_base */
2187 0, /* tp_base */
2125 0, /* tp_dict */
2188 0, /* tp_dict */
2126 0, /* tp_descr_get */
2189 0, /* tp_descr_get */
2127 0, /* tp_descr_set */
2190 0, /* tp_descr_set */
2128 0, /* tp_dictoffset */
2191 0, /* tp_dictoffset */
2129 (initproc)index_init, /* tp_init */
2192 (initproc)index_init, /* tp_init */
2130 0, /* tp_alloc */
2193 0, /* tp_alloc */
2131 };
2194 };
2132
2195
2133 /*
2196 /*
2134 * returns a tuple of the form (index, index, cache) with elements as
2197 * returns a tuple of the form (index, index, cache) with elements as
2135 * follows:
2198 * follows:
2136 *
2199 *
2137 * index: an index object that lazily parses RevlogNG records
2200 * index: an index object that lazily parses RevlogNG records
2138 * cache: if data is inlined, a tuple (0, index_file_content), else None
2201 * cache: if data is inlined, a tuple (0, index_file_content), else None
2139 * index_file_content could be a string, or a buffer
2202 * index_file_content could be a string, or a buffer
2140 *
2203 *
2141 * added complications are for backwards compatibility
2204 * added complications are for backwards compatibility
2142 */
2205 */
2143 PyObject *parse_index2(PyObject *self, PyObject *args)
2206 PyObject *parse_index2(PyObject *self, PyObject *args)
2144 {
2207 {
2145 PyObject *tuple = NULL, *cache = NULL;
2208 PyObject *tuple = NULL, *cache = NULL;
2146 indexObject *idx;
2209 indexObject *idx;
2147 int ret;
2210 int ret;
2148
2211
2149 idx = PyObject_New(indexObject, &indexType);
2212 idx = PyObject_New(indexObject, &indexType);
2150 if (idx == NULL)
2213 if (idx == NULL)
2151 goto bail;
2214 goto bail;
2152
2215
2153 ret = index_init(idx, args);
2216 ret = index_init(idx, args);
2154 if (ret == -1)
2217 if (ret == -1)
2155 goto bail;
2218 goto bail;
2156
2219
2157 if (idx->inlined) {
2220 if (idx->inlined) {
2158 cache = Py_BuildValue("iO", 0, idx->data);
2221 cache = Py_BuildValue("iO", 0, idx->data);
2159 if (cache == NULL)
2222 if (cache == NULL)
2160 goto bail;
2223 goto bail;
2161 } else {
2224 } else {
2162 cache = Py_None;
2225 cache = Py_None;
2163 Py_INCREF(cache);
2226 Py_INCREF(cache);
2164 }
2227 }
2165
2228
2166 tuple = Py_BuildValue("NN", idx, cache);
2229 tuple = Py_BuildValue("NN", idx, cache);
2167 if (!tuple)
2230 if (!tuple)
2168 goto bail;
2231 goto bail;
2169 return tuple;
2232 return tuple;
2170
2233
2171 bail:
2234 bail:
2172 Py_XDECREF(idx);
2235 Py_XDECREF(idx);
2173 Py_XDECREF(cache);
2236 Py_XDECREF(cache);
2174 Py_XDECREF(tuple);
2237 Py_XDECREF(tuple);
2175 return NULL;
2238 return NULL;
2176 }
2239 }
2177
2240
2178 void revlog_module_init(PyObject *mod)
2241 void revlog_module_init(PyObject *mod)
2179 {
2242 {
2180 indexType.tp_new = PyType_GenericNew;
2243 indexType.tp_new = PyType_GenericNew;
2181 if (PyType_Ready(&indexType) < 0)
2244 if (PyType_Ready(&indexType) < 0)
2182 return;
2245 return;
2183 Py_INCREF(&indexType);
2246 Py_INCREF(&indexType);
2184 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2247 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2185
2248
2249 nodetreeType.tp_new = PyType_GenericNew;
2250 if (PyType_Ready(&nodetreeType) < 0)
2251 return;
2252 Py_INCREF(&nodetreeType);
2253 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2254
2186 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
2255 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
2187 -1, -1, -1, -1, nullid, 20);
2256 -1, -1, -1, -1, nullid, 20);
2188 if (nullentry)
2257 if (nullentry)
2189 PyObject_GC_UnTrack(nullentry);
2258 PyObject_GC_UnTrack(nullentry);
2190 }
2259 }
@@ -1,109 +1,109
1 # policy.py - module policy logic for Mercurial.
1 # policy.py - module policy logic for Mercurial.
2 #
2 #
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import sys
11 import sys
12
12
13 # Rules for how modules can be loaded. Values are:
13 # Rules for how modules can be loaded. Values are:
14 #
14 #
15 # c - require C extensions
15 # c - require C extensions
16 # allow - allow pure Python implementation when C loading fails
16 # allow - allow pure Python implementation when C loading fails
17 # cffi - required cffi versions (implemented within pure module)
17 # cffi - required cffi versions (implemented within pure module)
18 # cffi-allow - allow pure Python implementation if cffi version is missing
18 # cffi-allow - allow pure Python implementation if cffi version is missing
19 # py - only load pure Python modules
19 # py - only load pure Python modules
20 #
20 #
21 # By default, fall back to the pure modules so the in-place build can
21 # By default, fall back to the pure modules so the in-place build can
22 # run without recompiling the C extensions. This will be overridden by
22 # run without recompiling the C extensions. This will be overridden by
23 # __modulepolicy__ generated by setup.py.
23 # __modulepolicy__ generated by setup.py.
24 policy = b'allow'
24 policy = b'allow'
25 _packageprefs = {
25 _packageprefs = {
26 # policy: (versioned package, pure package)
26 # policy: (versioned package, pure package)
27 b'c': (r'cext', None),
27 b'c': (r'cext', None),
28 b'allow': (r'cext', r'pure'),
28 b'allow': (r'cext', r'pure'),
29 b'cffi': (r'cffi', None),
29 b'cffi': (r'cffi', None),
30 b'cffi-allow': (r'cffi', r'pure'),
30 b'cffi-allow': (r'cffi', r'pure'),
31 b'py': (None, r'pure'),
31 b'py': (None, r'pure'),
32 }
32 }
33
33
34 try:
34 try:
35 from . import __modulepolicy__
35 from . import __modulepolicy__
36 policy = __modulepolicy__.modulepolicy
36 policy = __modulepolicy__.modulepolicy
37 except ImportError:
37 except ImportError:
38 pass
38 pass
39
39
40 # PyPy doesn't load C extensions.
40 # PyPy doesn't load C extensions.
41 #
41 #
42 # The canonical way to do this is to test platform.python_implementation().
42 # The canonical way to do this is to test platform.python_implementation().
43 # But we don't import platform and don't bloat for it here.
43 # But we don't import platform and don't bloat for it here.
44 if r'__pypy__' in sys.builtin_module_names:
44 if r'__pypy__' in sys.builtin_module_names:
45 policy = b'cffi'
45 policy = b'cffi'
46
46
47 # Environment variable can always force settings.
47 # Environment variable can always force settings.
48 if sys.version_info[0] >= 3:
48 if sys.version_info[0] >= 3:
49 if r'HGMODULEPOLICY' in os.environ:
49 if r'HGMODULEPOLICY' in os.environ:
50 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
50 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
51 else:
51 else:
52 policy = os.environ.get(r'HGMODULEPOLICY', policy)
52 policy = os.environ.get(r'HGMODULEPOLICY', policy)
53
53
54 def _importfrom(pkgname, modname):
54 def _importfrom(pkgname, modname):
55 # from .<pkgname> import <modname> (where . is looked through this module)
55 # from .<pkgname> import <modname> (where . is looked through this module)
56 fakelocals = {}
56 fakelocals = {}
57 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
57 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
58 try:
58 try:
59 fakelocals[modname] = mod = getattr(pkg, modname)
59 fakelocals[modname] = mod = getattr(pkg, modname)
60 except AttributeError:
60 except AttributeError:
61 raise ImportError(r'cannot import name %s' % modname)
61 raise ImportError(r'cannot import name %s' % modname)
62 # force import; fakelocals[modname] may be replaced with the real module
62 # force import; fakelocals[modname] may be replaced with the real module
63 getattr(mod, r'__doc__', None)
63 getattr(mod, r'__doc__', None)
64 return fakelocals[modname]
64 return fakelocals[modname]
65
65
66 # keep in sync with "version" in C modules
66 # keep in sync with "version" in C modules
67 _cextversions = {
67 _cextversions = {
68 (r'cext', r'base85'): 1,
68 (r'cext', r'base85'): 1,
69 (r'cext', r'bdiff'): 3,
69 (r'cext', r'bdiff'): 3,
70 (r'cext', r'mpatch'): 1,
70 (r'cext', r'mpatch'): 1,
71 (r'cext', r'osutil'): 4,
71 (r'cext', r'osutil'): 4,
72 (r'cext', r'parsers'): 7,
72 (r'cext', r'parsers'): 8,
73 }
73 }
74
74
75 # map import request to other package or module
75 # map import request to other package or module
76 _modredirects = {
76 _modredirects = {
77 (r'cext', r'charencode'): (r'cext', r'parsers'),
77 (r'cext', r'charencode'): (r'cext', r'parsers'),
78 (r'cffi', r'base85'): (r'pure', r'base85'),
78 (r'cffi', r'base85'): (r'pure', r'base85'),
79 (r'cffi', r'charencode'): (r'pure', r'charencode'),
79 (r'cffi', r'charencode'): (r'pure', r'charencode'),
80 (r'cffi', r'parsers'): (r'pure', r'parsers'),
80 (r'cffi', r'parsers'): (r'pure', r'parsers'),
81 }
81 }
82
82
83 def _checkmod(pkgname, modname, mod):
83 def _checkmod(pkgname, modname, mod):
84 expected = _cextversions.get((pkgname, modname))
84 expected = _cextversions.get((pkgname, modname))
85 actual = getattr(mod, r'version', None)
85 actual = getattr(mod, r'version', None)
86 if actual != expected:
86 if actual != expected:
87 raise ImportError(r'cannot import module %s.%s '
87 raise ImportError(r'cannot import module %s.%s '
88 r'(expected version: %d, actual: %r)'
88 r'(expected version: %d, actual: %r)'
89 % (pkgname, modname, expected, actual))
89 % (pkgname, modname, expected, actual))
90
90
91 def importmod(modname):
91 def importmod(modname):
92 """Import module according to policy and check API version"""
92 """Import module according to policy and check API version"""
93 try:
93 try:
94 verpkg, purepkg = _packageprefs[policy]
94 verpkg, purepkg = _packageprefs[policy]
95 except KeyError:
95 except KeyError:
96 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
96 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
97 assert verpkg or purepkg
97 assert verpkg or purepkg
98 if verpkg:
98 if verpkg:
99 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
99 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
100 try:
100 try:
101 mod = _importfrom(pn, mn)
101 mod = _importfrom(pn, mn)
102 if pn == verpkg:
102 if pn == verpkg:
103 _checkmod(pn, mn, mod)
103 _checkmod(pn, mn, mod)
104 return mod
104 return mod
105 except ImportError:
105 except ImportError:
106 if not purepkg:
106 if not purepkg:
107 raise
107 raise
108 pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname))
108 pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname))
109 return _importfrom(pn, mn)
109 return _importfrom(pn, mn)
General Comments 0
You need to be logged in to leave comments. Login now