##// END OF EJS Templates
sparse-revlog: add a `index_segment_span` function in C...
Boris Feld -
r40741:4ec6a240 default
parent child Browse files
Show More
@@ -1,2577 +1,2605 b''
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <assert.h>
11 #include <assert.h>
12 #include <ctype.h>
12 #include <ctype.h>
13 #include <limits.h>
13 #include <limits.h>
14 #include <stddef.h>
14 #include <stddef.h>
15 #include <string.h>
15 #include <string.h>
16
16
17 #include "bitmanipulation.h"
17 #include "bitmanipulation.h"
18 #include "charencode.h"
18 #include "charencode.h"
19 #include "util.h"
19 #include "util.h"
20
20
21 #ifdef IS_PY3K
21 #ifdef IS_PY3K
22 /* The mapping of Python types is meant to be temporary to get Python
22 /* The mapping of Python types is meant to be temporary to get Python
23 * 3 to compile. We should remove this once Python 3 support is fully
23 * 3 to compile. We should remove this once Python 3 support is fully
24 * supported and proper types are used in the extensions themselves. */
24 * supported and proper types are used in the extensions themselves. */
25 #define PyInt_Check PyLong_Check
25 #define PyInt_Check PyLong_Check
26 #define PyInt_FromLong PyLong_FromLong
26 #define PyInt_FromLong PyLong_FromLong
27 #define PyInt_FromSsize_t PyLong_FromSsize_t
27 #define PyInt_FromSsize_t PyLong_FromSsize_t
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 indexObject *index;
45 indexObject *index;
46 nodetreenode *nodes;
46 nodetreenode *nodes;
47 unsigned length; /* # nodes in use */
47 unsigned length; /* # nodes in use */
48 unsigned capacity; /* # nodes allocated */
48 unsigned capacity; /* # nodes allocated */
49 int depth; /* maximum depth of tree */
49 int depth; /* maximum depth of tree */
50 int splits; /* # splits performed */
50 int splits; /* # splits performed */
51 } nodetree;
51 } nodetree;
52
52
53 typedef struct {
53 typedef struct {
54 PyObject_HEAD /* ; */
54 PyObject_HEAD /* ; */
55 nodetree nt;
55 nodetree nt;
56 } nodetreeObject;
56 } nodetreeObject;
57
57
58 /*
58 /*
59 * This class has two behaviors.
59 * This class has two behaviors.
60 *
60 *
61 * When used in a list-like way (with integer keys), we decode an
61 * When used in a list-like way (with integer keys), we decode an
62 * entry in a RevlogNG index file on demand. Our last entry is a
62 * entry in a RevlogNG index file on demand. Our last entry is a
63 * sentinel, always a nullid. We have limited support for
63 * sentinel, always a nullid. We have limited support for
64 * integer-keyed insert and delete, only at elements right before the
64 * integer-keyed insert and delete, only at elements right before the
65 * sentinel.
65 * sentinel.
66 *
66 *
67 * With string keys, we lazily perform a reverse mapping from node to
67 * With string keys, we lazily perform a reverse mapping from node to
68 * rev, using a base-16 trie.
68 * rev, using a base-16 trie.
69 */
69 */
70 struct indexObjectStruct {
70 struct indexObjectStruct {
71 PyObject_HEAD
71 PyObject_HEAD
72 /* Type-specific fields go here. */
72 /* Type-specific fields go here. */
73 PyObject *data; /* raw bytes of index */
73 PyObject *data; /* raw bytes of index */
74 Py_buffer buf; /* buffer of data */
74 Py_buffer buf; /* buffer of data */
75 PyObject **cache; /* cached tuples */
75 PyObject **cache; /* cached tuples */
76 const char **offsets; /* populated on demand */
76 const char **offsets; /* populated on demand */
77 Py_ssize_t raw_length; /* original number of elements */
77 Py_ssize_t raw_length; /* original number of elements */
78 Py_ssize_t length; /* current number of elements */
78 Py_ssize_t length; /* current number of elements */
79 PyObject *added; /* populated on demand */
79 PyObject *added; /* populated on demand */
80 PyObject *headrevs; /* cache, invalidated on changes */
80 PyObject *headrevs; /* cache, invalidated on changes */
81 PyObject *filteredrevs; /* filtered revs set */
81 PyObject *filteredrevs; /* filtered revs set */
82 nodetree nt; /* base-16 trie */
82 nodetree nt; /* base-16 trie */
83 int ntinitialized; /* 0 or 1 */
83 int ntinitialized; /* 0 or 1 */
84 int ntrev; /* last rev scanned */
84 int ntrev; /* last rev scanned */
85 int ntlookups; /* # lookups */
85 int ntlookups; /* # lookups */
86 int ntmisses; /* # lookups that miss the cache */
86 int ntmisses; /* # lookups that miss the cache */
87 int inlined;
87 int inlined;
88 };
88 };
89
89
90 static Py_ssize_t index_length(const indexObject *self)
90 static Py_ssize_t index_length(const indexObject *self)
91 {
91 {
92 if (self->added == NULL)
92 if (self->added == NULL)
93 return self->length;
93 return self->length;
94 return self->length + PyList_GET_SIZE(self->added);
94 return self->length + PyList_GET_SIZE(self->added);
95 }
95 }
96
96
97 static PyObject *nullentry = NULL;
97 static PyObject *nullentry = NULL;
98 static const char nullid[20] = {0};
98 static const char nullid[20] = {0};
99
99
100 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
100 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
101
101
102 #if LONG_MAX == 0x7fffffffL
102 #if LONG_MAX == 0x7fffffffL
103 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
103 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
104 #else
104 #else
105 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
105 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
106 #endif
106 #endif
107
107
108 /* A RevlogNG v1 index entry is 64 bytes long. */
108 /* A RevlogNG v1 index entry is 64 bytes long. */
109 static const long v1_hdrsize = 64;
109 static const long v1_hdrsize = 64;
110
110
111 static void raise_revlog_error(void)
111 static void raise_revlog_error(void)
112 {
112 {
113 PyObject *mod = NULL, *dict = NULL, *errclass = NULL;
113 PyObject *mod = NULL, *dict = NULL, *errclass = NULL;
114
114
115 mod = PyImport_ImportModule("mercurial.error");
115 mod = PyImport_ImportModule("mercurial.error");
116 if (mod == NULL) {
116 if (mod == NULL) {
117 goto cleanup;
117 goto cleanup;
118 }
118 }
119
119
120 dict = PyModule_GetDict(mod);
120 dict = PyModule_GetDict(mod);
121 if (dict == NULL) {
121 if (dict == NULL) {
122 goto cleanup;
122 goto cleanup;
123 }
123 }
124 Py_INCREF(dict);
124 Py_INCREF(dict);
125
125
126 errclass = PyDict_GetItemString(dict, "RevlogError");
126 errclass = PyDict_GetItemString(dict, "RevlogError");
127 if (errclass == NULL) {
127 if (errclass == NULL) {
128 PyErr_SetString(PyExc_SystemError,
128 PyErr_SetString(PyExc_SystemError,
129 "could not find RevlogError");
129 "could not find RevlogError");
130 goto cleanup;
130 goto cleanup;
131 }
131 }
132
132
133 /* value of exception is ignored by callers */
133 /* value of exception is ignored by callers */
134 PyErr_SetString(errclass, "RevlogError");
134 PyErr_SetString(errclass, "RevlogError");
135
135
136 cleanup:
136 cleanup:
137 Py_XDECREF(dict);
137 Py_XDECREF(dict);
138 Py_XDECREF(mod);
138 Py_XDECREF(mod);
139 }
139 }
140
140
141 /*
141 /*
142 * Return a pointer to the beginning of a RevlogNG record.
142 * Return a pointer to the beginning of a RevlogNG record.
143 */
143 */
144 static const char *index_deref(indexObject *self, Py_ssize_t pos)
144 static const char *index_deref(indexObject *self, Py_ssize_t pos)
145 {
145 {
146 if (self->inlined && pos > 0) {
146 if (self->inlined && pos > 0) {
147 if (self->offsets == NULL) {
147 if (self->offsets == NULL) {
148 self->offsets = PyMem_Malloc(self->raw_length *
148 self->offsets = PyMem_Malloc(self->raw_length *
149 sizeof(*self->offsets));
149 sizeof(*self->offsets));
150 if (self->offsets == NULL)
150 if (self->offsets == NULL)
151 return (const char *)PyErr_NoMemory();
151 return (const char *)PyErr_NoMemory();
152 inline_scan(self, self->offsets);
152 inline_scan(self, self->offsets);
153 }
153 }
154 return self->offsets[pos];
154 return self->offsets[pos];
155 }
155 }
156
156
157 return (const char *)(self->buf.buf) + pos * v1_hdrsize;
157 return (const char *)(self->buf.buf) + pos * v1_hdrsize;
158 }
158 }
159
159
160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps,
160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps,
161 int maxrev)
161 int maxrev)
162 {
162 {
163 if (rev >= self->length) {
163 if (rev >= self->length) {
164 long tmp;
164 long tmp;
165 PyObject *tuple =
165 PyObject *tuple =
166 PyList_GET_ITEM(self->added, rev - self->length);
166 PyList_GET_ITEM(self->added, rev - self->length);
167 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 5), &tmp)) {
167 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 5), &tmp)) {
168 return -1;
168 return -1;
169 }
169 }
170 ps[0] = (int)tmp;
170 ps[0] = (int)tmp;
171 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 6), &tmp)) {
171 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 6), &tmp)) {
172 return -1;
172 return -1;
173 }
173 }
174 ps[1] = (int)tmp;
174 ps[1] = (int)tmp;
175 } else {
175 } else {
176 const char *data = index_deref(self, rev);
176 const char *data = index_deref(self, rev);
177 ps[0] = getbe32(data + 24);
177 ps[0] = getbe32(data + 24);
178 ps[1] = getbe32(data + 28);
178 ps[1] = getbe32(data + 28);
179 }
179 }
180 /* If index file is corrupted, ps[] may point to invalid revisions. So
180 /* If index file is corrupted, ps[] may point to invalid revisions. So
181 * there is a risk of buffer overflow to trust them unconditionally. */
181 * there is a risk of buffer overflow to trust them unconditionally. */
182 if (ps[0] > maxrev || ps[1] > maxrev) {
182 if (ps[0] > maxrev || ps[1] > maxrev) {
183 PyErr_SetString(PyExc_ValueError, "parent out of range");
183 PyErr_SetString(PyExc_ValueError, "parent out of range");
184 return -1;
184 return -1;
185 }
185 }
186 return 0;
186 return 0;
187 }
187 }
188
188
189 static inline int64_t index_get_start(indexObject *self, Py_ssize_t rev)
189 static inline int64_t index_get_start(indexObject *self, Py_ssize_t rev)
190 {
190 {
191 uint64_t offset;
191 uint64_t offset;
192 if (rev >= self->length) {
192 if (rev >= self->length) {
193 PyObject *tuple;
193 PyObject *tuple;
194 PyObject *pylong;
194 PyObject *pylong;
195 PY_LONG_LONG tmp;
195 PY_LONG_LONG tmp;
196 tuple = PyList_GET_ITEM(self->added, rev - self->length);
196 tuple = PyList_GET_ITEM(self->added, rev - self->length);
197 pylong = PyTuple_GET_ITEM(tuple, 0);
197 pylong = PyTuple_GET_ITEM(tuple, 0);
198 tmp = PyLong_AsLongLong(pylong);
198 tmp = PyLong_AsLongLong(pylong);
199 if (tmp == -1 && PyErr_Occurred()) {
199 if (tmp == -1 && PyErr_Occurred()) {
200 return -1;
200 return -1;
201 }
201 }
202 if (tmp < 0) {
202 if (tmp < 0) {
203 PyErr_Format(PyExc_OverflowError,
203 PyErr_Format(PyExc_OverflowError,
204 "revlog entry size out of bound (%lld)",
204 "revlog entry size out of bound (%lld)",
205 (long long)tmp);
205 (long long)tmp);
206 return -1;
206 return -1;
207 }
207 }
208 offset = (uint64_t)tmp;
208 offset = (uint64_t)tmp;
209 } else {
209 } else {
210 const char *data = index_deref(self, rev);
210 const char *data = index_deref(self, rev);
211 offset = getbe32(data + 4);
211 offset = getbe32(data + 4);
212 if (rev == 0) {
212 if (rev == 0) {
213 /* mask out version number for the first entry */
213 /* mask out version number for the first entry */
214 offset &= 0xFFFF;
214 offset &= 0xFFFF;
215 } else {
215 } else {
216 uint32_t offset_high = getbe32(data);
216 uint32_t offset_high = getbe32(data);
217 offset |= ((uint64_t)offset_high) << 32;
217 offset |= ((uint64_t)offset_high) << 32;
218 }
218 }
219 }
219 }
220 return (int64_t)(offset >> 16);
220 return (int64_t)(offset >> 16);
221 }
221 }
222
222
223 static inline int index_get_length(indexObject *self, Py_ssize_t rev)
223 static inline int index_get_length(indexObject *self, Py_ssize_t rev)
224 {
224 {
225 if (rev >= self->length) {
225 if (rev >= self->length) {
226 PyObject *tuple;
226 PyObject *tuple;
227 PyObject *pylong;
227 PyObject *pylong;
228 long ret;
228 long ret;
229 tuple = PyList_GET_ITEM(self->added, rev - self->length);
229 tuple = PyList_GET_ITEM(self->added, rev - self->length);
230 pylong = PyTuple_GET_ITEM(tuple, 1);
230 pylong = PyTuple_GET_ITEM(tuple, 1);
231 ret = PyInt_AsLong(pylong);
231 ret = PyInt_AsLong(pylong);
232 if (ret == -1 && PyErr_Occurred()) {
232 if (ret == -1 && PyErr_Occurred()) {
233 return -1;
233 return -1;
234 }
234 }
235 if (ret < 0 || ret > (long)INT_MAX) {
235 if (ret < 0 || ret > (long)INT_MAX) {
236 PyErr_Format(PyExc_OverflowError,
236 PyErr_Format(PyExc_OverflowError,
237 "revlog entry size out of bound (%ld)",
237 "revlog entry size out of bound (%ld)",
238 ret);
238 ret);
239 return -1;
239 return -1;
240 }
240 }
241 return (int)ret;
241 return (int)ret;
242 } else {
242 } else {
243 const char *data = index_deref(self, rev);
243 const char *data = index_deref(self, rev);
244 return (int)getbe32(data + 8);
244 return (int)getbe32(data + 8);
245 }
245 }
246 }
246 }
247
247
248 /*
248 /*
249 * RevlogNG format (all in big endian, data may be inlined):
249 * RevlogNG format (all in big endian, data may be inlined):
250 * 6 bytes: offset
250 * 6 bytes: offset
251 * 2 bytes: flags
251 * 2 bytes: flags
252 * 4 bytes: compressed length
252 * 4 bytes: compressed length
253 * 4 bytes: uncompressed length
253 * 4 bytes: uncompressed length
254 * 4 bytes: base revision
254 * 4 bytes: base revision
255 * 4 bytes: link revision
255 * 4 bytes: link revision
256 * 4 bytes: parent 1 revision
256 * 4 bytes: parent 1 revision
257 * 4 bytes: parent 2 revision
257 * 4 bytes: parent 2 revision
258 * 32 bytes: nodeid (only 20 bytes used)
258 * 32 bytes: nodeid (only 20 bytes used)
259 */
259 */
260 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
260 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
261 {
261 {
262 uint64_t offset_flags;
262 uint64_t offset_flags;
263 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
263 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
264 const char *c_node_id;
264 const char *c_node_id;
265 const char *data;
265 const char *data;
266 Py_ssize_t length = index_length(self);
266 Py_ssize_t length = index_length(self);
267 PyObject *entry;
267 PyObject *entry;
268
268
269 if (pos == -1) {
269 if (pos == -1) {
270 Py_INCREF(nullentry);
270 Py_INCREF(nullentry);
271 return nullentry;
271 return nullentry;
272 }
272 }
273
273
274 if (pos < 0 || pos >= length) {
274 if (pos < 0 || pos >= length) {
275 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
275 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
276 return NULL;
276 return NULL;
277 }
277 }
278
278
279 if (pos >= self->length) {
279 if (pos >= self->length) {
280 PyObject *obj;
280 PyObject *obj;
281 obj = PyList_GET_ITEM(self->added, pos - self->length);
281 obj = PyList_GET_ITEM(self->added, pos - self->length);
282 Py_INCREF(obj);
282 Py_INCREF(obj);
283 return obj;
283 return obj;
284 }
284 }
285
285
286 if (self->cache) {
286 if (self->cache) {
287 if (self->cache[pos]) {
287 if (self->cache[pos]) {
288 Py_INCREF(self->cache[pos]);
288 Py_INCREF(self->cache[pos]);
289 return self->cache[pos];
289 return self->cache[pos];
290 }
290 }
291 } else {
291 } else {
292 self->cache = calloc(self->raw_length, sizeof(PyObject *));
292 self->cache = calloc(self->raw_length, sizeof(PyObject *));
293 if (self->cache == NULL)
293 if (self->cache == NULL)
294 return PyErr_NoMemory();
294 return PyErr_NoMemory();
295 }
295 }
296
296
297 data = index_deref(self, pos);
297 data = index_deref(self, pos);
298 if (data == NULL)
298 if (data == NULL)
299 return NULL;
299 return NULL;
300
300
301 offset_flags = getbe32(data + 4);
301 offset_flags = getbe32(data + 4);
302 if (pos == 0) /* mask out version number for the first entry */
302 if (pos == 0) /* mask out version number for the first entry */
303 offset_flags &= 0xFFFF;
303 offset_flags &= 0xFFFF;
304 else {
304 else {
305 uint32_t offset_high = getbe32(data);
305 uint32_t offset_high = getbe32(data);
306 offset_flags |= ((uint64_t)offset_high) << 32;
306 offset_flags |= ((uint64_t)offset_high) << 32;
307 }
307 }
308
308
309 comp_len = getbe32(data + 8);
309 comp_len = getbe32(data + 8);
310 uncomp_len = getbe32(data + 12);
310 uncomp_len = getbe32(data + 12);
311 base_rev = getbe32(data + 16);
311 base_rev = getbe32(data + 16);
312 link_rev = getbe32(data + 20);
312 link_rev = getbe32(data + 20);
313 parent_1 = getbe32(data + 24);
313 parent_1 = getbe32(data + 24);
314 parent_2 = getbe32(data + 28);
314 parent_2 = getbe32(data + 28);
315 c_node_id = data + 32;
315 c_node_id = data + 32;
316
316
317 entry = Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
317 entry = Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
318 base_rev, link_rev, parent_1, parent_2, c_node_id,
318 base_rev, link_rev, parent_1, parent_2, c_node_id,
319 20);
319 20);
320
320
321 if (entry) {
321 if (entry) {
322 PyObject_GC_UnTrack(entry);
322 PyObject_GC_UnTrack(entry);
323 Py_INCREF(entry);
323 Py_INCREF(entry);
324 }
324 }
325
325
326 self->cache[pos] = entry;
326 self->cache[pos] = entry;
327
327
328 return entry;
328 return entry;
329 }
329 }
330
330
331 /*
331 /*
332 * Return the 20-byte SHA of the node corresponding to the given rev.
332 * Return the 20-byte SHA of the node corresponding to the given rev.
333 */
333 */
334 static const char *index_node(indexObject *self, Py_ssize_t pos)
334 static const char *index_node(indexObject *self, Py_ssize_t pos)
335 {
335 {
336 Py_ssize_t length = index_length(self);
336 Py_ssize_t length = index_length(self);
337 const char *data;
337 const char *data;
338
338
339 if (pos == -1)
339 if (pos == -1)
340 return nullid;
340 return nullid;
341
341
342 if (pos >= length)
342 if (pos >= length)
343 return NULL;
343 return NULL;
344
344
345 if (pos >= self->length) {
345 if (pos >= self->length) {
346 PyObject *tuple, *str;
346 PyObject *tuple, *str;
347 tuple = PyList_GET_ITEM(self->added, pos - self->length);
347 tuple = PyList_GET_ITEM(self->added, pos - self->length);
348 str = PyTuple_GetItem(tuple, 7);
348 str = PyTuple_GetItem(tuple, 7);
349 return str ? PyBytes_AS_STRING(str) : NULL;
349 return str ? PyBytes_AS_STRING(str) : NULL;
350 }
350 }
351
351
352 data = index_deref(self, pos);
352 data = index_deref(self, pos);
353 return data ? data + 32 : NULL;
353 return data ? data + 32 : NULL;
354 }
354 }
355
355
356 /*
356 /*
357 * Return the 20-byte SHA of the node corresponding to the given rev. The
357 * Return the 20-byte SHA of the node corresponding to the given rev. The
358 * rev is assumed to be existing. If not, an exception is set.
358 * rev is assumed to be existing. If not, an exception is set.
359 */
359 */
360 static const char *index_node_existing(indexObject *self, Py_ssize_t pos)
360 static const char *index_node_existing(indexObject *self, Py_ssize_t pos)
361 {
361 {
362 const char *node = index_node(self, pos);
362 const char *node = index_node(self, pos);
363 if (node == NULL) {
363 if (node == NULL) {
364 PyErr_Format(PyExc_IndexError, "could not access rev %d",
364 PyErr_Format(PyExc_IndexError, "could not access rev %d",
365 (int)pos);
365 (int)pos);
366 }
366 }
367 return node;
367 return node;
368 }
368 }
369
369
370 static int nt_insert(nodetree *self, const char *node, int rev);
370 static int nt_insert(nodetree *self, const char *node, int rev);
371
371
372 static int node_check(PyObject *obj, char **node)
372 static int node_check(PyObject *obj, char **node)
373 {
373 {
374 Py_ssize_t nodelen;
374 Py_ssize_t nodelen;
375 if (PyBytes_AsStringAndSize(obj, node, &nodelen) == -1)
375 if (PyBytes_AsStringAndSize(obj, node, &nodelen) == -1)
376 return -1;
376 return -1;
377 if (nodelen == 20)
377 if (nodelen == 20)
378 return 0;
378 return 0;
379 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
379 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
380 return -1;
380 return -1;
381 }
381 }
382
382
383 static PyObject *index_append(indexObject *self, PyObject *obj)
383 static PyObject *index_append(indexObject *self, PyObject *obj)
384 {
384 {
385 char *node;
385 char *node;
386 Py_ssize_t len;
386 Py_ssize_t len;
387
387
388 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
388 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
389 PyErr_SetString(PyExc_TypeError, "8-tuple required");
389 PyErr_SetString(PyExc_TypeError, "8-tuple required");
390 return NULL;
390 return NULL;
391 }
391 }
392
392
393 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
393 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
394 return NULL;
394 return NULL;
395
395
396 len = index_length(self);
396 len = index_length(self);
397
397
398 if (self->added == NULL) {
398 if (self->added == NULL) {
399 self->added = PyList_New(0);
399 self->added = PyList_New(0);
400 if (self->added == NULL)
400 if (self->added == NULL)
401 return NULL;
401 return NULL;
402 }
402 }
403
403
404 if (PyList_Append(self->added, obj) == -1)
404 if (PyList_Append(self->added, obj) == -1)
405 return NULL;
405 return NULL;
406
406
407 if (self->ntinitialized)
407 if (self->ntinitialized)
408 nt_insert(&self->nt, node, (int)len);
408 nt_insert(&self->nt, node, (int)len);
409
409
410 Py_CLEAR(self->headrevs);
410 Py_CLEAR(self->headrevs);
411 Py_RETURN_NONE;
411 Py_RETURN_NONE;
412 }
412 }
413
413
414 static PyObject *index_stats(indexObject *self)
414 static PyObject *index_stats(indexObject *self)
415 {
415 {
416 PyObject *obj = PyDict_New();
416 PyObject *obj = PyDict_New();
417 PyObject *s = NULL;
417 PyObject *s = NULL;
418 PyObject *t = NULL;
418 PyObject *t = NULL;
419
419
420 if (obj == NULL)
420 if (obj == NULL)
421 return NULL;
421 return NULL;
422
422
423 #define istat(__n, __d) \
423 #define istat(__n, __d) \
424 do { \
424 do { \
425 s = PyBytes_FromString(__d); \
425 s = PyBytes_FromString(__d); \
426 t = PyInt_FromSsize_t(self->__n); \
426 t = PyInt_FromSsize_t(self->__n); \
427 if (!s || !t) \
427 if (!s || !t) \
428 goto bail; \
428 goto bail; \
429 if (PyDict_SetItem(obj, s, t) == -1) \
429 if (PyDict_SetItem(obj, s, t) == -1) \
430 goto bail; \
430 goto bail; \
431 Py_CLEAR(s); \
431 Py_CLEAR(s); \
432 Py_CLEAR(t); \
432 Py_CLEAR(t); \
433 } while (0)
433 } while (0)
434
434
435 if (self->added) {
435 if (self->added) {
436 Py_ssize_t len = PyList_GET_SIZE(self->added);
436 Py_ssize_t len = PyList_GET_SIZE(self->added);
437 s = PyBytes_FromString("index entries added");
437 s = PyBytes_FromString("index entries added");
438 t = PyInt_FromSsize_t(len);
438 t = PyInt_FromSsize_t(len);
439 if (!s || !t)
439 if (!s || !t)
440 goto bail;
440 goto bail;
441 if (PyDict_SetItem(obj, s, t) == -1)
441 if (PyDict_SetItem(obj, s, t) == -1)
442 goto bail;
442 goto bail;
443 Py_CLEAR(s);
443 Py_CLEAR(s);
444 Py_CLEAR(t);
444 Py_CLEAR(t);
445 }
445 }
446
446
447 if (self->raw_length != self->length)
447 if (self->raw_length != self->length)
448 istat(raw_length, "revs on disk");
448 istat(raw_length, "revs on disk");
449 istat(length, "revs in memory");
449 istat(length, "revs in memory");
450 istat(ntlookups, "node trie lookups");
450 istat(ntlookups, "node trie lookups");
451 istat(ntmisses, "node trie misses");
451 istat(ntmisses, "node trie misses");
452 istat(ntrev, "node trie last rev scanned");
452 istat(ntrev, "node trie last rev scanned");
453 if (self->ntinitialized) {
453 if (self->ntinitialized) {
454 istat(nt.capacity, "node trie capacity");
454 istat(nt.capacity, "node trie capacity");
455 istat(nt.depth, "node trie depth");
455 istat(nt.depth, "node trie depth");
456 istat(nt.length, "node trie count");
456 istat(nt.length, "node trie count");
457 istat(nt.splits, "node trie splits");
457 istat(nt.splits, "node trie splits");
458 }
458 }
459
459
460 #undef istat
460 #undef istat
461
461
462 return obj;
462 return obj;
463
463
464 bail:
464 bail:
465 Py_XDECREF(obj);
465 Py_XDECREF(obj);
466 Py_XDECREF(s);
466 Py_XDECREF(s);
467 Py_XDECREF(t);
467 Py_XDECREF(t);
468 return NULL;
468 return NULL;
469 }
469 }
470
470
471 /*
471 /*
472 * When we cache a list, we want to be sure the caller can't mutate
472 * When we cache a list, we want to be sure the caller can't mutate
473 * the cached copy.
473 * the cached copy.
474 */
474 */
475 static PyObject *list_copy(PyObject *list)
475 static PyObject *list_copy(PyObject *list)
476 {
476 {
477 Py_ssize_t len = PyList_GET_SIZE(list);
477 Py_ssize_t len = PyList_GET_SIZE(list);
478 PyObject *newlist = PyList_New(len);
478 PyObject *newlist = PyList_New(len);
479 Py_ssize_t i;
479 Py_ssize_t i;
480
480
481 if (newlist == NULL)
481 if (newlist == NULL)
482 return NULL;
482 return NULL;
483
483
484 for (i = 0; i < len; i++) {
484 for (i = 0; i < len; i++) {
485 PyObject *obj = PyList_GET_ITEM(list, i);
485 PyObject *obj = PyList_GET_ITEM(list, i);
486 Py_INCREF(obj);
486 Py_INCREF(obj);
487 PyList_SET_ITEM(newlist, i, obj);
487 PyList_SET_ITEM(newlist, i, obj);
488 }
488 }
489
489
490 return newlist;
490 return newlist;
491 }
491 }
492
492
493 static int check_filter(PyObject *filter, Py_ssize_t arg)
493 static int check_filter(PyObject *filter, Py_ssize_t arg)
494 {
494 {
495 if (filter) {
495 if (filter) {
496 PyObject *arglist, *result;
496 PyObject *arglist, *result;
497 int isfiltered;
497 int isfiltered;
498
498
499 arglist = Py_BuildValue("(n)", arg);
499 arglist = Py_BuildValue("(n)", arg);
500 if (!arglist) {
500 if (!arglist) {
501 return -1;
501 return -1;
502 }
502 }
503
503
504 result = PyEval_CallObject(filter, arglist);
504 result = PyEval_CallObject(filter, arglist);
505 Py_DECREF(arglist);
505 Py_DECREF(arglist);
506 if (!result) {
506 if (!result) {
507 return -1;
507 return -1;
508 }
508 }
509
509
510 /* PyObject_IsTrue returns 1 if true, 0 if false, -1 if error,
510 /* PyObject_IsTrue returns 1 if true, 0 if false, -1 if error,
511 * same as this function, so we can just return it directly.*/
511 * same as this function, so we can just return it directly.*/
512 isfiltered = PyObject_IsTrue(result);
512 isfiltered = PyObject_IsTrue(result);
513 Py_DECREF(result);
513 Py_DECREF(result);
514 return isfiltered;
514 return isfiltered;
515 } else {
515 } else {
516 return 0;
516 return 0;
517 }
517 }
518 }
518 }
519
519
520 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
520 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
521 Py_ssize_t marker, char *phases)
521 Py_ssize_t marker, char *phases)
522 {
522 {
523 PyObject *iter = NULL;
523 PyObject *iter = NULL;
524 PyObject *iter_item = NULL;
524 PyObject *iter_item = NULL;
525 Py_ssize_t min_idx = index_length(self) + 2;
525 Py_ssize_t min_idx = index_length(self) + 2;
526 long iter_item_long;
526 long iter_item_long;
527
527
528 if (PyList_GET_SIZE(list) != 0) {
528 if (PyList_GET_SIZE(list) != 0) {
529 iter = PyObject_GetIter(list);
529 iter = PyObject_GetIter(list);
530 if (iter == NULL)
530 if (iter == NULL)
531 return -2;
531 return -2;
532 while ((iter_item = PyIter_Next(iter))) {
532 while ((iter_item = PyIter_Next(iter))) {
533 if (!pylong_to_long(iter_item, &iter_item_long)) {
533 if (!pylong_to_long(iter_item, &iter_item_long)) {
534 Py_DECREF(iter_item);
534 Py_DECREF(iter_item);
535 return -2;
535 return -2;
536 }
536 }
537 Py_DECREF(iter_item);
537 Py_DECREF(iter_item);
538 if (iter_item_long < min_idx)
538 if (iter_item_long < min_idx)
539 min_idx = iter_item_long;
539 min_idx = iter_item_long;
540 phases[iter_item_long] = (char)marker;
540 phases[iter_item_long] = (char)marker;
541 }
541 }
542 Py_DECREF(iter);
542 Py_DECREF(iter);
543 }
543 }
544
544
545 return min_idx;
545 return min_idx;
546 }
546 }
547
547
548 static inline void set_phase_from_parents(char *phases, int parent_1,
548 static inline void set_phase_from_parents(char *phases, int parent_1,
549 int parent_2, Py_ssize_t i)
549 int parent_2, Py_ssize_t i)
550 {
550 {
551 if (parent_1 >= 0 && phases[parent_1] > phases[i])
551 if (parent_1 >= 0 && phases[parent_1] > phases[i])
552 phases[i] = phases[parent_1];
552 phases[i] = phases[parent_1];
553 if (parent_2 >= 0 && phases[parent_2] > phases[i])
553 if (parent_2 >= 0 && phases[parent_2] > phases[i])
554 phases[i] = phases[parent_2];
554 phases[i] = phases[parent_2];
555 }
555 }
556
556
557 static PyObject *reachableroots2(indexObject *self, PyObject *args)
557 static PyObject *reachableroots2(indexObject *self, PyObject *args)
558 {
558 {
559
559
560 /* Input */
560 /* Input */
561 long minroot;
561 long minroot;
562 PyObject *includepatharg = NULL;
562 PyObject *includepatharg = NULL;
563 int includepath = 0;
563 int includepath = 0;
564 /* heads and roots are lists */
564 /* heads and roots are lists */
565 PyObject *heads = NULL;
565 PyObject *heads = NULL;
566 PyObject *roots = NULL;
566 PyObject *roots = NULL;
567 PyObject *reachable = NULL;
567 PyObject *reachable = NULL;
568
568
569 PyObject *val;
569 PyObject *val;
570 Py_ssize_t len = index_length(self);
570 Py_ssize_t len = index_length(self);
571 long revnum;
571 long revnum;
572 Py_ssize_t k;
572 Py_ssize_t k;
573 Py_ssize_t i;
573 Py_ssize_t i;
574 Py_ssize_t l;
574 Py_ssize_t l;
575 int r;
575 int r;
576 int parents[2];
576 int parents[2];
577
577
578 /* Internal data structure:
578 /* Internal data structure:
579 * tovisit: array of length len+1 (all revs + nullrev), filled upto
579 * tovisit: array of length len+1 (all revs + nullrev), filled upto
580 * lentovisit
580 * lentovisit
581 *
581 *
582 * revstates: array of length len+1 (all revs + nullrev) */
582 * revstates: array of length len+1 (all revs + nullrev) */
583 int *tovisit = NULL;
583 int *tovisit = NULL;
584 long lentovisit = 0;
584 long lentovisit = 0;
585 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
585 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
586 char *revstates = NULL;
586 char *revstates = NULL;
587
587
588 /* Get arguments */
588 /* Get arguments */
589 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
589 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
590 &PyList_Type, &roots, &PyBool_Type,
590 &PyList_Type, &roots, &PyBool_Type,
591 &includepatharg))
591 &includepatharg))
592 goto bail;
592 goto bail;
593
593
594 if (includepatharg == Py_True)
594 if (includepatharg == Py_True)
595 includepath = 1;
595 includepath = 1;
596
596
597 /* Initialize return set */
597 /* Initialize return set */
598 reachable = PyList_New(0);
598 reachable = PyList_New(0);
599 if (reachable == NULL)
599 if (reachable == NULL)
600 goto bail;
600 goto bail;
601
601
602 /* Initialize internal datastructures */
602 /* Initialize internal datastructures */
603 tovisit = (int *)malloc((len + 1) * sizeof(int));
603 tovisit = (int *)malloc((len + 1) * sizeof(int));
604 if (tovisit == NULL) {
604 if (tovisit == NULL) {
605 PyErr_NoMemory();
605 PyErr_NoMemory();
606 goto bail;
606 goto bail;
607 }
607 }
608
608
609 revstates = (char *)calloc(len + 1, 1);
609 revstates = (char *)calloc(len + 1, 1);
610 if (revstates == NULL) {
610 if (revstates == NULL) {
611 PyErr_NoMemory();
611 PyErr_NoMemory();
612 goto bail;
612 goto bail;
613 }
613 }
614
614
615 l = PyList_GET_SIZE(roots);
615 l = PyList_GET_SIZE(roots);
616 for (i = 0; i < l; i++) {
616 for (i = 0; i < l; i++) {
617 revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i));
617 revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i));
618 if (revnum == -1 && PyErr_Occurred())
618 if (revnum == -1 && PyErr_Occurred())
619 goto bail;
619 goto bail;
620 /* If root is out of range, e.g. wdir(), it must be unreachable
620 /* If root is out of range, e.g. wdir(), it must be unreachable
621 * from heads. So we can just ignore it. */
621 * from heads. So we can just ignore it. */
622 if (revnum + 1 < 0 || revnum + 1 >= len + 1)
622 if (revnum + 1 < 0 || revnum + 1 >= len + 1)
623 continue;
623 continue;
624 revstates[revnum + 1] |= RS_ROOT;
624 revstates[revnum + 1] |= RS_ROOT;
625 }
625 }
626
626
627 /* Populate tovisit with all the heads */
627 /* Populate tovisit with all the heads */
628 l = PyList_GET_SIZE(heads);
628 l = PyList_GET_SIZE(heads);
629 for (i = 0; i < l; i++) {
629 for (i = 0; i < l; i++) {
630 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i));
630 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i));
631 if (revnum == -1 && PyErr_Occurred())
631 if (revnum == -1 && PyErr_Occurred())
632 goto bail;
632 goto bail;
633 if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
633 if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
634 PyErr_SetString(PyExc_IndexError, "head out of range");
634 PyErr_SetString(PyExc_IndexError, "head out of range");
635 goto bail;
635 goto bail;
636 }
636 }
637 if (!(revstates[revnum + 1] & RS_SEEN)) {
637 if (!(revstates[revnum + 1] & RS_SEEN)) {
638 tovisit[lentovisit++] = (int)revnum;
638 tovisit[lentovisit++] = (int)revnum;
639 revstates[revnum + 1] |= RS_SEEN;
639 revstates[revnum + 1] |= RS_SEEN;
640 }
640 }
641 }
641 }
642
642
643 /* Visit the tovisit list and find the reachable roots */
643 /* Visit the tovisit list and find the reachable roots */
644 k = 0;
644 k = 0;
645 while (k < lentovisit) {
645 while (k < lentovisit) {
646 /* Add the node to reachable if it is a root*/
646 /* Add the node to reachable if it is a root*/
647 revnum = tovisit[k++];
647 revnum = tovisit[k++];
648 if (revstates[revnum + 1] & RS_ROOT) {
648 if (revstates[revnum + 1] & RS_ROOT) {
649 revstates[revnum + 1] |= RS_REACHABLE;
649 revstates[revnum + 1] |= RS_REACHABLE;
650 val = PyInt_FromLong(revnum);
650 val = PyInt_FromLong(revnum);
651 if (val == NULL)
651 if (val == NULL)
652 goto bail;
652 goto bail;
653 r = PyList_Append(reachable, val);
653 r = PyList_Append(reachable, val);
654 Py_DECREF(val);
654 Py_DECREF(val);
655 if (r < 0)
655 if (r < 0)
656 goto bail;
656 goto bail;
657 if (includepath == 0)
657 if (includepath == 0)
658 continue;
658 continue;
659 }
659 }
660
660
661 /* Add its parents to the list of nodes to visit */
661 /* Add its parents to the list of nodes to visit */
662 if (revnum == -1)
662 if (revnum == -1)
663 continue;
663 continue;
664 r = index_get_parents(self, revnum, parents, (int)len - 1);
664 r = index_get_parents(self, revnum, parents, (int)len - 1);
665 if (r < 0)
665 if (r < 0)
666 goto bail;
666 goto bail;
667 for (i = 0; i < 2; i++) {
667 for (i = 0; i < 2; i++) {
668 if (!(revstates[parents[i] + 1] & RS_SEEN) &&
668 if (!(revstates[parents[i] + 1] & RS_SEEN) &&
669 parents[i] >= minroot) {
669 parents[i] >= minroot) {
670 tovisit[lentovisit++] = parents[i];
670 tovisit[lentovisit++] = parents[i];
671 revstates[parents[i] + 1] |= RS_SEEN;
671 revstates[parents[i] + 1] |= RS_SEEN;
672 }
672 }
673 }
673 }
674 }
674 }
675
675
676 /* Find all the nodes in between the roots we found and the heads
676 /* Find all the nodes in between the roots we found and the heads
677 * and add them to the reachable set */
677 * and add them to the reachable set */
678 if (includepath == 1) {
678 if (includepath == 1) {
679 long minidx = minroot;
679 long minidx = minroot;
680 if (minidx < 0)
680 if (minidx < 0)
681 minidx = 0;
681 minidx = 0;
682 for (i = minidx; i < len; i++) {
682 for (i = minidx; i < len; i++) {
683 if (!(revstates[i + 1] & RS_SEEN))
683 if (!(revstates[i + 1] & RS_SEEN))
684 continue;
684 continue;
685 r = index_get_parents(self, i, parents, (int)len - 1);
685 r = index_get_parents(self, i, parents, (int)len - 1);
686 /* Corrupted index file, error is set from
686 /* Corrupted index file, error is set from
687 * index_get_parents */
687 * index_get_parents */
688 if (r < 0)
688 if (r < 0)
689 goto bail;
689 goto bail;
690 if (((revstates[parents[0] + 1] |
690 if (((revstates[parents[0] + 1] |
691 revstates[parents[1] + 1]) &
691 revstates[parents[1] + 1]) &
692 RS_REACHABLE) &&
692 RS_REACHABLE) &&
693 !(revstates[i + 1] & RS_REACHABLE)) {
693 !(revstates[i + 1] & RS_REACHABLE)) {
694 revstates[i + 1] |= RS_REACHABLE;
694 revstates[i + 1] |= RS_REACHABLE;
695 val = PyInt_FromSsize_t(i);
695 val = PyInt_FromSsize_t(i);
696 if (val == NULL)
696 if (val == NULL)
697 goto bail;
697 goto bail;
698 r = PyList_Append(reachable, val);
698 r = PyList_Append(reachable, val);
699 Py_DECREF(val);
699 Py_DECREF(val);
700 if (r < 0)
700 if (r < 0)
701 goto bail;
701 goto bail;
702 }
702 }
703 }
703 }
704 }
704 }
705
705
706 free(revstates);
706 free(revstates);
707 free(tovisit);
707 free(tovisit);
708 return reachable;
708 return reachable;
709 bail:
709 bail:
710 Py_XDECREF(reachable);
710 Py_XDECREF(reachable);
711 free(revstates);
711 free(revstates);
712 free(tovisit);
712 free(tovisit);
713 return NULL;
713 return NULL;
714 }
714 }
715
715
716 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
716 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
717 {
717 {
718 PyObject *roots = Py_None;
718 PyObject *roots = Py_None;
719 PyObject *ret = NULL;
719 PyObject *ret = NULL;
720 PyObject *phasessize = NULL;
720 PyObject *phasessize = NULL;
721 PyObject *phaseroots = NULL;
721 PyObject *phaseroots = NULL;
722 PyObject *phaseset = NULL;
722 PyObject *phaseset = NULL;
723 PyObject *phasessetlist = NULL;
723 PyObject *phasessetlist = NULL;
724 PyObject *rev = NULL;
724 PyObject *rev = NULL;
725 Py_ssize_t len = index_length(self);
725 Py_ssize_t len = index_length(self);
726 Py_ssize_t numphase = 0;
726 Py_ssize_t numphase = 0;
727 Py_ssize_t minrevallphases = 0;
727 Py_ssize_t minrevallphases = 0;
728 Py_ssize_t minrevphase = 0;
728 Py_ssize_t minrevphase = 0;
729 Py_ssize_t i = 0;
729 Py_ssize_t i = 0;
730 char *phases = NULL;
730 char *phases = NULL;
731 long phase;
731 long phase;
732
732
733 if (!PyArg_ParseTuple(args, "O", &roots))
733 if (!PyArg_ParseTuple(args, "O", &roots))
734 goto done;
734 goto done;
735 if (roots == NULL || !PyList_Check(roots)) {
735 if (roots == NULL || !PyList_Check(roots)) {
736 PyErr_SetString(PyExc_TypeError, "roots must be a list");
736 PyErr_SetString(PyExc_TypeError, "roots must be a list");
737 goto done;
737 goto done;
738 }
738 }
739
739
740 phases = calloc(
740 phases = calloc(
741 len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
741 len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
742 if (phases == NULL) {
742 if (phases == NULL) {
743 PyErr_NoMemory();
743 PyErr_NoMemory();
744 goto done;
744 goto done;
745 }
745 }
746 /* Put the phase information of all the roots in phases */
746 /* Put the phase information of all the roots in phases */
747 numphase = PyList_GET_SIZE(roots) + 1;
747 numphase = PyList_GET_SIZE(roots) + 1;
748 minrevallphases = len + 1;
748 minrevallphases = len + 1;
749 phasessetlist = PyList_New(numphase);
749 phasessetlist = PyList_New(numphase);
750 if (phasessetlist == NULL)
750 if (phasessetlist == NULL)
751 goto done;
751 goto done;
752
752
753 PyList_SET_ITEM(phasessetlist, 0, Py_None);
753 PyList_SET_ITEM(phasessetlist, 0, Py_None);
754 Py_INCREF(Py_None);
754 Py_INCREF(Py_None);
755
755
756 for (i = 0; i < numphase - 1; i++) {
756 for (i = 0; i < numphase - 1; i++) {
757 phaseroots = PyList_GET_ITEM(roots, i);
757 phaseroots = PyList_GET_ITEM(roots, i);
758 phaseset = PySet_New(NULL);
758 phaseset = PySet_New(NULL);
759 if (phaseset == NULL)
759 if (phaseset == NULL)
760 goto release;
760 goto release;
761 PyList_SET_ITEM(phasessetlist, i + 1, phaseset);
761 PyList_SET_ITEM(phasessetlist, i + 1, phaseset);
762 if (!PyList_Check(phaseroots)) {
762 if (!PyList_Check(phaseroots)) {
763 PyErr_SetString(PyExc_TypeError,
763 PyErr_SetString(PyExc_TypeError,
764 "roots item must be a list");
764 "roots item must be a list");
765 goto release;
765 goto release;
766 }
766 }
767 minrevphase =
767 minrevphase =
768 add_roots_get_min(self, phaseroots, i + 1, phases);
768 add_roots_get_min(self, phaseroots, i + 1, phases);
769 if (minrevphase == -2) /* Error from add_roots_get_min */
769 if (minrevphase == -2) /* Error from add_roots_get_min */
770 goto release;
770 goto release;
771 minrevallphases = MIN(minrevallphases, minrevphase);
771 minrevallphases = MIN(minrevallphases, minrevphase);
772 }
772 }
773 /* Propagate the phase information from the roots to the revs */
773 /* Propagate the phase information from the roots to the revs */
774 if (minrevallphases != -1) {
774 if (minrevallphases != -1) {
775 int parents[2];
775 int parents[2];
776 for (i = minrevallphases; i < len; i++) {
776 for (i = minrevallphases; i < len; i++) {
777 if (index_get_parents(self, i, parents, (int)len - 1) <
777 if (index_get_parents(self, i, parents, (int)len - 1) <
778 0)
778 0)
779 goto release;
779 goto release;
780 set_phase_from_parents(phases, parents[0], parents[1],
780 set_phase_from_parents(phases, parents[0], parents[1],
781 i);
781 i);
782 }
782 }
783 }
783 }
784 /* Transform phase list to a python list */
784 /* Transform phase list to a python list */
785 phasessize = PyInt_FromSsize_t(len);
785 phasessize = PyInt_FromSsize_t(len);
786 if (phasessize == NULL)
786 if (phasessize == NULL)
787 goto release;
787 goto release;
788 for (i = 0; i < len; i++) {
788 for (i = 0; i < len; i++) {
789 phase = phases[i];
789 phase = phases[i];
790 /* We only store the sets of phase for non public phase, the
790 /* We only store the sets of phase for non public phase, the
791 * public phase is computed as a difference */
791 * public phase is computed as a difference */
792 if (phase != 0) {
792 if (phase != 0) {
793 phaseset = PyList_GET_ITEM(phasessetlist, phase);
793 phaseset = PyList_GET_ITEM(phasessetlist, phase);
794 rev = PyInt_FromSsize_t(i);
794 rev = PyInt_FromSsize_t(i);
795 if (rev == NULL)
795 if (rev == NULL)
796 goto release;
796 goto release;
797 PySet_Add(phaseset, rev);
797 PySet_Add(phaseset, rev);
798 Py_XDECREF(rev);
798 Py_XDECREF(rev);
799 }
799 }
800 }
800 }
801 ret = PyTuple_Pack(2, phasessize, phasessetlist);
801 ret = PyTuple_Pack(2, phasessize, phasessetlist);
802
802
803 release:
803 release:
804 Py_XDECREF(phasessize);
804 Py_XDECREF(phasessize);
805 Py_XDECREF(phasessetlist);
805 Py_XDECREF(phasessetlist);
806 done:
806 done:
807 free(phases);
807 free(phases);
808 return ret;
808 return ret;
809 }
809 }
810
810
811 static PyObject *index_headrevs(indexObject *self, PyObject *args)
811 static PyObject *index_headrevs(indexObject *self, PyObject *args)
812 {
812 {
813 Py_ssize_t i, j, len;
813 Py_ssize_t i, j, len;
814 char *nothead = NULL;
814 char *nothead = NULL;
815 PyObject *heads = NULL;
815 PyObject *heads = NULL;
816 PyObject *filter = NULL;
816 PyObject *filter = NULL;
817 PyObject *filteredrevs = Py_None;
817 PyObject *filteredrevs = Py_None;
818
818
819 if (!PyArg_ParseTuple(args, "|O", &filteredrevs)) {
819 if (!PyArg_ParseTuple(args, "|O", &filteredrevs)) {
820 return NULL;
820 return NULL;
821 }
821 }
822
822
823 if (self->headrevs && filteredrevs == self->filteredrevs)
823 if (self->headrevs && filteredrevs == self->filteredrevs)
824 return list_copy(self->headrevs);
824 return list_copy(self->headrevs);
825
825
826 Py_DECREF(self->filteredrevs);
826 Py_DECREF(self->filteredrevs);
827 self->filteredrevs = filteredrevs;
827 self->filteredrevs = filteredrevs;
828 Py_INCREF(filteredrevs);
828 Py_INCREF(filteredrevs);
829
829
830 if (filteredrevs != Py_None) {
830 if (filteredrevs != Py_None) {
831 filter = PyObject_GetAttrString(filteredrevs, "__contains__");
831 filter = PyObject_GetAttrString(filteredrevs, "__contains__");
832 if (!filter) {
832 if (!filter) {
833 PyErr_SetString(
833 PyErr_SetString(
834 PyExc_TypeError,
834 PyExc_TypeError,
835 "filteredrevs has no attribute __contains__");
835 "filteredrevs has no attribute __contains__");
836 goto bail;
836 goto bail;
837 }
837 }
838 }
838 }
839
839
840 len = index_length(self);
840 len = index_length(self);
841 heads = PyList_New(0);
841 heads = PyList_New(0);
842 if (heads == NULL)
842 if (heads == NULL)
843 goto bail;
843 goto bail;
844 if (len == 0) {
844 if (len == 0) {
845 PyObject *nullid = PyInt_FromLong(-1);
845 PyObject *nullid = PyInt_FromLong(-1);
846 if (nullid == NULL || PyList_Append(heads, nullid) == -1) {
846 if (nullid == NULL || PyList_Append(heads, nullid) == -1) {
847 Py_XDECREF(nullid);
847 Py_XDECREF(nullid);
848 goto bail;
848 goto bail;
849 }
849 }
850 goto done;
850 goto done;
851 }
851 }
852
852
853 nothead = calloc(len, 1);
853 nothead = calloc(len, 1);
854 if (nothead == NULL) {
854 if (nothead == NULL) {
855 PyErr_NoMemory();
855 PyErr_NoMemory();
856 goto bail;
856 goto bail;
857 }
857 }
858
858
859 for (i = len - 1; i >= 0; i--) {
859 for (i = len - 1; i >= 0; i--) {
860 int isfiltered;
860 int isfiltered;
861 int parents[2];
861 int parents[2];
862
862
863 /* If nothead[i] == 1, it means we've seen an unfiltered child
863 /* If nothead[i] == 1, it means we've seen an unfiltered child
864 * of this node already, and therefore this node is not
864 * of this node already, and therefore this node is not
865 * filtered. So we can skip the expensive check_filter step.
865 * filtered. So we can skip the expensive check_filter step.
866 */
866 */
867 if (nothead[i] != 1) {
867 if (nothead[i] != 1) {
868 isfiltered = check_filter(filter, i);
868 isfiltered = check_filter(filter, i);
869 if (isfiltered == -1) {
869 if (isfiltered == -1) {
870 PyErr_SetString(PyExc_TypeError,
870 PyErr_SetString(PyExc_TypeError,
871 "unable to check filter");
871 "unable to check filter");
872 goto bail;
872 goto bail;
873 }
873 }
874
874
875 if (isfiltered) {
875 if (isfiltered) {
876 nothead[i] = 1;
876 nothead[i] = 1;
877 continue;
877 continue;
878 }
878 }
879 }
879 }
880
880
881 if (index_get_parents(self, i, parents, (int)len - 1) < 0)
881 if (index_get_parents(self, i, parents, (int)len - 1) < 0)
882 goto bail;
882 goto bail;
883 for (j = 0; j < 2; j++) {
883 for (j = 0; j < 2; j++) {
884 if (parents[j] >= 0)
884 if (parents[j] >= 0)
885 nothead[parents[j]] = 1;
885 nothead[parents[j]] = 1;
886 }
886 }
887 }
887 }
888
888
889 for (i = 0; i < len; i++) {
889 for (i = 0; i < len; i++) {
890 PyObject *head;
890 PyObject *head;
891
891
892 if (nothead[i])
892 if (nothead[i])
893 continue;
893 continue;
894 head = PyInt_FromSsize_t(i);
894 head = PyInt_FromSsize_t(i);
895 if (head == NULL || PyList_Append(heads, head) == -1) {
895 if (head == NULL || PyList_Append(heads, head) == -1) {
896 Py_XDECREF(head);
896 Py_XDECREF(head);
897 goto bail;
897 goto bail;
898 }
898 }
899 }
899 }
900
900
901 done:
901 done:
902 self->headrevs = heads;
902 self->headrevs = heads;
903 Py_XDECREF(filter);
903 Py_XDECREF(filter);
904 free(nothead);
904 free(nothead);
905 return list_copy(self->headrevs);
905 return list_copy(self->headrevs);
906 bail:
906 bail:
907 Py_XDECREF(filter);
907 Py_XDECREF(filter);
908 Py_XDECREF(heads);
908 Py_XDECREF(heads);
909 free(nothead);
909 free(nothead);
910 return NULL;
910 return NULL;
911 }
911 }
912
912
913 /**
913 /**
914 * Obtain the base revision index entry.
914 * Obtain the base revision index entry.
915 *
915 *
916 * Callers must ensure that rev >= 0 or illegal memory access may occur.
916 * Callers must ensure that rev >= 0 or illegal memory access may occur.
917 */
917 */
918 static inline int index_baserev(indexObject *self, int rev)
918 static inline int index_baserev(indexObject *self, int rev)
919 {
919 {
920 const char *data;
920 const char *data;
921
921
922 if (rev >= self->length) {
922 if (rev >= self->length) {
923 PyObject *tuple =
923 PyObject *tuple =
924 PyList_GET_ITEM(self->added, rev - self->length);
924 PyList_GET_ITEM(self->added, rev - self->length);
925 long ret;
925 long ret;
926 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), &ret)) {
926 if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), &ret)) {
927 return -2;
927 return -2;
928 }
928 }
929 return (int)ret;
929 return (int)ret;
930 } else {
930 } else {
931 data = index_deref(self, rev);
931 data = index_deref(self, rev);
932 if (data == NULL) {
932 if (data == NULL) {
933 return -2;
933 return -2;
934 }
934 }
935
935
936 return getbe32(data + 16);
936 return getbe32(data + 16);
937 }
937 }
938 }
938 }
939
939
940 static PyObject *index_deltachain(indexObject *self, PyObject *args)
940 static PyObject *index_deltachain(indexObject *self, PyObject *args)
941 {
941 {
942 int rev, generaldelta;
942 int rev, generaldelta;
943 PyObject *stoparg;
943 PyObject *stoparg;
944 int stoprev, iterrev, baserev = -1;
944 int stoprev, iterrev, baserev = -1;
945 int stopped;
945 int stopped;
946 PyObject *chain = NULL, *result = NULL;
946 PyObject *chain = NULL, *result = NULL;
947 const Py_ssize_t length = index_length(self);
947 const Py_ssize_t length = index_length(self);
948
948
949 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
949 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
950 return NULL;
950 return NULL;
951 }
951 }
952
952
953 if (PyInt_Check(stoparg)) {
953 if (PyInt_Check(stoparg)) {
954 stoprev = (int)PyInt_AsLong(stoparg);
954 stoprev = (int)PyInt_AsLong(stoparg);
955 if (stoprev == -1 && PyErr_Occurred()) {
955 if (stoprev == -1 && PyErr_Occurred()) {
956 return NULL;
956 return NULL;
957 }
957 }
958 } else if (stoparg == Py_None) {
958 } else if (stoparg == Py_None) {
959 stoprev = -2;
959 stoprev = -2;
960 } else {
960 } else {
961 PyErr_SetString(PyExc_ValueError,
961 PyErr_SetString(PyExc_ValueError,
962 "stoprev must be integer or None");
962 "stoprev must be integer or None");
963 return NULL;
963 return NULL;
964 }
964 }
965
965
966 if (rev < 0 || rev >= length) {
966 if (rev < 0 || rev >= length) {
967 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
967 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
968 return NULL;
968 return NULL;
969 }
969 }
970
970
971 chain = PyList_New(0);
971 chain = PyList_New(0);
972 if (chain == NULL) {
972 if (chain == NULL) {
973 return NULL;
973 return NULL;
974 }
974 }
975
975
976 baserev = index_baserev(self, rev);
976 baserev = index_baserev(self, rev);
977
977
978 /* This should never happen. */
978 /* This should never happen. */
979 if (baserev <= -2) {
979 if (baserev <= -2) {
980 /* Error should be set by index_deref() */
980 /* Error should be set by index_deref() */
981 assert(PyErr_Occurred());
981 assert(PyErr_Occurred());
982 goto bail;
982 goto bail;
983 }
983 }
984
984
985 iterrev = rev;
985 iterrev = rev;
986
986
987 while (iterrev != baserev && iterrev != stoprev) {
987 while (iterrev != baserev && iterrev != stoprev) {
988 PyObject *value = PyInt_FromLong(iterrev);
988 PyObject *value = PyInt_FromLong(iterrev);
989 if (value == NULL) {
989 if (value == NULL) {
990 goto bail;
990 goto bail;
991 }
991 }
992 if (PyList_Append(chain, value)) {
992 if (PyList_Append(chain, value)) {
993 Py_DECREF(value);
993 Py_DECREF(value);
994 goto bail;
994 goto bail;
995 }
995 }
996 Py_DECREF(value);
996 Py_DECREF(value);
997
997
998 if (generaldelta) {
998 if (generaldelta) {
999 iterrev = baserev;
999 iterrev = baserev;
1000 } else {
1000 } else {
1001 iterrev--;
1001 iterrev--;
1002 }
1002 }
1003
1003
1004 if (iterrev < 0) {
1004 if (iterrev < 0) {
1005 break;
1005 break;
1006 }
1006 }
1007
1007
1008 if (iterrev >= length) {
1008 if (iterrev >= length) {
1009 PyErr_SetString(PyExc_IndexError,
1009 PyErr_SetString(PyExc_IndexError,
1010 "revision outside index");
1010 "revision outside index");
1011 return NULL;
1011 return NULL;
1012 }
1012 }
1013
1013
1014 baserev = index_baserev(self, iterrev);
1014 baserev = index_baserev(self, iterrev);
1015
1015
1016 /* This should never happen. */
1016 /* This should never happen. */
1017 if (baserev <= -2) {
1017 if (baserev <= -2) {
1018 /* Error should be set by index_deref() */
1018 /* Error should be set by index_deref() */
1019 assert(PyErr_Occurred());
1019 assert(PyErr_Occurred());
1020 goto bail;
1020 goto bail;
1021 }
1021 }
1022 }
1022 }
1023
1023
1024 if (iterrev == stoprev) {
1024 if (iterrev == stoprev) {
1025 stopped = 1;
1025 stopped = 1;
1026 } else {
1026 } else {
1027 PyObject *value = PyInt_FromLong(iterrev);
1027 PyObject *value = PyInt_FromLong(iterrev);
1028 if (value == NULL) {
1028 if (value == NULL) {
1029 goto bail;
1029 goto bail;
1030 }
1030 }
1031 if (PyList_Append(chain, value)) {
1031 if (PyList_Append(chain, value)) {
1032 Py_DECREF(value);
1032 Py_DECREF(value);
1033 goto bail;
1033 goto bail;
1034 }
1034 }
1035 Py_DECREF(value);
1035 Py_DECREF(value);
1036
1036
1037 stopped = 0;
1037 stopped = 0;
1038 }
1038 }
1039
1039
1040 if (PyList_Reverse(chain)) {
1040 if (PyList_Reverse(chain)) {
1041 goto bail;
1041 goto bail;
1042 }
1042 }
1043
1043
1044 result = Py_BuildValue("OO", chain, stopped ? Py_True : Py_False);
1044 result = Py_BuildValue("OO", chain, stopped ? Py_True : Py_False);
1045 Py_DECREF(chain);
1045 Py_DECREF(chain);
1046 return result;
1046 return result;
1047
1047
1048 bail:
1048 bail:
1049 Py_DECREF(chain);
1049 Py_DECREF(chain);
1050 return NULL;
1050 return NULL;
1051 }
1051 }
1052
1052
1053 static inline int64_t
1054 index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t end_rev)
1055 {
1056 int64_t start_offset;
1057 int64_t end_offset;
1058 int end_size;
1059 start_offset = index_get_start(self, start_rev);
1060 if (start_offset < 0) {
1061 return -1;
1062 }
1063 end_offset = index_get_start(self, end_rev);
1064 if (end_offset < 0) {
1065 return -1;
1066 }
1067 end_size = index_get_length(self, end_rev);
1068 if (end_size < 0) {
1069 return -1;
1070 }
1071 if (end_offset < start_offset) {
1072 PyErr_Format(PyExc_ValueError,
1073 "corrupted revlog index: inconsistent offset "
1074 "between revisions (%zd) and (%zd)",
1075 start_rev, end_rev);
1076 return -1;
1077 }
1078 return (end_offset - start_offset) + (int64_t)end_size;
1079 }
1080
1053 static inline int nt_level(const char *node, Py_ssize_t level)
1081 static inline int nt_level(const char *node, Py_ssize_t level)
1054 {
1082 {
1055 int v = node[level >> 1];
1083 int v = node[level >> 1];
1056 if (!(level & 1))
1084 if (!(level & 1))
1057 v >>= 4;
1085 v >>= 4;
1058 return v & 0xf;
1086 return v & 0xf;
1059 }
1087 }
1060
1088
1061 /*
1089 /*
1062 * Return values:
1090 * Return values:
1063 *
1091 *
1064 * -4: match is ambiguous (multiple candidates)
1092 * -4: match is ambiguous (multiple candidates)
1065 * -2: not found
1093 * -2: not found
1066 * rest: valid rev
1094 * rest: valid rev
1067 */
1095 */
1068 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
1096 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
1069 int hex)
1097 int hex)
1070 {
1098 {
1071 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
1099 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
1072 int level, maxlevel, off;
1100 int level, maxlevel, off;
1073
1101
1074 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
1102 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
1075 return -1;
1103 return -1;
1076
1104
1077 if (hex)
1105 if (hex)
1078 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
1106 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
1079 else
1107 else
1080 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
1108 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
1081
1109
1082 for (level = off = 0; level < maxlevel; level++) {
1110 for (level = off = 0; level < maxlevel; level++) {
1083 int k = getnybble(node, level);
1111 int k = getnybble(node, level);
1084 nodetreenode *n = &self->nodes[off];
1112 nodetreenode *n = &self->nodes[off];
1085 int v = n->children[k];
1113 int v = n->children[k];
1086
1114
1087 if (v < 0) {
1115 if (v < 0) {
1088 const char *n;
1116 const char *n;
1089 Py_ssize_t i;
1117 Py_ssize_t i;
1090
1118
1091 v = -(v + 2);
1119 v = -(v + 2);
1092 n = index_node(self->index, v);
1120 n = index_node(self->index, v);
1093 if (n == NULL)
1121 if (n == NULL)
1094 return -2;
1122 return -2;
1095 for (i = level; i < maxlevel; i++)
1123 for (i = level; i < maxlevel; i++)
1096 if (getnybble(node, i) != nt_level(n, i))
1124 if (getnybble(node, i) != nt_level(n, i))
1097 return -2;
1125 return -2;
1098 return v;
1126 return v;
1099 }
1127 }
1100 if (v == 0)
1128 if (v == 0)
1101 return -2;
1129 return -2;
1102 off = v;
1130 off = v;
1103 }
1131 }
1104 /* multiple matches against an ambiguous prefix */
1132 /* multiple matches against an ambiguous prefix */
1105 return -4;
1133 return -4;
1106 }
1134 }
1107
1135
1108 static int nt_new(nodetree *self)
1136 static int nt_new(nodetree *self)
1109 {
1137 {
1110 if (self->length == self->capacity) {
1138 if (self->length == self->capacity) {
1111 unsigned newcapacity;
1139 unsigned newcapacity;
1112 nodetreenode *newnodes;
1140 nodetreenode *newnodes;
1113 newcapacity = self->capacity * 2;
1141 newcapacity = self->capacity * 2;
1114 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
1142 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
1115 PyErr_SetString(PyExc_MemoryError,
1143 PyErr_SetString(PyExc_MemoryError,
1116 "overflow in nt_new");
1144 "overflow in nt_new");
1117 return -1;
1145 return -1;
1118 }
1146 }
1119 newnodes =
1147 newnodes =
1120 realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1148 realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1121 if (newnodes == NULL) {
1149 if (newnodes == NULL) {
1122 PyErr_SetString(PyExc_MemoryError, "out of memory");
1150 PyErr_SetString(PyExc_MemoryError, "out of memory");
1123 return -1;
1151 return -1;
1124 }
1152 }
1125 self->capacity = newcapacity;
1153 self->capacity = newcapacity;
1126 self->nodes = newnodes;
1154 self->nodes = newnodes;
1127 memset(&self->nodes[self->length], 0,
1155 memset(&self->nodes[self->length], 0,
1128 sizeof(nodetreenode) * (self->capacity - self->length));
1156 sizeof(nodetreenode) * (self->capacity - self->length));
1129 }
1157 }
1130 return self->length++;
1158 return self->length++;
1131 }
1159 }
1132
1160
1133 static int nt_insert(nodetree *self, const char *node, int rev)
1161 static int nt_insert(nodetree *self, const char *node, int rev)
1134 {
1162 {
1135 int level = 0;
1163 int level = 0;
1136 int off = 0;
1164 int off = 0;
1137
1165
1138 while (level < 40) {
1166 while (level < 40) {
1139 int k = nt_level(node, level);
1167 int k = nt_level(node, level);
1140 nodetreenode *n;
1168 nodetreenode *n;
1141 int v;
1169 int v;
1142
1170
1143 n = &self->nodes[off];
1171 n = &self->nodes[off];
1144 v = n->children[k];
1172 v = n->children[k];
1145
1173
1146 if (v == 0) {
1174 if (v == 0) {
1147 n->children[k] = -rev - 2;
1175 n->children[k] = -rev - 2;
1148 return 0;
1176 return 0;
1149 }
1177 }
1150 if (v < 0) {
1178 if (v < 0) {
1151 const char *oldnode =
1179 const char *oldnode =
1152 index_node_existing(self->index, -(v + 2));
1180 index_node_existing(self->index, -(v + 2));
1153 int noff;
1181 int noff;
1154
1182
1155 if (oldnode == NULL)
1183 if (oldnode == NULL)
1156 return -1;
1184 return -1;
1157 if (!memcmp(oldnode, node, 20)) {
1185 if (!memcmp(oldnode, node, 20)) {
1158 n->children[k] = -rev - 2;
1186 n->children[k] = -rev - 2;
1159 return 0;
1187 return 0;
1160 }
1188 }
1161 noff = nt_new(self);
1189 noff = nt_new(self);
1162 if (noff == -1)
1190 if (noff == -1)
1163 return -1;
1191 return -1;
1164 /* self->nodes may have been changed by realloc */
1192 /* self->nodes may have been changed by realloc */
1165 self->nodes[off].children[k] = noff;
1193 self->nodes[off].children[k] = noff;
1166 off = noff;
1194 off = noff;
1167 n = &self->nodes[off];
1195 n = &self->nodes[off];
1168 n->children[nt_level(oldnode, ++level)] = v;
1196 n->children[nt_level(oldnode, ++level)] = v;
1169 if (level > self->depth)
1197 if (level > self->depth)
1170 self->depth = level;
1198 self->depth = level;
1171 self->splits += 1;
1199 self->splits += 1;
1172 } else {
1200 } else {
1173 level += 1;
1201 level += 1;
1174 off = v;
1202 off = v;
1175 }
1203 }
1176 }
1204 }
1177
1205
1178 return -1;
1206 return -1;
1179 }
1207 }
1180
1208
1181 static PyObject *ntobj_insert(nodetreeObject *self, PyObject *args)
1209 static PyObject *ntobj_insert(nodetreeObject *self, PyObject *args)
1182 {
1210 {
1183 Py_ssize_t rev;
1211 Py_ssize_t rev;
1184 const char *node;
1212 const char *node;
1185 Py_ssize_t length;
1213 Py_ssize_t length;
1186 if (!PyArg_ParseTuple(args, "n", &rev))
1214 if (!PyArg_ParseTuple(args, "n", &rev))
1187 return NULL;
1215 return NULL;
1188 length = index_length(self->nt.index);
1216 length = index_length(self->nt.index);
1189 if (rev < 0 || rev >= length) {
1217 if (rev < 0 || rev >= length) {
1190 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1218 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1191 return NULL;
1219 return NULL;
1192 }
1220 }
1193 node = index_node_existing(self->nt.index, rev);
1221 node = index_node_existing(self->nt.index, rev);
1194 if (nt_insert(&self->nt, node, (int)rev) == -1)
1222 if (nt_insert(&self->nt, node, (int)rev) == -1)
1195 return NULL;
1223 return NULL;
1196 Py_RETURN_NONE;
1224 Py_RETURN_NONE;
1197 }
1225 }
1198
1226
1199 static int nt_delete_node(nodetree *self, const char *node)
1227 static int nt_delete_node(nodetree *self, const char *node)
1200 {
1228 {
1201 /* rev==-2 happens to get encoded as 0, which is interpreted as not set
1229 /* rev==-2 happens to get encoded as 0, which is interpreted as not set
1202 */
1230 */
1203 return nt_insert(self, node, -2);
1231 return nt_insert(self, node, -2);
1204 }
1232 }
1205
1233
1206 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1234 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1207 {
1235 {
1208 /* Initialize before overflow-checking to avoid nt_dealloc() crash. */
1236 /* Initialize before overflow-checking to avoid nt_dealloc() crash. */
1209 self->nodes = NULL;
1237 self->nodes = NULL;
1210
1238
1211 self->index = index;
1239 self->index = index;
1212 /* The input capacity is in terms of revisions, while the field is in
1240 /* The input capacity is in terms of revisions, while the field is in
1213 * terms of nodetree nodes. */
1241 * terms of nodetree nodes. */
1214 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1242 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1215 self->depth = 0;
1243 self->depth = 0;
1216 self->splits = 0;
1244 self->splits = 0;
1217 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1245 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1218 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1246 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1219 return -1;
1247 return -1;
1220 }
1248 }
1221 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1249 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1222 if (self->nodes == NULL) {
1250 if (self->nodes == NULL) {
1223 PyErr_NoMemory();
1251 PyErr_NoMemory();
1224 return -1;
1252 return -1;
1225 }
1253 }
1226 self->length = 1;
1254 self->length = 1;
1227 return 0;
1255 return 0;
1228 }
1256 }
1229
1257
1230 static PyTypeObject indexType;
1258 static PyTypeObject indexType;
1231
1259
1232 static int ntobj_init(nodetreeObject *self, PyObject *args)
1260 static int ntobj_init(nodetreeObject *self, PyObject *args)
1233 {
1261 {
1234 PyObject *index;
1262 PyObject *index;
1235 unsigned capacity;
1263 unsigned capacity;
1236 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1264 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1237 return -1;
1265 return -1;
1238 Py_INCREF(index);
1266 Py_INCREF(index);
1239 return nt_init(&self->nt, (indexObject *)index, capacity);
1267 return nt_init(&self->nt, (indexObject *)index, capacity);
1240 }
1268 }
1241
1269
1242 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen)
1270 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen)
1243 {
1271 {
1244 return nt_find(self, node, nodelen, 1);
1272 return nt_find(self, node, nodelen, 1);
1245 }
1273 }
1246
1274
1247 /*
1275 /*
1248 * Find the length of the shortest unique prefix of node.
1276 * Find the length of the shortest unique prefix of node.
1249 *
1277 *
1250 * Return values:
1278 * Return values:
1251 *
1279 *
1252 * -3: error (exception set)
1280 * -3: error (exception set)
1253 * -2: not found (no exception set)
1281 * -2: not found (no exception set)
1254 * rest: length of shortest prefix
1282 * rest: length of shortest prefix
1255 */
1283 */
1256 static int nt_shortest(nodetree *self, const char *node)
1284 static int nt_shortest(nodetree *self, const char *node)
1257 {
1285 {
1258 int level, off;
1286 int level, off;
1259
1287
1260 for (level = off = 0; level < 40; level++) {
1288 for (level = off = 0; level < 40; level++) {
1261 int k, v;
1289 int k, v;
1262 nodetreenode *n = &self->nodes[off];
1290 nodetreenode *n = &self->nodes[off];
1263 k = nt_level(node, level);
1291 k = nt_level(node, level);
1264 v = n->children[k];
1292 v = n->children[k];
1265 if (v < 0) {
1293 if (v < 0) {
1266 const char *n;
1294 const char *n;
1267 v = -(v + 2);
1295 v = -(v + 2);
1268 n = index_node_existing(self->index, v);
1296 n = index_node_existing(self->index, v);
1269 if (n == NULL)
1297 if (n == NULL)
1270 return -3;
1298 return -3;
1271 if (memcmp(node, n, 20) != 0)
1299 if (memcmp(node, n, 20) != 0)
1272 /*
1300 /*
1273 * Found a unique prefix, but it wasn't for the
1301 * Found a unique prefix, but it wasn't for the
1274 * requested node (i.e the requested node does
1302 * requested node (i.e the requested node does
1275 * not exist).
1303 * not exist).
1276 */
1304 */
1277 return -2;
1305 return -2;
1278 return level + 1;
1306 return level + 1;
1279 }
1307 }
1280 if (v == 0)
1308 if (v == 0)
1281 return -2;
1309 return -2;
1282 off = v;
1310 off = v;
1283 }
1311 }
1284 /*
1312 /*
1285 * The node was still not unique after 40 hex digits, so this won't
1313 * The node was still not unique after 40 hex digits, so this won't
1286 * happen. Also, if we get here, then there's a programming error in
1314 * happen. Also, if we get here, then there's a programming error in
1287 * this file that made us insert a node longer than 40 hex digits.
1315 * this file that made us insert a node longer than 40 hex digits.
1288 */
1316 */
1289 PyErr_SetString(PyExc_Exception, "broken node tree");
1317 PyErr_SetString(PyExc_Exception, "broken node tree");
1290 return -3;
1318 return -3;
1291 }
1319 }
1292
1320
1293 static PyObject *ntobj_shortest(nodetreeObject *self, PyObject *args)
1321 static PyObject *ntobj_shortest(nodetreeObject *self, PyObject *args)
1294 {
1322 {
1295 PyObject *val;
1323 PyObject *val;
1296 char *node;
1324 char *node;
1297 int length;
1325 int length;
1298
1326
1299 if (!PyArg_ParseTuple(args, "O", &val))
1327 if (!PyArg_ParseTuple(args, "O", &val))
1300 return NULL;
1328 return NULL;
1301 if (node_check(val, &node) == -1)
1329 if (node_check(val, &node) == -1)
1302 return NULL;
1330 return NULL;
1303
1331
1304 length = nt_shortest(&self->nt, node);
1332 length = nt_shortest(&self->nt, node);
1305 if (length == -3)
1333 if (length == -3)
1306 return NULL;
1334 return NULL;
1307 if (length == -2) {
1335 if (length == -2) {
1308 raise_revlog_error();
1336 raise_revlog_error();
1309 return NULL;
1337 return NULL;
1310 }
1338 }
1311 return PyInt_FromLong(length);
1339 return PyInt_FromLong(length);
1312 }
1340 }
1313
1341
1314 static void nt_dealloc(nodetree *self)
1342 static void nt_dealloc(nodetree *self)
1315 {
1343 {
1316 free(self->nodes);
1344 free(self->nodes);
1317 self->nodes = NULL;
1345 self->nodes = NULL;
1318 }
1346 }
1319
1347
1320 static void ntobj_dealloc(nodetreeObject *self)
1348 static void ntobj_dealloc(nodetreeObject *self)
1321 {
1349 {
1322 Py_XDECREF(self->nt.index);
1350 Py_XDECREF(self->nt.index);
1323 nt_dealloc(&self->nt);
1351 nt_dealloc(&self->nt);
1324 PyObject_Del(self);
1352 PyObject_Del(self);
1325 }
1353 }
1326
1354
1327 static PyMethodDef ntobj_methods[] = {
1355 static PyMethodDef ntobj_methods[] = {
1328 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
1356 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
1329 "insert an index entry"},
1357 "insert an index entry"},
1330 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
1358 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
1331 "find length of shortest hex nodeid of a binary ID"},
1359 "find length of shortest hex nodeid of a binary ID"},
1332 {NULL} /* Sentinel */
1360 {NULL} /* Sentinel */
1333 };
1361 };
1334
1362
1335 static PyTypeObject nodetreeType = {
1363 static PyTypeObject nodetreeType = {
1336 PyVarObject_HEAD_INIT(NULL, 0) /* header */
1364 PyVarObject_HEAD_INIT(NULL, 0) /* header */
1337 "parsers.nodetree", /* tp_name */
1365 "parsers.nodetree", /* tp_name */
1338 sizeof(nodetreeObject), /* tp_basicsize */
1366 sizeof(nodetreeObject), /* tp_basicsize */
1339 0, /* tp_itemsize */
1367 0, /* tp_itemsize */
1340 (destructor)ntobj_dealloc, /* tp_dealloc */
1368 (destructor)ntobj_dealloc, /* tp_dealloc */
1341 0, /* tp_print */
1369 0, /* tp_print */
1342 0, /* tp_getattr */
1370 0, /* tp_getattr */
1343 0, /* tp_setattr */
1371 0, /* tp_setattr */
1344 0, /* tp_compare */
1372 0, /* tp_compare */
1345 0, /* tp_repr */
1373 0, /* tp_repr */
1346 0, /* tp_as_number */
1374 0, /* tp_as_number */
1347 0, /* tp_as_sequence */
1375 0, /* tp_as_sequence */
1348 0, /* tp_as_mapping */
1376 0, /* tp_as_mapping */
1349 0, /* tp_hash */
1377 0, /* tp_hash */
1350 0, /* tp_call */
1378 0, /* tp_call */
1351 0, /* tp_str */
1379 0, /* tp_str */
1352 0, /* tp_getattro */
1380 0, /* tp_getattro */
1353 0, /* tp_setattro */
1381 0, /* tp_setattro */
1354 0, /* tp_as_buffer */
1382 0, /* tp_as_buffer */
1355 Py_TPFLAGS_DEFAULT, /* tp_flags */
1383 Py_TPFLAGS_DEFAULT, /* tp_flags */
1356 "nodetree", /* tp_doc */
1384 "nodetree", /* tp_doc */
1357 0, /* tp_traverse */
1385 0, /* tp_traverse */
1358 0, /* tp_clear */
1386 0, /* tp_clear */
1359 0, /* tp_richcompare */
1387 0, /* tp_richcompare */
1360 0, /* tp_weaklistoffset */
1388 0, /* tp_weaklistoffset */
1361 0, /* tp_iter */
1389 0, /* tp_iter */
1362 0, /* tp_iternext */
1390 0, /* tp_iternext */
1363 ntobj_methods, /* tp_methods */
1391 ntobj_methods, /* tp_methods */
1364 0, /* tp_members */
1392 0, /* tp_members */
1365 0, /* tp_getset */
1393 0, /* tp_getset */
1366 0, /* tp_base */
1394 0, /* tp_base */
1367 0, /* tp_dict */
1395 0, /* tp_dict */
1368 0, /* tp_descr_get */
1396 0, /* tp_descr_get */
1369 0, /* tp_descr_set */
1397 0, /* tp_descr_set */
1370 0, /* tp_dictoffset */
1398 0, /* tp_dictoffset */
1371 (initproc)ntobj_init, /* tp_init */
1399 (initproc)ntobj_init, /* tp_init */
1372 0, /* tp_alloc */
1400 0, /* tp_alloc */
1373 };
1401 };
1374
1402
1375 static int index_init_nt(indexObject *self)
1403 static int index_init_nt(indexObject *self)
1376 {
1404 {
1377 if (!self->ntinitialized) {
1405 if (!self->ntinitialized) {
1378 if (nt_init(&self->nt, self, (int)self->raw_length) == -1) {
1406 if (nt_init(&self->nt, self, (int)self->raw_length) == -1) {
1379 nt_dealloc(&self->nt);
1407 nt_dealloc(&self->nt);
1380 return -1;
1408 return -1;
1381 }
1409 }
1382 if (nt_insert(&self->nt, nullid, -1) == -1) {
1410 if (nt_insert(&self->nt, nullid, -1) == -1) {
1383 nt_dealloc(&self->nt);
1411 nt_dealloc(&self->nt);
1384 return -1;
1412 return -1;
1385 }
1413 }
1386 self->ntinitialized = 1;
1414 self->ntinitialized = 1;
1387 self->ntrev = (int)index_length(self);
1415 self->ntrev = (int)index_length(self);
1388 self->ntlookups = 1;
1416 self->ntlookups = 1;
1389 self->ntmisses = 0;
1417 self->ntmisses = 0;
1390 }
1418 }
1391 return 0;
1419 return 0;
1392 }
1420 }
1393
1421
1394 /*
1422 /*
1395 * Return values:
1423 * Return values:
1396 *
1424 *
1397 * -3: error (exception set)
1425 * -3: error (exception set)
1398 * -2: not found (no exception set)
1426 * -2: not found (no exception set)
1399 * rest: valid rev
1427 * rest: valid rev
1400 */
1428 */
1401 static int index_find_node(indexObject *self, const char *node,
1429 static int index_find_node(indexObject *self, const char *node,
1402 Py_ssize_t nodelen)
1430 Py_ssize_t nodelen)
1403 {
1431 {
1404 int rev;
1432 int rev;
1405
1433
1406 if (index_init_nt(self) == -1)
1434 if (index_init_nt(self) == -1)
1407 return -3;
1435 return -3;
1408
1436
1409 self->ntlookups++;
1437 self->ntlookups++;
1410 rev = nt_find(&self->nt, node, nodelen, 0);
1438 rev = nt_find(&self->nt, node, nodelen, 0);
1411 if (rev >= -1)
1439 if (rev >= -1)
1412 return rev;
1440 return rev;
1413
1441
1414 /*
1442 /*
1415 * For the first handful of lookups, we scan the entire index,
1443 * For the first handful of lookups, we scan the entire index,
1416 * and cache only the matching nodes. This optimizes for cases
1444 * and cache only the matching nodes. This optimizes for cases
1417 * like "hg tip", where only a few nodes are accessed.
1445 * like "hg tip", where only a few nodes are accessed.
1418 *
1446 *
1419 * After that, we cache every node we visit, using a single
1447 * After that, we cache every node we visit, using a single
1420 * scan amortized over multiple lookups. This gives the best
1448 * scan amortized over multiple lookups. This gives the best
1421 * bulk performance, e.g. for "hg log".
1449 * bulk performance, e.g. for "hg log".
1422 */
1450 */
1423 if (self->ntmisses++ < 4) {
1451 if (self->ntmisses++ < 4) {
1424 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1452 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1425 const char *n = index_node_existing(self, rev);
1453 const char *n = index_node_existing(self, rev);
1426 if (n == NULL)
1454 if (n == NULL)
1427 return -3;
1455 return -3;
1428 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1456 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1429 if (nt_insert(&self->nt, n, rev) == -1)
1457 if (nt_insert(&self->nt, n, rev) == -1)
1430 return -3;
1458 return -3;
1431 break;
1459 break;
1432 }
1460 }
1433 }
1461 }
1434 } else {
1462 } else {
1435 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1463 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1436 const char *n = index_node_existing(self, rev);
1464 const char *n = index_node_existing(self, rev);
1437 if (n == NULL)
1465 if (n == NULL)
1438 return -3;
1466 return -3;
1439 if (nt_insert(&self->nt, n, rev) == -1) {
1467 if (nt_insert(&self->nt, n, rev) == -1) {
1440 self->ntrev = rev + 1;
1468 self->ntrev = rev + 1;
1441 return -3;
1469 return -3;
1442 }
1470 }
1443 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1471 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1444 break;
1472 break;
1445 }
1473 }
1446 }
1474 }
1447 self->ntrev = rev;
1475 self->ntrev = rev;
1448 }
1476 }
1449
1477
1450 if (rev >= 0)
1478 if (rev >= 0)
1451 return rev;
1479 return rev;
1452 return -2;
1480 return -2;
1453 }
1481 }
1454
1482
1455 static PyObject *index_getitem(indexObject *self, PyObject *value)
1483 static PyObject *index_getitem(indexObject *self, PyObject *value)
1456 {
1484 {
1457 char *node;
1485 char *node;
1458 int rev;
1486 int rev;
1459
1487
1460 if (PyInt_Check(value)) {
1488 if (PyInt_Check(value)) {
1461 long idx;
1489 long idx;
1462 if (!pylong_to_long(value, &idx)) {
1490 if (!pylong_to_long(value, &idx)) {
1463 return NULL;
1491 return NULL;
1464 }
1492 }
1465 return index_get(self, idx);
1493 return index_get(self, idx);
1466 }
1494 }
1467
1495
1468 if (node_check(value, &node) == -1)
1496 if (node_check(value, &node) == -1)
1469 return NULL;
1497 return NULL;
1470 rev = index_find_node(self, node, 20);
1498 rev = index_find_node(self, node, 20);
1471 if (rev >= -1)
1499 if (rev >= -1)
1472 return PyInt_FromLong(rev);
1500 return PyInt_FromLong(rev);
1473 if (rev == -2)
1501 if (rev == -2)
1474 raise_revlog_error();
1502 raise_revlog_error();
1475 return NULL;
1503 return NULL;
1476 }
1504 }
1477
1505
1478 /*
1506 /*
1479 * Fully populate the radix tree.
1507 * Fully populate the radix tree.
1480 */
1508 */
1481 static int index_populate_nt(indexObject *self)
1509 static int index_populate_nt(indexObject *self)
1482 {
1510 {
1483 int rev;
1511 int rev;
1484 if (self->ntrev > 0) {
1512 if (self->ntrev > 0) {
1485 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1513 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1486 const char *n = index_node_existing(self, rev);
1514 const char *n = index_node_existing(self, rev);
1487 if (n == NULL)
1515 if (n == NULL)
1488 return -1;
1516 return -1;
1489 if (nt_insert(&self->nt, n, rev) == -1)
1517 if (nt_insert(&self->nt, n, rev) == -1)
1490 return -1;
1518 return -1;
1491 }
1519 }
1492 self->ntrev = -1;
1520 self->ntrev = -1;
1493 }
1521 }
1494 return 0;
1522 return 0;
1495 }
1523 }
1496
1524
1497 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1525 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1498 {
1526 {
1499 const char *fullnode;
1527 const char *fullnode;
1500 int nodelen;
1528 int nodelen;
1501 char *node;
1529 char *node;
1502 int rev, i;
1530 int rev, i;
1503
1531
1504 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1532 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1505 return NULL;
1533 return NULL;
1506
1534
1507 if (nodelen < 1) {
1535 if (nodelen < 1) {
1508 PyErr_SetString(PyExc_ValueError, "key too short");
1536 PyErr_SetString(PyExc_ValueError, "key too short");
1509 return NULL;
1537 return NULL;
1510 }
1538 }
1511
1539
1512 if (nodelen > 40) {
1540 if (nodelen > 40) {
1513 PyErr_SetString(PyExc_ValueError, "key too long");
1541 PyErr_SetString(PyExc_ValueError, "key too long");
1514 return NULL;
1542 return NULL;
1515 }
1543 }
1516
1544
1517 for (i = 0; i < nodelen; i++)
1545 for (i = 0; i < nodelen; i++)
1518 hexdigit(node, i);
1546 hexdigit(node, i);
1519 if (PyErr_Occurred()) {
1547 if (PyErr_Occurred()) {
1520 /* input contains non-hex characters */
1548 /* input contains non-hex characters */
1521 PyErr_Clear();
1549 PyErr_Clear();
1522 Py_RETURN_NONE;
1550 Py_RETURN_NONE;
1523 }
1551 }
1524
1552
1525 if (index_init_nt(self) == -1)
1553 if (index_init_nt(self) == -1)
1526 return NULL;
1554 return NULL;
1527 if (index_populate_nt(self) == -1)
1555 if (index_populate_nt(self) == -1)
1528 return NULL;
1556 return NULL;
1529 rev = nt_partialmatch(&self->nt, node, nodelen);
1557 rev = nt_partialmatch(&self->nt, node, nodelen);
1530
1558
1531 switch (rev) {
1559 switch (rev) {
1532 case -4:
1560 case -4:
1533 raise_revlog_error();
1561 raise_revlog_error();
1534 return NULL;
1562 return NULL;
1535 case -2:
1563 case -2:
1536 Py_RETURN_NONE;
1564 Py_RETURN_NONE;
1537 case -1:
1565 case -1:
1538 return PyBytes_FromStringAndSize(nullid, 20);
1566 return PyBytes_FromStringAndSize(nullid, 20);
1539 }
1567 }
1540
1568
1541 fullnode = index_node_existing(self, rev);
1569 fullnode = index_node_existing(self, rev);
1542 if (fullnode == NULL) {
1570 if (fullnode == NULL) {
1543 return NULL;
1571 return NULL;
1544 }
1572 }
1545 return PyBytes_FromStringAndSize(fullnode, 20);
1573 return PyBytes_FromStringAndSize(fullnode, 20);
1546 }
1574 }
1547
1575
1548 static PyObject *index_shortest(indexObject *self, PyObject *args)
1576 static PyObject *index_shortest(indexObject *self, PyObject *args)
1549 {
1577 {
1550 PyObject *val;
1578 PyObject *val;
1551 char *node;
1579 char *node;
1552 int length;
1580 int length;
1553
1581
1554 if (!PyArg_ParseTuple(args, "O", &val))
1582 if (!PyArg_ParseTuple(args, "O", &val))
1555 return NULL;
1583 return NULL;
1556 if (node_check(val, &node) == -1)
1584 if (node_check(val, &node) == -1)
1557 return NULL;
1585 return NULL;
1558
1586
1559 self->ntlookups++;
1587 self->ntlookups++;
1560 if (index_init_nt(self) == -1)
1588 if (index_init_nt(self) == -1)
1561 return NULL;
1589 return NULL;
1562 if (index_populate_nt(self) == -1)
1590 if (index_populate_nt(self) == -1)
1563 return NULL;
1591 return NULL;
1564 length = nt_shortest(&self->nt, node);
1592 length = nt_shortest(&self->nt, node);
1565 if (length == -3)
1593 if (length == -3)
1566 return NULL;
1594 return NULL;
1567 if (length == -2) {
1595 if (length == -2) {
1568 raise_revlog_error();
1596 raise_revlog_error();
1569 return NULL;
1597 return NULL;
1570 }
1598 }
1571 return PyInt_FromLong(length);
1599 return PyInt_FromLong(length);
1572 }
1600 }
1573
1601
1574 static PyObject *index_m_get(indexObject *self, PyObject *args)
1602 static PyObject *index_m_get(indexObject *self, PyObject *args)
1575 {
1603 {
1576 PyObject *val;
1604 PyObject *val;
1577 char *node;
1605 char *node;
1578 int rev;
1606 int rev;
1579
1607
1580 if (!PyArg_ParseTuple(args, "O", &val))
1608 if (!PyArg_ParseTuple(args, "O", &val))
1581 return NULL;
1609 return NULL;
1582 if (node_check(val, &node) == -1)
1610 if (node_check(val, &node) == -1)
1583 return NULL;
1611 return NULL;
1584 rev = index_find_node(self, node, 20);
1612 rev = index_find_node(self, node, 20);
1585 if (rev == -3)
1613 if (rev == -3)
1586 return NULL;
1614 return NULL;
1587 if (rev == -2)
1615 if (rev == -2)
1588 Py_RETURN_NONE;
1616 Py_RETURN_NONE;
1589 return PyInt_FromLong(rev);
1617 return PyInt_FromLong(rev);
1590 }
1618 }
1591
1619
1592 static int index_contains(indexObject *self, PyObject *value)
1620 static int index_contains(indexObject *self, PyObject *value)
1593 {
1621 {
1594 char *node;
1622 char *node;
1595
1623
1596 if (PyInt_Check(value)) {
1624 if (PyInt_Check(value)) {
1597 long rev;
1625 long rev;
1598 if (!pylong_to_long(value, &rev)) {
1626 if (!pylong_to_long(value, &rev)) {
1599 return -1;
1627 return -1;
1600 }
1628 }
1601 return rev >= -1 && rev < index_length(self);
1629 return rev >= -1 && rev < index_length(self);
1602 }
1630 }
1603
1631
1604 if (node_check(value, &node) == -1)
1632 if (node_check(value, &node) == -1)
1605 return -1;
1633 return -1;
1606
1634
1607 switch (index_find_node(self, node, 20)) {
1635 switch (index_find_node(self, node, 20)) {
1608 case -3:
1636 case -3:
1609 return -1;
1637 return -1;
1610 case -2:
1638 case -2:
1611 return 0;
1639 return 0;
1612 default:
1640 default:
1613 return 1;
1641 return 1;
1614 }
1642 }
1615 }
1643 }
1616
1644
1617 typedef uint64_t bitmask;
1645 typedef uint64_t bitmask;
1618
1646
1619 /*
1647 /*
1620 * Given a disjoint set of revs, return all candidates for the
1648 * Given a disjoint set of revs, return all candidates for the
1621 * greatest common ancestor. In revset notation, this is the set
1649 * greatest common ancestor. In revset notation, this is the set
1622 * "heads(::a and ::b and ...)"
1650 * "heads(::a and ::b and ...)"
1623 */
1651 */
1624 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1652 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1625 int revcount)
1653 int revcount)
1626 {
1654 {
1627 const bitmask allseen = (1ull << revcount) - 1;
1655 const bitmask allseen = (1ull << revcount) - 1;
1628 const bitmask poison = 1ull << revcount;
1656 const bitmask poison = 1ull << revcount;
1629 PyObject *gca = PyList_New(0);
1657 PyObject *gca = PyList_New(0);
1630 int i, v, interesting;
1658 int i, v, interesting;
1631 int maxrev = -1;
1659 int maxrev = -1;
1632 bitmask sp;
1660 bitmask sp;
1633 bitmask *seen;
1661 bitmask *seen;
1634
1662
1635 if (gca == NULL)
1663 if (gca == NULL)
1636 return PyErr_NoMemory();
1664 return PyErr_NoMemory();
1637
1665
1638 for (i = 0; i < revcount; i++) {
1666 for (i = 0; i < revcount; i++) {
1639 if (revs[i] > maxrev)
1667 if (revs[i] > maxrev)
1640 maxrev = revs[i];
1668 maxrev = revs[i];
1641 }
1669 }
1642
1670
1643 seen = calloc(sizeof(*seen), maxrev + 1);
1671 seen = calloc(sizeof(*seen), maxrev + 1);
1644 if (seen == NULL) {
1672 if (seen == NULL) {
1645 Py_DECREF(gca);
1673 Py_DECREF(gca);
1646 return PyErr_NoMemory();
1674 return PyErr_NoMemory();
1647 }
1675 }
1648
1676
1649 for (i = 0; i < revcount; i++)
1677 for (i = 0; i < revcount; i++)
1650 seen[revs[i]] = 1ull << i;
1678 seen[revs[i]] = 1ull << i;
1651
1679
1652 interesting = revcount;
1680 interesting = revcount;
1653
1681
1654 for (v = maxrev; v >= 0 && interesting; v--) {
1682 for (v = maxrev; v >= 0 && interesting; v--) {
1655 bitmask sv = seen[v];
1683 bitmask sv = seen[v];
1656 int parents[2];
1684 int parents[2];
1657
1685
1658 if (!sv)
1686 if (!sv)
1659 continue;
1687 continue;
1660
1688
1661 if (sv < poison) {
1689 if (sv < poison) {
1662 interesting -= 1;
1690 interesting -= 1;
1663 if (sv == allseen) {
1691 if (sv == allseen) {
1664 PyObject *obj = PyInt_FromLong(v);
1692 PyObject *obj = PyInt_FromLong(v);
1665 if (obj == NULL)
1693 if (obj == NULL)
1666 goto bail;
1694 goto bail;
1667 if (PyList_Append(gca, obj) == -1) {
1695 if (PyList_Append(gca, obj) == -1) {
1668 Py_DECREF(obj);
1696 Py_DECREF(obj);
1669 goto bail;
1697 goto bail;
1670 }
1698 }
1671 sv |= poison;
1699 sv |= poison;
1672 for (i = 0; i < revcount; i++) {
1700 for (i = 0; i < revcount; i++) {
1673 if (revs[i] == v)
1701 if (revs[i] == v)
1674 goto done;
1702 goto done;
1675 }
1703 }
1676 }
1704 }
1677 }
1705 }
1678 if (index_get_parents(self, v, parents, maxrev) < 0)
1706 if (index_get_parents(self, v, parents, maxrev) < 0)
1679 goto bail;
1707 goto bail;
1680
1708
1681 for (i = 0; i < 2; i++) {
1709 for (i = 0; i < 2; i++) {
1682 int p = parents[i];
1710 int p = parents[i];
1683 if (p == -1)
1711 if (p == -1)
1684 continue;
1712 continue;
1685 sp = seen[p];
1713 sp = seen[p];
1686 if (sv < poison) {
1714 if (sv < poison) {
1687 if (sp == 0) {
1715 if (sp == 0) {
1688 seen[p] = sv;
1716 seen[p] = sv;
1689 interesting++;
1717 interesting++;
1690 } else if (sp != sv)
1718 } else if (sp != sv)
1691 seen[p] |= sv;
1719 seen[p] |= sv;
1692 } else {
1720 } else {
1693 if (sp && sp < poison)
1721 if (sp && sp < poison)
1694 interesting--;
1722 interesting--;
1695 seen[p] = sv;
1723 seen[p] = sv;
1696 }
1724 }
1697 }
1725 }
1698 }
1726 }
1699
1727
1700 done:
1728 done:
1701 free(seen);
1729 free(seen);
1702 return gca;
1730 return gca;
1703 bail:
1731 bail:
1704 free(seen);
1732 free(seen);
1705 Py_XDECREF(gca);
1733 Py_XDECREF(gca);
1706 return NULL;
1734 return NULL;
1707 }
1735 }
1708
1736
1709 /*
1737 /*
1710 * Given a disjoint set of revs, return the subset with the longest
1738 * Given a disjoint set of revs, return the subset with the longest
1711 * path to the root.
1739 * path to the root.
1712 */
1740 */
1713 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1741 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1714 {
1742 {
1715 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1743 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1716 static const Py_ssize_t capacity = 24;
1744 static const Py_ssize_t capacity = 24;
1717 int *depth, *interesting = NULL;
1745 int *depth, *interesting = NULL;
1718 int i, j, v, ninteresting;
1746 int i, j, v, ninteresting;
1719 PyObject *dict = NULL, *keys = NULL;
1747 PyObject *dict = NULL, *keys = NULL;
1720 long *seen = NULL;
1748 long *seen = NULL;
1721 int maxrev = -1;
1749 int maxrev = -1;
1722 long final;
1750 long final;
1723
1751
1724 if (revcount > capacity) {
1752 if (revcount > capacity) {
1725 PyErr_Format(PyExc_OverflowError,
1753 PyErr_Format(PyExc_OverflowError,
1726 "bitset size (%ld) > capacity (%ld)",
1754 "bitset size (%ld) > capacity (%ld)",
1727 (long)revcount, (long)capacity);
1755 (long)revcount, (long)capacity);
1728 return NULL;
1756 return NULL;
1729 }
1757 }
1730
1758
1731 for (i = 0; i < revcount; i++) {
1759 for (i = 0; i < revcount; i++) {
1732 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1760 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1733 if (n > maxrev)
1761 if (n > maxrev)
1734 maxrev = n;
1762 maxrev = n;
1735 }
1763 }
1736
1764
1737 depth = calloc(sizeof(*depth), maxrev + 1);
1765 depth = calloc(sizeof(*depth), maxrev + 1);
1738 if (depth == NULL)
1766 if (depth == NULL)
1739 return PyErr_NoMemory();
1767 return PyErr_NoMemory();
1740
1768
1741 seen = calloc(sizeof(*seen), maxrev + 1);
1769 seen = calloc(sizeof(*seen), maxrev + 1);
1742 if (seen == NULL) {
1770 if (seen == NULL) {
1743 PyErr_NoMemory();
1771 PyErr_NoMemory();
1744 goto bail;
1772 goto bail;
1745 }
1773 }
1746
1774
1747 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1775 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1748 if (interesting == NULL) {
1776 if (interesting == NULL) {
1749 PyErr_NoMemory();
1777 PyErr_NoMemory();
1750 goto bail;
1778 goto bail;
1751 }
1779 }
1752
1780
1753 if (PyList_Sort(revs) == -1)
1781 if (PyList_Sort(revs) == -1)
1754 goto bail;
1782 goto bail;
1755
1783
1756 for (i = 0; i < revcount; i++) {
1784 for (i = 0; i < revcount; i++) {
1757 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1785 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1758 long b = 1l << i;
1786 long b = 1l << i;
1759 depth[n] = 1;
1787 depth[n] = 1;
1760 seen[n] = b;
1788 seen[n] = b;
1761 interesting[b] = 1;
1789 interesting[b] = 1;
1762 }
1790 }
1763
1791
1764 /* invariant: ninteresting is the number of non-zero entries in
1792 /* invariant: ninteresting is the number of non-zero entries in
1765 * interesting. */
1793 * interesting. */
1766 ninteresting = (int)revcount;
1794 ninteresting = (int)revcount;
1767
1795
1768 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1796 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1769 int dv = depth[v];
1797 int dv = depth[v];
1770 int parents[2];
1798 int parents[2];
1771 long sv;
1799 long sv;
1772
1800
1773 if (dv == 0)
1801 if (dv == 0)
1774 continue;
1802 continue;
1775
1803
1776 sv = seen[v];
1804 sv = seen[v];
1777 if (index_get_parents(self, v, parents, maxrev) < 0)
1805 if (index_get_parents(self, v, parents, maxrev) < 0)
1778 goto bail;
1806 goto bail;
1779
1807
1780 for (i = 0; i < 2; i++) {
1808 for (i = 0; i < 2; i++) {
1781 int p = parents[i];
1809 int p = parents[i];
1782 long sp;
1810 long sp;
1783 int dp;
1811 int dp;
1784
1812
1785 if (p == -1)
1813 if (p == -1)
1786 continue;
1814 continue;
1787
1815
1788 dp = depth[p];
1816 dp = depth[p];
1789 sp = seen[p];
1817 sp = seen[p];
1790 if (dp <= dv) {
1818 if (dp <= dv) {
1791 depth[p] = dv + 1;
1819 depth[p] = dv + 1;
1792 if (sp != sv) {
1820 if (sp != sv) {
1793 interesting[sv] += 1;
1821 interesting[sv] += 1;
1794 seen[p] = sv;
1822 seen[p] = sv;
1795 if (sp) {
1823 if (sp) {
1796 interesting[sp] -= 1;
1824 interesting[sp] -= 1;
1797 if (interesting[sp] == 0)
1825 if (interesting[sp] == 0)
1798 ninteresting -= 1;
1826 ninteresting -= 1;
1799 }
1827 }
1800 }
1828 }
1801 } else if (dv == dp - 1) {
1829 } else if (dv == dp - 1) {
1802 long nsp = sp | sv;
1830 long nsp = sp | sv;
1803 if (nsp == sp)
1831 if (nsp == sp)
1804 continue;
1832 continue;
1805 seen[p] = nsp;
1833 seen[p] = nsp;
1806 interesting[sp] -= 1;
1834 interesting[sp] -= 1;
1807 if (interesting[sp] == 0)
1835 if (interesting[sp] == 0)
1808 ninteresting -= 1;
1836 ninteresting -= 1;
1809 if (interesting[nsp] == 0)
1837 if (interesting[nsp] == 0)
1810 ninteresting += 1;
1838 ninteresting += 1;
1811 interesting[nsp] += 1;
1839 interesting[nsp] += 1;
1812 }
1840 }
1813 }
1841 }
1814 interesting[sv] -= 1;
1842 interesting[sv] -= 1;
1815 if (interesting[sv] == 0)
1843 if (interesting[sv] == 0)
1816 ninteresting -= 1;
1844 ninteresting -= 1;
1817 }
1845 }
1818
1846
1819 final = 0;
1847 final = 0;
1820 j = ninteresting;
1848 j = ninteresting;
1821 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1849 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1822 if (interesting[i] == 0)
1850 if (interesting[i] == 0)
1823 continue;
1851 continue;
1824 final |= i;
1852 final |= i;
1825 j -= 1;
1853 j -= 1;
1826 }
1854 }
1827 if (final == 0) {
1855 if (final == 0) {
1828 keys = PyList_New(0);
1856 keys = PyList_New(0);
1829 goto bail;
1857 goto bail;
1830 }
1858 }
1831
1859
1832 dict = PyDict_New();
1860 dict = PyDict_New();
1833 if (dict == NULL)
1861 if (dict == NULL)
1834 goto bail;
1862 goto bail;
1835
1863
1836 for (i = 0; i < revcount; i++) {
1864 for (i = 0; i < revcount; i++) {
1837 PyObject *key;
1865 PyObject *key;
1838
1866
1839 if ((final & (1 << i)) == 0)
1867 if ((final & (1 << i)) == 0)
1840 continue;
1868 continue;
1841
1869
1842 key = PyList_GET_ITEM(revs, i);
1870 key = PyList_GET_ITEM(revs, i);
1843 Py_INCREF(key);
1871 Py_INCREF(key);
1844 Py_INCREF(Py_None);
1872 Py_INCREF(Py_None);
1845 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1873 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1846 Py_DECREF(key);
1874 Py_DECREF(key);
1847 Py_DECREF(Py_None);
1875 Py_DECREF(Py_None);
1848 goto bail;
1876 goto bail;
1849 }
1877 }
1850 }
1878 }
1851
1879
1852 keys = PyDict_Keys(dict);
1880 keys = PyDict_Keys(dict);
1853
1881
1854 bail:
1882 bail:
1855 free(depth);
1883 free(depth);
1856 free(seen);
1884 free(seen);
1857 free(interesting);
1885 free(interesting);
1858 Py_XDECREF(dict);
1886 Py_XDECREF(dict);
1859
1887
1860 return keys;
1888 return keys;
1861 }
1889 }
1862
1890
1863 /*
1891 /*
1864 * Given a (possibly overlapping) set of revs, return all the
1892 * Given a (possibly overlapping) set of revs, return all the
1865 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1893 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1866 */
1894 */
1867 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1895 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1868 {
1896 {
1869 PyObject *ret = NULL;
1897 PyObject *ret = NULL;
1870 Py_ssize_t argcount, i, len;
1898 Py_ssize_t argcount, i, len;
1871 bitmask repeat = 0;
1899 bitmask repeat = 0;
1872 int revcount = 0;
1900 int revcount = 0;
1873 int *revs;
1901 int *revs;
1874
1902
1875 argcount = PySequence_Length(args);
1903 argcount = PySequence_Length(args);
1876 revs = PyMem_Malloc(argcount * sizeof(*revs));
1904 revs = PyMem_Malloc(argcount * sizeof(*revs));
1877 if (argcount > 0 && revs == NULL)
1905 if (argcount > 0 && revs == NULL)
1878 return PyErr_NoMemory();
1906 return PyErr_NoMemory();
1879 len = index_length(self);
1907 len = index_length(self);
1880
1908
1881 for (i = 0; i < argcount; i++) {
1909 for (i = 0; i < argcount; i++) {
1882 static const int capacity = 24;
1910 static const int capacity = 24;
1883 PyObject *obj = PySequence_GetItem(args, i);
1911 PyObject *obj = PySequence_GetItem(args, i);
1884 bitmask x;
1912 bitmask x;
1885 long val;
1913 long val;
1886
1914
1887 if (!PyInt_Check(obj)) {
1915 if (!PyInt_Check(obj)) {
1888 PyErr_SetString(PyExc_TypeError,
1916 PyErr_SetString(PyExc_TypeError,
1889 "arguments must all be ints");
1917 "arguments must all be ints");
1890 Py_DECREF(obj);
1918 Py_DECREF(obj);
1891 goto bail;
1919 goto bail;
1892 }
1920 }
1893 val = PyInt_AsLong(obj);
1921 val = PyInt_AsLong(obj);
1894 Py_DECREF(obj);
1922 Py_DECREF(obj);
1895 if (val == -1) {
1923 if (val == -1) {
1896 ret = PyList_New(0);
1924 ret = PyList_New(0);
1897 goto done;
1925 goto done;
1898 }
1926 }
1899 if (val < 0 || val >= len) {
1927 if (val < 0 || val >= len) {
1900 PyErr_SetString(PyExc_IndexError, "index out of range");
1928 PyErr_SetString(PyExc_IndexError, "index out of range");
1901 goto bail;
1929 goto bail;
1902 }
1930 }
1903 /* this cheesy bloom filter lets us avoid some more
1931 /* this cheesy bloom filter lets us avoid some more
1904 * expensive duplicate checks in the common set-is-disjoint
1932 * expensive duplicate checks in the common set-is-disjoint
1905 * case */
1933 * case */
1906 x = 1ull << (val & 0x3f);
1934 x = 1ull << (val & 0x3f);
1907 if (repeat & x) {
1935 if (repeat & x) {
1908 int k;
1936 int k;
1909 for (k = 0; k < revcount; k++) {
1937 for (k = 0; k < revcount; k++) {
1910 if (val == revs[k])
1938 if (val == revs[k])
1911 goto duplicate;
1939 goto duplicate;
1912 }
1940 }
1913 } else
1941 } else
1914 repeat |= x;
1942 repeat |= x;
1915 if (revcount >= capacity) {
1943 if (revcount >= capacity) {
1916 PyErr_Format(PyExc_OverflowError,
1944 PyErr_Format(PyExc_OverflowError,
1917 "bitset size (%d) > capacity (%d)",
1945 "bitset size (%d) > capacity (%d)",
1918 revcount, capacity);
1946 revcount, capacity);
1919 goto bail;
1947 goto bail;
1920 }
1948 }
1921 revs[revcount++] = (int)val;
1949 revs[revcount++] = (int)val;
1922 duplicate:;
1950 duplicate:;
1923 }
1951 }
1924
1952
1925 if (revcount == 0) {
1953 if (revcount == 0) {
1926 ret = PyList_New(0);
1954 ret = PyList_New(0);
1927 goto done;
1955 goto done;
1928 }
1956 }
1929 if (revcount == 1) {
1957 if (revcount == 1) {
1930 PyObject *obj;
1958 PyObject *obj;
1931 ret = PyList_New(1);
1959 ret = PyList_New(1);
1932 if (ret == NULL)
1960 if (ret == NULL)
1933 goto bail;
1961 goto bail;
1934 obj = PyInt_FromLong(revs[0]);
1962 obj = PyInt_FromLong(revs[0]);
1935 if (obj == NULL)
1963 if (obj == NULL)
1936 goto bail;
1964 goto bail;
1937 PyList_SET_ITEM(ret, 0, obj);
1965 PyList_SET_ITEM(ret, 0, obj);
1938 goto done;
1966 goto done;
1939 }
1967 }
1940
1968
1941 ret = find_gca_candidates(self, revs, revcount);
1969 ret = find_gca_candidates(self, revs, revcount);
1942 if (ret == NULL)
1970 if (ret == NULL)
1943 goto bail;
1971 goto bail;
1944
1972
1945 done:
1973 done:
1946 PyMem_Free(revs);
1974 PyMem_Free(revs);
1947 return ret;
1975 return ret;
1948
1976
1949 bail:
1977 bail:
1950 PyMem_Free(revs);
1978 PyMem_Free(revs);
1951 Py_XDECREF(ret);
1979 Py_XDECREF(ret);
1952 return NULL;
1980 return NULL;
1953 }
1981 }
1954
1982
1955 /*
1983 /*
1956 * Given a (possibly overlapping) set of revs, return the greatest
1984 * Given a (possibly overlapping) set of revs, return the greatest
1957 * common ancestors: those with the longest path to the root.
1985 * common ancestors: those with the longest path to the root.
1958 */
1986 */
1959 static PyObject *index_ancestors(indexObject *self, PyObject *args)
1987 static PyObject *index_ancestors(indexObject *self, PyObject *args)
1960 {
1988 {
1961 PyObject *ret;
1989 PyObject *ret;
1962 PyObject *gca = index_commonancestorsheads(self, args);
1990 PyObject *gca = index_commonancestorsheads(self, args);
1963 if (gca == NULL)
1991 if (gca == NULL)
1964 return NULL;
1992 return NULL;
1965
1993
1966 if (PyList_GET_SIZE(gca) <= 1) {
1994 if (PyList_GET_SIZE(gca) <= 1) {
1967 return gca;
1995 return gca;
1968 }
1996 }
1969
1997
1970 ret = find_deepest(self, gca);
1998 ret = find_deepest(self, gca);
1971 Py_DECREF(gca);
1999 Py_DECREF(gca);
1972 return ret;
2000 return ret;
1973 }
2001 }
1974
2002
1975 /*
2003 /*
1976 * Invalidate any trie entries introduced by added revs.
2004 * Invalidate any trie entries introduced by added revs.
1977 */
2005 */
1978 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
2006 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
1979 {
2007 {
1980 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
2008 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
1981
2009
1982 for (i = start; i < len; i++) {
2010 for (i = start; i < len; i++) {
1983 PyObject *tuple = PyList_GET_ITEM(self->added, i);
2011 PyObject *tuple = PyList_GET_ITEM(self->added, i);
1984 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
2012 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
1985
2013
1986 nt_delete_node(&self->nt, PyBytes_AS_STRING(node));
2014 nt_delete_node(&self->nt, PyBytes_AS_STRING(node));
1987 }
2015 }
1988
2016
1989 if (start == 0)
2017 if (start == 0)
1990 Py_CLEAR(self->added);
2018 Py_CLEAR(self->added);
1991 }
2019 }
1992
2020
1993 /*
2021 /*
1994 * Delete a numeric range of revs, which must be at the end of the
2022 * Delete a numeric range of revs, which must be at the end of the
1995 * range, but exclude the sentinel nullid entry.
2023 * range, but exclude the sentinel nullid entry.
1996 */
2024 */
1997 static int index_slice_del(indexObject *self, PyObject *item)
2025 static int index_slice_del(indexObject *self, PyObject *item)
1998 {
2026 {
1999 Py_ssize_t start, stop, step, slicelength;
2027 Py_ssize_t start, stop, step, slicelength;
2000 Py_ssize_t length = index_length(self) + 1;
2028 Py_ssize_t length = index_length(self) + 1;
2001 int ret = 0;
2029 int ret = 0;
2002
2030
2003 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
2031 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
2004 #ifdef IS_PY3K
2032 #ifdef IS_PY3K
2005 if (PySlice_GetIndicesEx(item, length, &start, &stop, &step,
2033 if (PySlice_GetIndicesEx(item, length, &start, &stop, &step,
2006 &slicelength) < 0)
2034 &slicelength) < 0)
2007 #else
2035 #else
2008 if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop,
2036 if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop,
2009 &step, &slicelength) < 0)
2037 &step, &slicelength) < 0)
2010 #endif
2038 #endif
2011 return -1;
2039 return -1;
2012
2040
2013 if (slicelength <= 0)
2041 if (slicelength <= 0)
2014 return 0;
2042 return 0;
2015
2043
2016 if ((step < 0 && start < stop) || (step > 0 && start > stop))
2044 if ((step < 0 && start < stop) || (step > 0 && start > stop))
2017 stop = start;
2045 stop = start;
2018
2046
2019 if (step < 0) {
2047 if (step < 0) {
2020 stop = start + 1;
2048 stop = start + 1;
2021 start = stop + step * (slicelength - 1) - 1;
2049 start = stop + step * (slicelength - 1) - 1;
2022 step = -step;
2050 step = -step;
2023 }
2051 }
2024
2052
2025 if (step != 1) {
2053 if (step != 1) {
2026 PyErr_SetString(PyExc_ValueError,
2054 PyErr_SetString(PyExc_ValueError,
2027 "revlog index delete requires step size of 1");
2055 "revlog index delete requires step size of 1");
2028 return -1;
2056 return -1;
2029 }
2057 }
2030
2058
2031 if (stop != length - 1) {
2059 if (stop != length - 1) {
2032 PyErr_SetString(PyExc_IndexError,
2060 PyErr_SetString(PyExc_IndexError,
2033 "revlog index deletion indices are invalid");
2061 "revlog index deletion indices are invalid");
2034 return -1;
2062 return -1;
2035 }
2063 }
2036
2064
2037 if (start < self->length) {
2065 if (start < self->length) {
2038 if (self->ntinitialized) {
2066 if (self->ntinitialized) {
2039 Py_ssize_t i;
2067 Py_ssize_t i;
2040
2068
2041 for (i = start + 1; i < self->length; i++) {
2069 for (i = start + 1; i < self->length; i++) {
2042 const char *node = index_node_existing(self, i);
2070 const char *node = index_node_existing(self, i);
2043 if (node == NULL)
2071 if (node == NULL)
2044 return -1;
2072 return -1;
2045
2073
2046 nt_delete_node(&self->nt, node);
2074 nt_delete_node(&self->nt, node);
2047 }
2075 }
2048 if (self->added)
2076 if (self->added)
2049 index_invalidate_added(self, 0);
2077 index_invalidate_added(self, 0);
2050 if (self->ntrev > start)
2078 if (self->ntrev > start)
2051 self->ntrev = (int)start;
2079 self->ntrev = (int)start;
2052 }
2080 }
2053 self->length = start;
2081 self->length = start;
2054 if (start < self->raw_length) {
2082 if (start < self->raw_length) {
2055 if (self->cache) {
2083 if (self->cache) {
2056 Py_ssize_t i;
2084 Py_ssize_t i;
2057 for (i = start; i < self->raw_length; i++)
2085 for (i = start; i < self->raw_length; i++)
2058 Py_CLEAR(self->cache[i]);
2086 Py_CLEAR(self->cache[i]);
2059 }
2087 }
2060 self->raw_length = start;
2088 self->raw_length = start;
2061 }
2089 }
2062 goto done;
2090 goto done;
2063 }
2091 }
2064
2092
2065 if (self->ntinitialized) {
2093 if (self->ntinitialized) {
2066 index_invalidate_added(self, start - self->length);
2094 index_invalidate_added(self, start - self->length);
2067 if (self->ntrev > start)
2095 if (self->ntrev > start)
2068 self->ntrev = (int)start;
2096 self->ntrev = (int)start;
2069 }
2097 }
2070 if (self->added)
2098 if (self->added)
2071 ret = PyList_SetSlice(self->added, start - self->length,
2099 ret = PyList_SetSlice(self->added, start - self->length,
2072 PyList_GET_SIZE(self->added), NULL);
2100 PyList_GET_SIZE(self->added), NULL);
2073 done:
2101 done:
2074 Py_CLEAR(self->headrevs);
2102 Py_CLEAR(self->headrevs);
2075 return ret;
2103 return ret;
2076 }
2104 }
2077
2105
2078 /*
2106 /*
2079 * Supported ops:
2107 * Supported ops:
2080 *
2108 *
2081 * slice deletion
2109 * slice deletion
2082 * string assignment (extend node->rev mapping)
2110 * string assignment (extend node->rev mapping)
2083 * string deletion (shrink node->rev mapping)
2111 * string deletion (shrink node->rev mapping)
2084 */
2112 */
2085 static int index_assign_subscript(indexObject *self, PyObject *item,
2113 static int index_assign_subscript(indexObject *self, PyObject *item,
2086 PyObject *value)
2114 PyObject *value)
2087 {
2115 {
2088 char *node;
2116 char *node;
2089 long rev;
2117 long rev;
2090
2118
2091 if (PySlice_Check(item) && value == NULL)
2119 if (PySlice_Check(item) && value == NULL)
2092 return index_slice_del(self, item);
2120 return index_slice_del(self, item);
2093
2121
2094 if (node_check(item, &node) == -1)
2122 if (node_check(item, &node) == -1)
2095 return -1;
2123 return -1;
2096
2124
2097 if (value == NULL)
2125 if (value == NULL)
2098 return self->ntinitialized ? nt_delete_node(&self->nt, node)
2126 return self->ntinitialized ? nt_delete_node(&self->nt, node)
2099 : 0;
2127 : 0;
2100 rev = PyInt_AsLong(value);
2128 rev = PyInt_AsLong(value);
2101 if (rev > INT_MAX || rev < 0) {
2129 if (rev > INT_MAX || rev < 0) {
2102 if (!PyErr_Occurred())
2130 if (!PyErr_Occurred())
2103 PyErr_SetString(PyExc_ValueError, "rev out of range");
2131 PyErr_SetString(PyExc_ValueError, "rev out of range");
2104 return -1;
2132 return -1;
2105 }
2133 }
2106
2134
2107 if (index_init_nt(self) == -1)
2135 if (index_init_nt(self) == -1)
2108 return -1;
2136 return -1;
2109 return nt_insert(&self->nt, node, (int)rev);
2137 return nt_insert(&self->nt, node, (int)rev);
2110 }
2138 }
2111
2139
2112 /*
2140 /*
2113 * Find all RevlogNG entries in an index that has inline data. Update
2141 * Find all RevlogNG entries in an index that has inline data. Update
2114 * the optional "offsets" table with those entries.
2142 * the optional "offsets" table with those entries.
2115 */
2143 */
2116 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
2144 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
2117 {
2145 {
2118 const char *data = (const char *)self->buf.buf;
2146 const char *data = (const char *)self->buf.buf;
2119 Py_ssize_t pos = 0;
2147 Py_ssize_t pos = 0;
2120 Py_ssize_t end = self->buf.len;
2148 Py_ssize_t end = self->buf.len;
2121 long incr = v1_hdrsize;
2149 long incr = v1_hdrsize;
2122 Py_ssize_t len = 0;
2150 Py_ssize_t len = 0;
2123
2151
2124 while (pos + v1_hdrsize <= end && pos >= 0) {
2152 while (pos + v1_hdrsize <= end && pos >= 0) {
2125 uint32_t comp_len;
2153 uint32_t comp_len;
2126 /* 3rd element of header is length of compressed inline data */
2154 /* 3rd element of header is length of compressed inline data */
2127 comp_len = getbe32(data + pos + 8);
2155 comp_len = getbe32(data + pos + 8);
2128 incr = v1_hdrsize + comp_len;
2156 incr = v1_hdrsize + comp_len;
2129 if (offsets)
2157 if (offsets)
2130 offsets[len] = data + pos;
2158 offsets[len] = data + pos;
2131 len++;
2159 len++;
2132 pos += incr;
2160 pos += incr;
2133 }
2161 }
2134
2162
2135 if (pos != end) {
2163 if (pos != end) {
2136 if (!PyErr_Occurred())
2164 if (!PyErr_Occurred())
2137 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2165 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2138 return -1;
2166 return -1;
2139 }
2167 }
2140
2168
2141 return len;
2169 return len;
2142 }
2170 }
2143
2171
2144 static int index_init(indexObject *self, PyObject *args)
2172 static int index_init(indexObject *self, PyObject *args)
2145 {
2173 {
2146 PyObject *data_obj, *inlined_obj;
2174 PyObject *data_obj, *inlined_obj;
2147 Py_ssize_t size;
2175 Py_ssize_t size;
2148
2176
2149 /* Initialize before argument-checking to avoid index_dealloc() crash.
2177 /* Initialize before argument-checking to avoid index_dealloc() crash.
2150 */
2178 */
2151 self->raw_length = 0;
2179 self->raw_length = 0;
2152 self->added = NULL;
2180 self->added = NULL;
2153 self->cache = NULL;
2181 self->cache = NULL;
2154 self->data = NULL;
2182 self->data = NULL;
2155 memset(&self->buf, 0, sizeof(self->buf));
2183 memset(&self->buf, 0, sizeof(self->buf));
2156 self->headrevs = NULL;
2184 self->headrevs = NULL;
2157 self->filteredrevs = Py_None;
2185 self->filteredrevs = Py_None;
2158 Py_INCREF(Py_None);
2186 Py_INCREF(Py_None);
2159 self->ntinitialized = 0;
2187 self->ntinitialized = 0;
2160 self->offsets = NULL;
2188 self->offsets = NULL;
2161
2189
2162 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2190 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2163 return -1;
2191 return -1;
2164 if (!PyObject_CheckBuffer(data_obj)) {
2192 if (!PyObject_CheckBuffer(data_obj)) {
2165 PyErr_SetString(PyExc_TypeError,
2193 PyErr_SetString(PyExc_TypeError,
2166 "data does not support buffer interface");
2194 "data does not support buffer interface");
2167 return -1;
2195 return -1;
2168 }
2196 }
2169
2197
2170 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2198 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2171 return -1;
2199 return -1;
2172 size = self->buf.len;
2200 size = self->buf.len;
2173
2201
2174 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
2202 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
2175 self->data = data_obj;
2203 self->data = data_obj;
2176
2204
2177 self->ntlookups = self->ntmisses = 0;
2205 self->ntlookups = self->ntmisses = 0;
2178 self->ntrev = -1;
2206 self->ntrev = -1;
2179 Py_INCREF(self->data);
2207 Py_INCREF(self->data);
2180
2208
2181 if (self->inlined) {
2209 if (self->inlined) {
2182 Py_ssize_t len = inline_scan(self, NULL);
2210 Py_ssize_t len = inline_scan(self, NULL);
2183 if (len == -1)
2211 if (len == -1)
2184 goto bail;
2212 goto bail;
2185 self->raw_length = len;
2213 self->raw_length = len;
2186 self->length = len;
2214 self->length = len;
2187 } else {
2215 } else {
2188 if (size % v1_hdrsize) {
2216 if (size % v1_hdrsize) {
2189 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2217 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2190 goto bail;
2218 goto bail;
2191 }
2219 }
2192 self->raw_length = size / v1_hdrsize;
2220 self->raw_length = size / v1_hdrsize;
2193 self->length = self->raw_length;
2221 self->length = self->raw_length;
2194 }
2222 }
2195
2223
2196 return 0;
2224 return 0;
2197 bail:
2225 bail:
2198 return -1;
2226 return -1;
2199 }
2227 }
2200
2228
2201 static PyObject *index_nodemap(indexObject *self)
2229 static PyObject *index_nodemap(indexObject *self)
2202 {
2230 {
2203 Py_INCREF(self);
2231 Py_INCREF(self);
2204 return (PyObject *)self;
2232 return (PyObject *)self;
2205 }
2233 }
2206
2234
2207 static void _index_clearcaches(indexObject *self)
2235 static void _index_clearcaches(indexObject *self)
2208 {
2236 {
2209 if (self->cache) {
2237 if (self->cache) {
2210 Py_ssize_t i;
2238 Py_ssize_t i;
2211
2239
2212 for (i = 0; i < self->raw_length; i++)
2240 for (i = 0; i < self->raw_length; i++)
2213 Py_CLEAR(self->cache[i]);
2241 Py_CLEAR(self->cache[i]);
2214 free(self->cache);
2242 free(self->cache);
2215 self->cache = NULL;
2243 self->cache = NULL;
2216 }
2244 }
2217 if (self->offsets) {
2245 if (self->offsets) {
2218 PyMem_Free((void *)self->offsets);
2246 PyMem_Free((void *)self->offsets);
2219 self->offsets = NULL;
2247 self->offsets = NULL;
2220 }
2248 }
2221 if (self->ntinitialized) {
2249 if (self->ntinitialized) {
2222 nt_dealloc(&self->nt);
2250 nt_dealloc(&self->nt);
2223 }
2251 }
2224 self->ntinitialized = 0;
2252 self->ntinitialized = 0;
2225 Py_CLEAR(self->headrevs);
2253 Py_CLEAR(self->headrevs);
2226 }
2254 }
2227
2255
2228 static PyObject *index_clearcaches(indexObject *self)
2256 static PyObject *index_clearcaches(indexObject *self)
2229 {
2257 {
2230 _index_clearcaches(self);
2258 _index_clearcaches(self);
2231 self->ntrev = -1;
2259 self->ntrev = -1;
2232 self->ntlookups = self->ntmisses = 0;
2260 self->ntlookups = self->ntmisses = 0;
2233 Py_RETURN_NONE;
2261 Py_RETURN_NONE;
2234 }
2262 }
2235
2263
2236 static void index_dealloc(indexObject *self)
2264 static void index_dealloc(indexObject *self)
2237 {
2265 {
2238 _index_clearcaches(self);
2266 _index_clearcaches(self);
2239 Py_XDECREF(self->filteredrevs);
2267 Py_XDECREF(self->filteredrevs);
2240 if (self->buf.buf) {
2268 if (self->buf.buf) {
2241 PyBuffer_Release(&self->buf);
2269 PyBuffer_Release(&self->buf);
2242 memset(&self->buf, 0, sizeof(self->buf));
2270 memset(&self->buf, 0, sizeof(self->buf));
2243 }
2271 }
2244 Py_XDECREF(self->data);
2272 Py_XDECREF(self->data);
2245 Py_XDECREF(self->added);
2273 Py_XDECREF(self->added);
2246 PyObject_Del(self);
2274 PyObject_Del(self);
2247 }
2275 }
2248
2276
2249 static PySequenceMethods index_sequence_methods = {
2277 static PySequenceMethods index_sequence_methods = {
2250 (lenfunc)index_length, /* sq_length */
2278 (lenfunc)index_length, /* sq_length */
2251 0, /* sq_concat */
2279 0, /* sq_concat */
2252 0, /* sq_repeat */
2280 0, /* sq_repeat */
2253 (ssizeargfunc)index_get, /* sq_item */
2281 (ssizeargfunc)index_get, /* sq_item */
2254 0, /* sq_slice */
2282 0, /* sq_slice */
2255 0, /* sq_ass_item */
2283 0, /* sq_ass_item */
2256 0, /* sq_ass_slice */
2284 0, /* sq_ass_slice */
2257 (objobjproc)index_contains, /* sq_contains */
2285 (objobjproc)index_contains, /* sq_contains */
2258 };
2286 };
2259
2287
2260 static PyMappingMethods index_mapping_methods = {
2288 static PyMappingMethods index_mapping_methods = {
2261 (lenfunc)index_length, /* mp_length */
2289 (lenfunc)index_length, /* mp_length */
2262 (binaryfunc)index_getitem, /* mp_subscript */
2290 (binaryfunc)index_getitem, /* mp_subscript */
2263 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2291 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2264 };
2292 };
2265
2293
2266 static PyMethodDef index_methods[] = {
2294 static PyMethodDef index_methods[] = {
2267 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2295 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2268 "return the gca set of the given revs"},
2296 "return the gca set of the given revs"},
2269 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2297 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2270 METH_VARARGS,
2298 METH_VARARGS,
2271 "return the heads of the common ancestors of the given revs"},
2299 "return the heads of the common ancestors of the given revs"},
2272 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2300 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2273 "clear the index caches"},
2301 "clear the index caches"},
2274 {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"},
2302 {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"},
2275 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS,
2303 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS,
2276 "compute phases"},
2304 "compute phases"},
2277 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2305 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2278 "reachableroots"},
2306 "reachableroots"},
2279 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2307 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2280 "get head revisions"}, /* Can do filtering since 3.2 */
2308 "get head revisions"}, /* Can do filtering since 3.2 */
2281 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2309 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2282 "get filtered head revisions"}, /* Can always do filtering */
2310 "get filtered head revisions"}, /* Can always do filtering */
2283 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2311 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2284 "determine revisions with deltas to reconstruct fulltext"},
2312 "determine revisions with deltas to reconstruct fulltext"},
2285 {"append", (PyCFunction)index_append, METH_O, "append an index entry"},
2313 {"append", (PyCFunction)index_append, METH_O, "append an index entry"},
2286 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2314 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2287 "match a potentially ambiguous node ID"},
2315 "match a potentially ambiguous node ID"},
2288 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2316 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2289 "find length of shortest hex nodeid of a binary ID"},
2317 "find length of shortest hex nodeid of a binary ID"},
2290 {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
2318 {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
2291 {NULL} /* Sentinel */
2319 {NULL} /* Sentinel */
2292 };
2320 };
2293
2321
2294 static PyGetSetDef index_getset[] = {
2322 static PyGetSetDef index_getset[] = {
2295 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2323 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2296 {NULL} /* Sentinel */
2324 {NULL} /* Sentinel */
2297 };
2325 };
2298
2326
2299 static PyTypeObject indexType = {
2327 static PyTypeObject indexType = {
2300 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2328 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2301 "parsers.index", /* tp_name */
2329 "parsers.index", /* tp_name */
2302 sizeof(indexObject), /* tp_basicsize */
2330 sizeof(indexObject), /* tp_basicsize */
2303 0, /* tp_itemsize */
2331 0, /* tp_itemsize */
2304 (destructor)index_dealloc, /* tp_dealloc */
2332 (destructor)index_dealloc, /* tp_dealloc */
2305 0, /* tp_print */
2333 0, /* tp_print */
2306 0, /* tp_getattr */
2334 0, /* tp_getattr */
2307 0, /* tp_setattr */
2335 0, /* tp_setattr */
2308 0, /* tp_compare */
2336 0, /* tp_compare */
2309 0, /* tp_repr */
2337 0, /* tp_repr */
2310 0, /* tp_as_number */
2338 0, /* tp_as_number */
2311 &index_sequence_methods, /* tp_as_sequence */
2339 &index_sequence_methods, /* tp_as_sequence */
2312 &index_mapping_methods, /* tp_as_mapping */
2340 &index_mapping_methods, /* tp_as_mapping */
2313 0, /* tp_hash */
2341 0, /* tp_hash */
2314 0, /* tp_call */
2342 0, /* tp_call */
2315 0, /* tp_str */
2343 0, /* tp_str */
2316 0, /* tp_getattro */
2344 0, /* tp_getattro */
2317 0, /* tp_setattro */
2345 0, /* tp_setattro */
2318 0, /* tp_as_buffer */
2346 0, /* tp_as_buffer */
2319 Py_TPFLAGS_DEFAULT, /* tp_flags */
2347 Py_TPFLAGS_DEFAULT, /* tp_flags */
2320 "revlog index", /* tp_doc */
2348 "revlog index", /* tp_doc */
2321 0, /* tp_traverse */
2349 0, /* tp_traverse */
2322 0, /* tp_clear */
2350 0, /* tp_clear */
2323 0, /* tp_richcompare */
2351 0, /* tp_richcompare */
2324 0, /* tp_weaklistoffset */
2352 0, /* tp_weaklistoffset */
2325 0, /* tp_iter */
2353 0, /* tp_iter */
2326 0, /* tp_iternext */
2354 0, /* tp_iternext */
2327 index_methods, /* tp_methods */
2355 index_methods, /* tp_methods */
2328 0, /* tp_members */
2356 0, /* tp_members */
2329 index_getset, /* tp_getset */
2357 index_getset, /* tp_getset */
2330 0, /* tp_base */
2358 0, /* tp_base */
2331 0, /* tp_dict */
2359 0, /* tp_dict */
2332 0, /* tp_descr_get */
2360 0, /* tp_descr_get */
2333 0, /* tp_descr_set */
2361 0, /* tp_descr_set */
2334 0, /* tp_dictoffset */
2362 0, /* tp_dictoffset */
2335 (initproc)index_init, /* tp_init */
2363 (initproc)index_init, /* tp_init */
2336 0, /* tp_alloc */
2364 0, /* tp_alloc */
2337 };
2365 };
2338
2366
2339 /*
2367 /*
2340 * returns a tuple of the form (index, index, cache) with elements as
2368 * returns a tuple of the form (index, index, cache) with elements as
2341 * follows:
2369 * follows:
2342 *
2370 *
2343 * index: an index object that lazily parses RevlogNG records
2371 * index: an index object that lazily parses RevlogNG records
2344 * cache: if data is inlined, a tuple (0, index_file_content), else None
2372 * cache: if data is inlined, a tuple (0, index_file_content), else None
2345 * index_file_content could be a string, or a buffer
2373 * index_file_content could be a string, or a buffer
2346 *
2374 *
2347 * added complications are for backwards compatibility
2375 * added complications are for backwards compatibility
2348 */
2376 */
2349 PyObject *parse_index2(PyObject *self, PyObject *args)
2377 PyObject *parse_index2(PyObject *self, PyObject *args)
2350 {
2378 {
2351 PyObject *tuple = NULL, *cache = NULL;
2379 PyObject *tuple = NULL, *cache = NULL;
2352 indexObject *idx;
2380 indexObject *idx;
2353 int ret;
2381 int ret;
2354
2382
2355 idx = PyObject_New(indexObject, &indexType);
2383 idx = PyObject_New(indexObject, &indexType);
2356 if (idx == NULL)
2384 if (idx == NULL)
2357 goto bail;
2385 goto bail;
2358
2386
2359 ret = index_init(idx, args);
2387 ret = index_init(idx, args);
2360 if (ret == -1)
2388 if (ret == -1)
2361 goto bail;
2389 goto bail;
2362
2390
2363 if (idx->inlined) {
2391 if (idx->inlined) {
2364 cache = Py_BuildValue("iO", 0, idx->data);
2392 cache = Py_BuildValue("iO", 0, idx->data);
2365 if (cache == NULL)
2393 if (cache == NULL)
2366 goto bail;
2394 goto bail;
2367 } else {
2395 } else {
2368 cache = Py_None;
2396 cache = Py_None;
2369 Py_INCREF(cache);
2397 Py_INCREF(cache);
2370 }
2398 }
2371
2399
2372 tuple = Py_BuildValue("NN", idx, cache);
2400 tuple = Py_BuildValue("NN", idx, cache);
2373 if (!tuple)
2401 if (!tuple)
2374 goto bail;
2402 goto bail;
2375 return tuple;
2403 return tuple;
2376
2404
2377 bail:
2405 bail:
2378 Py_XDECREF(idx);
2406 Py_XDECREF(idx);
2379 Py_XDECREF(cache);
2407 Py_XDECREF(cache);
2380 Py_XDECREF(tuple);
2408 Py_XDECREF(tuple);
2381 return NULL;
2409 return NULL;
2382 }
2410 }
2383
2411
2384 #ifdef WITH_RUST
2412 #ifdef WITH_RUST
2385
2413
2386 /* rustlazyancestors: iteration over ancestors implemented in Rust
2414 /* rustlazyancestors: iteration over ancestors implemented in Rust
2387 *
2415 *
2388 * This class holds a reference to an index and to the Rust iterator.
2416 * This class holds a reference to an index and to the Rust iterator.
2389 */
2417 */
2390 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
2418 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
2391
2419
2392 struct rustlazyancestorsObjectStruct {
2420 struct rustlazyancestorsObjectStruct {
2393 PyObject_HEAD
2421 PyObject_HEAD
2394 /* Type-specific fields go here. */
2422 /* Type-specific fields go here. */
2395 indexObject *index; /* Ref kept to avoid GC'ing the index */
2423 indexObject *index; /* Ref kept to avoid GC'ing the index */
2396 void *iter; /* Rust iterator */
2424 void *iter; /* Rust iterator */
2397 };
2425 };
2398
2426
2399 /* FFI exposed from Rust code */
2427 /* FFI exposed from Rust code */
2400 rustlazyancestorsObject *
2428 rustlazyancestorsObject *
2401 rustlazyancestors_init(indexObject *index,
2429 rustlazyancestors_init(indexObject *index,
2402 /* to pass index_get_parents() */
2430 /* to pass index_get_parents() */
2403 int (*)(indexObject *, Py_ssize_t, int *, int),
2431 int (*)(indexObject *, Py_ssize_t, int *, int),
2404 /* intrevs vector */
2432 /* intrevs vector */
2405 Py_ssize_t initrevslen, long *initrevs, long stoprev,
2433 Py_ssize_t initrevslen, long *initrevs, long stoprev,
2406 int inclusive);
2434 int inclusive);
2407 void rustlazyancestors_drop(rustlazyancestorsObject *self);
2435 void rustlazyancestors_drop(rustlazyancestorsObject *self);
2408 int rustlazyancestors_next(rustlazyancestorsObject *self);
2436 int rustlazyancestors_next(rustlazyancestorsObject *self);
2409 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
2437 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
2410
2438
2411 /* CPython instance methods */
2439 /* CPython instance methods */
2412 static int rustla_init(rustlazyancestorsObject *self, PyObject *args)
2440 static int rustla_init(rustlazyancestorsObject *self, PyObject *args)
2413 {
2441 {
2414 PyObject *initrevsarg = NULL;
2442 PyObject *initrevsarg = NULL;
2415 PyObject *inclusivearg = NULL;
2443 PyObject *inclusivearg = NULL;
2416 long stoprev = 0;
2444 long stoprev = 0;
2417 long *initrevs = NULL;
2445 long *initrevs = NULL;
2418 int inclusive = 0;
2446 int inclusive = 0;
2419 Py_ssize_t i;
2447 Py_ssize_t i;
2420
2448
2421 indexObject *index;
2449 indexObject *index;
2422 if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type,
2450 if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type,
2423 &initrevsarg, &stoprev, &PyBool_Type,
2451 &initrevsarg, &stoprev, &PyBool_Type,
2424 &inclusivearg))
2452 &inclusivearg))
2425 return -1;
2453 return -1;
2426
2454
2427 Py_INCREF(index);
2455 Py_INCREF(index);
2428 self->index = index;
2456 self->index = index;
2429
2457
2430 if (inclusivearg == Py_True)
2458 if (inclusivearg == Py_True)
2431 inclusive = 1;
2459 inclusive = 1;
2432
2460
2433 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
2461 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
2434
2462
2435 initrevs = (long *)calloc(linit, sizeof(long));
2463 initrevs = (long *)calloc(linit, sizeof(long));
2436
2464
2437 if (initrevs == NULL) {
2465 if (initrevs == NULL) {
2438 PyErr_NoMemory();
2466 PyErr_NoMemory();
2439 goto bail;
2467 goto bail;
2440 }
2468 }
2441
2469
2442 for (i = 0; i < linit; i++) {
2470 for (i = 0; i < linit; i++) {
2443 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
2471 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
2444 }
2472 }
2445 if (PyErr_Occurred())
2473 if (PyErr_Occurred())
2446 goto bail;
2474 goto bail;
2447
2475
2448 self->iter = rustlazyancestors_init(index, index_get_parents, linit,
2476 self->iter = rustlazyancestors_init(index, index_get_parents, linit,
2449 initrevs, stoprev, inclusive);
2477 initrevs, stoprev, inclusive);
2450 if (self->iter == NULL) {
2478 if (self->iter == NULL) {
2451 /* if this is because of GraphError::ParentOutOfRange
2479 /* if this is because of GraphError::ParentOutOfRange
2452 * index_get_parents() has already set the proper ValueError */
2480 * index_get_parents() has already set the proper ValueError */
2453 goto bail;
2481 goto bail;
2454 }
2482 }
2455
2483
2456 free(initrevs);
2484 free(initrevs);
2457 return 0;
2485 return 0;
2458
2486
2459 bail:
2487 bail:
2460 free(initrevs);
2488 free(initrevs);
2461 return -1;
2489 return -1;
2462 };
2490 };
2463
2491
2464 static void rustla_dealloc(rustlazyancestorsObject *self)
2492 static void rustla_dealloc(rustlazyancestorsObject *self)
2465 {
2493 {
2466 Py_XDECREF(self->index);
2494 Py_XDECREF(self->index);
2467 if (self->iter != NULL) { /* can happen if rustla_init failed */
2495 if (self->iter != NULL) { /* can happen if rustla_init failed */
2468 rustlazyancestors_drop(self->iter);
2496 rustlazyancestors_drop(self->iter);
2469 }
2497 }
2470 PyObject_Del(self);
2498 PyObject_Del(self);
2471 }
2499 }
2472
2500
2473 static PyObject *rustla_next(rustlazyancestorsObject *self)
2501 static PyObject *rustla_next(rustlazyancestorsObject *self)
2474 {
2502 {
2475 int res = rustlazyancestors_next(self->iter);
2503 int res = rustlazyancestors_next(self->iter);
2476 if (res == -1) {
2504 if (res == -1) {
2477 /* Setting an explicit exception seems unnecessary
2505 /* Setting an explicit exception seems unnecessary
2478 * as examples from Python source code (Objects/rangeobjets.c
2506 * as examples from Python source code (Objects/rangeobjets.c
2479 * and Modules/_io/stringio.c) seem to demonstrate.
2507 * and Modules/_io/stringio.c) seem to demonstrate.
2480 */
2508 */
2481 return NULL;
2509 return NULL;
2482 }
2510 }
2483 return PyInt_FromLong(res);
2511 return PyInt_FromLong(res);
2484 }
2512 }
2485
2513
2486 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev)
2514 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev)
2487 {
2515 {
2488 long lrev;
2516 long lrev;
2489 if (!pylong_to_long(rev, &lrev)) {
2517 if (!pylong_to_long(rev, &lrev)) {
2490 PyErr_Clear();
2518 PyErr_Clear();
2491 return 0;
2519 return 0;
2492 }
2520 }
2493 return rustlazyancestors_contains(self->iter, lrev);
2521 return rustlazyancestors_contains(self->iter, lrev);
2494 }
2522 }
2495
2523
2496 static PySequenceMethods rustla_sequence_methods = {
2524 static PySequenceMethods rustla_sequence_methods = {
2497 0, /* sq_length */
2525 0, /* sq_length */
2498 0, /* sq_concat */
2526 0, /* sq_concat */
2499 0, /* sq_repeat */
2527 0, /* sq_repeat */
2500 0, /* sq_item */
2528 0, /* sq_item */
2501 0, /* sq_slice */
2529 0, /* sq_slice */
2502 0, /* sq_ass_item */
2530 0, /* sq_ass_item */
2503 0, /* sq_ass_slice */
2531 0, /* sq_ass_slice */
2504 (objobjproc)rustla_contains, /* sq_contains */
2532 (objobjproc)rustla_contains, /* sq_contains */
2505 };
2533 };
2506
2534
2507 static PyTypeObject rustlazyancestorsType = {
2535 static PyTypeObject rustlazyancestorsType = {
2508 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2536 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2509 "parsers.rustlazyancestors", /* tp_name */
2537 "parsers.rustlazyancestors", /* tp_name */
2510 sizeof(rustlazyancestorsObject), /* tp_basicsize */
2538 sizeof(rustlazyancestorsObject), /* tp_basicsize */
2511 0, /* tp_itemsize */
2539 0, /* tp_itemsize */
2512 (destructor)rustla_dealloc, /* tp_dealloc */
2540 (destructor)rustla_dealloc, /* tp_dealloc */
2513 0, /* tp_print */
2541 0, /* tp_print */
2514 0, /* tp_getattr */
2542 0, /* tp_getattr */
2515 0, /* tp_setattr */
2543 0, /* tp_setattr */
2516 0, /* tp_compare */
2544 0, /* tp_compare */
2517 0, /* tp_repr */
2545 0, /* tp_repr */
2518 0, /* tp_as_number */
2546 0, /* tp_as_number */
2519 &rustla_sequence_methods, /* tp_as_sequence */
2547 &rustla_sequence_methods, /* tp_as_sequence */
2520 0, /* tp_as_mapping */
2548 0, /* tp_as_mapping */
2521 0, /* tp_hash */
2549 0, /* tp_hash */
2522 0, /* tp_call */
2550 0, /* tp_call */
2523 0, /* tp_str */
2551 0, /* tp_str */
2524 0, /* tp_getattro */
2552 0, /* tp_getattro */
2525 0, /* tp_setattro */
2553 0, /* tp_setattro */
2526 0, /* tp_as_buffer */
2554 0, /* tp_as_buffer */
2527 Py_TPFLAGS_DEFAULT, /* tp_flags */
2555 Py_TPFLAGS_DEFAULT, /* tp_flags */
2528 "Iterator over ancestors, implemented in Rust", /* tp_doc */
2556 "Iterator over ancestors, implemented in Rust", /* tp_doc */
2529 0, /* tp_traverse */
2557 0, /* tp_traverse */
2530 0, /* tp_clear */
2558 0, /* tp_clear */
2531 0, /* tp_richcompare */
2559 0, /* tp_richcompare */
2532 0, /* tp_weaklistoffset */
2560 0, /* tp_weaklistoffset */
2533 0, /* tp_iter */
2561 0, /* tp_iter */
2534 (iternextfunc)rustla_next, /* tp_iternext */
2562 (iternextfunc)rustla_next, /* tp_iternext */
2535 0, /* tp_methods */
2563 0, /* tp_methods */
2536 0, /* tp_members */
2564 0, /* tp_members */
2537 0, /* tp_getset */
2565 0, /* tp_getset */
2538 0, /* tp_base */
2566 0, /* tp_base */
2539 0, /* tp_dict */
2567 0, /* tp_dict */
2540 0, /* tp_descr_get */
2568 0, /* tp_descr_get */
2541 0, /* tp_descr_set */
2569 0, /* tp_descr_set */
2542 0, /* tp_dictoffset */
2570 0, /* tp_dictoffset */
2543 (initproc)rustla_init, /* tp_init */
2571 (initproc)rustla_init, /* tp_init */
2544 0, /* tp_alloc */
2572 0, /* tp_alloc */
2545 };
2573 };
2546 #endif /* WITH_RUST */
2574 #endif /* WITH_RUST */
2547
2575
2548 void revlog_module_init(PyObject *mod)
2576 void revlog_module_init(PyObject *mod)
2549 {
2577 {
2550 indexType.tp_new = PyType_GenericNew;
2578 indexType.tp_new = PyType_GenericNew;
2551 if (PyType_Ready(&indexType) < 0)
2579 if (PyType_Ready(&indexType) < 0)
2552 return;
2580 return;
2553 Py_INCREF(&indexType);
2581 Py_INCREF(&indexType);
2554 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2582 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2555
2583
2556 nodetreeType.tp_new = PyType_GenericNew;
2584 nodetreeType.tp_new = PyType_GenericNew;
2557 if (PyType_Ready(&nodetreeType) < 0)
2585 if (PyType_Ready(&nodetreeType) < 0)
2558 return;
2586 return;
2559 Py_INCREF(&nodetreeType);
2587 Py_INCREF(&nodetreeType);
2560 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2588 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2561
2589
2562 if (!nullentry) {
2590 if (!nullentry) {
2563 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0,
2591 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0,
2564 0, -1, -1, -1, -1, nullid, 20);
2592 0, -1, -1, -1, -1, nullid, 20);
2565 }
2593 }
2566 if (nullentry)
2594 if (nullentry)
2567 PyObject_GC_UnTrack(nullentry);
2595 PyObject_GC_UnTrack(nullentry);
2568
2596
2569 #ifdef WITH_RUST
2597 #ifdef WITH_RUST
2570 rustlazyancestorsType.tp_new = PyType_GenericNew;
2598 rustlazyancestorsType.tp_new = PyType_GenericNew;
2571 if (PyType_Ready(&rustlazyancestorsType) < 0)
2599 if (PyType_Ready(&rustlazyancestorsType) < 0)
2572 return;
2600 return;
2573 Py_INCREF(&rustlazyancestorsType);
2601 Py_INCREF(&rustlazyancestorsType);
2574 PyModule_AddObject(mod, "rustlazyancestors",
2602 PyModule_AddObject(mod, "rustlazyancestors",
2575 (PyObject *)&rustlazyancestorsType);
2603 (PyObject *)&rustlazyancestorsType);
2576 #endif
2604 #endif
2577 }
2605 }
General Comments 0
You need to be logged in to leave comments. Login now