##// END OF EJS Templates
sparse-revlog: add a `trim_endidx` function in C...
Boris Feld -
r40742:0650be87 default
parent child Browse files
Show More
@@ -1,2605 +1,2623 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
1053 static inline int64_t
1054 index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t end_rev)
1054 index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t end_rev)
1055 {
1055 {
1056 int64_t start_offset;
1056 int64_t start_offset;
1057 int64_t end_offset;
1057 int64_t end_offset;
1058 int end_size;
1058 int end_size;
1059 start_offset = index_get_start(self, start_rev);
1059 start_offset = index_get_start(self, start_rev);
1060 if (start_offset < 0) {
1060 if (start_offset < 0) {
1061 return -1;
1061 return -1;
1062 }
1062 }
1063 end_offset = index_get_start(self, end_rev);
1063 end_offset = index_get_start(self, end_rev);
1064 if (end_offset < 0) {
1064 if (end_offset < 0) {
1065 return -1;
1065 return -1;
1066 }
1066 }
1067 end_size = index_get_length(self, end_rev);
1067 end_size = index_get_length(self, end_rev);
1068 if (end_size < 0) {
1068 if (end_size < 0) {
1069 return -1;
1069 return -1;
1070 }
1070 }
1071 if (end_offset < start_offset) {
1071 if (end_offset < start_offset) {
1072 PyErr_Format(PyExc_ValueError,
1072 PyErr_Format(PyExc_ValueError,
1073 "corrupted revlog index: inconsistent offset "
1073 "corrupted revlog index: inconsistent offset "
1074 "between revisions (%zd) and (%zd)",
1074 "between revisions (%zd) and (%zd)",
1075 start_rev, end_rev);
1075 start_rev, end_rev);
1076 return -1;
1076 return -1;
1077 }
1077 }
1078 return (end_offset - start_offset) + (int64_t)end_size;
1078 return (end_offset - start_offset) + (int64_t)end_size;
1079 }
1079 }
1080
1080
1081 /* returns revs[startidx:endidx] without empty trailing revs */
1082 static Py_ssize_t trim_endidx(indexObject *self, const Py_ssize_t *revs,
1083 Py_ssize_t startidx, Py_ssize_t endidx)
1084 {
1085 int length;
1086 while (endidx > 1 && endidx > startidx) {
1087 length = index_get_length(self, revs[endidx - 1]);
1088 if (length < 0) {
1089 return -1;
1090 }
1091 if (length != 0) {
1092 break;
1093 }
1094 endidx -= 1;
1095 }
1096 return endidx;
1097 }
1098
1081 static inline int nt_level(const char *node, Py_ssize_t level)
1099 static inline int nt_level(const char *node, Py_ssize_t level)
1082 {
1100 {
1083 int v = node[level >> 1];
1101 int v = node[level >> 1];
1084 if (!(level & 1))
1102 if (!(level & 1))
1085 v >>= 4;
1103 v >>= 4;
1086 return v & 0xf;
1104 return v & 0xf;
1087 }
1105 }
1088
1106
1089 /*
1107 /*
1090 * Return values:
1108 * Return values:
1091 *
1109 *
1092 * -4: match is ambiguous (multiple candidates)
1110 * -4: match is ambiguous (multiple candidates)
1093 * -2: not found
1111 * -2: not found
1094 * rest: valid rev
1112 * rest: valid rev
1095 */
1113 */
1096 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
1114 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
1097 int hex)
1115 int hex)
1098 {
1116 {
1099 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
1117 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
1100 int level, maxlevel, off;
1118 int level, maxlevel, off;
1101
1119
1102 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
1120 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
1103 return -1;
1121 return -1;
1104
1122
1105 if (hex)
1123 if (hex)
1106 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
1124 maxlevel = nodelen > 40 ? 40 : (int)nodelen;
1107 else
1125 else
1108 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
1126 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
1109
1127
1110 for (level = off = 0; level < maxlevel; level++) {
1128 for (level = off = 0; level < maxlevel; level++) {
1111 int k = getnybble(node, level);
1129 int k = getnybble(node, level);
1112 nodetreenode *n = &self->nodes[off];
1130 nodetreenode *n = &self->nodes[off];
1113 int v = n->children[k];
1131 int v = n->children[k];
1114
1132
1115 if (v < 0) {
1133 if (v < 0) {
1116 const char *n;
1134 const char *n;
1117 Py_ssize_t i;
1135 Py_ssize_t i;
1118
1136
1119 v = -(v + 2);
1137 v = -(v + 2);
1120 n = index_node(self->index, v);
1138 n = index_node(self->index, v);
1121 if (n == NULL)
1139 if (n == NULL)
1122 return -2;
1140 return -2;
1123 for (i = level; i < maxlevel; i++)
1141 for (i = level; i < maxlevel; i++)
1124 if (getnybble(node, i) != nt_level(n, i))
1142 if (getnybble(node, i) != nt_level(n, i))
1125 return -2;
1143 return -2;
1126 return v;
1144 return v;
1127 }
1145 }
1128 if (v == 0)
1146 if (v == 0)
1129 return -2;
1147 return -2;
1130 off = v;
1148 off = v;
1131 }
1149 }
1132 /* multiple matches against an ambiguous prefix */
1150 /* multiple matches against an ambiguous prefix */
1133 return -4;
1151 return -4;
1134 }
1152 }
1135
1153
1136 static int nt_new(nodetree *self)
1154 static int nt_new(nodetree *self)
1137 {
1155 {
1138 if (self->length == self->capacity) {
1156 if (self->length == self->capacity) {
1139 unsigned newcapacity;
1157 unsigned newcapacity;
1140 nodetreenode *newnodes;
1158 nodetreenode *newnodes;
1141 newcapacity = self->capacity * 2;
1159 newcapacity = self->capacity * 2;
1142 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
1160 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
1143 PyErr_SetString(PyExc_MemoryError,
1161 PyErr_SetString(PyExc_MemoryError,
1144 "overflow in nt_new");
1162 "overflow in nt_new");
1145 return -1;
1163 return -1;
1146 }
1164 }
1147 newnodes =
1165 newnodes =
1148 realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1166 realloc(self->nodes, newcapacity * sizeof(nodetreenode));
1149 if (newnodes == NULL) {
1167 if (newnodes == NULL) {
1150 PyErr_SetString(PyExc_MemoryError, "out of memory");
1168 PyErr_SetString(PyExc_MemoryError, "out of memory");
1151 return -1;
1169 return -1;
1152 }
1170 }
1153 self->capacity = newcapacity;
1171 self->capacity = newcapacity;
1154 self->nodes = newnodes;
1172 self->nodes = newnodes;
1155 memset(&self->nodes[self->length], 0,
1173 memset(&self->nodes[self->length], 0,
1156 sizeof(nodetreenode) * (self->capacity - self->length));
1174 sizeof(nodetreenode) * (self->capacity - self->length));
1157 }
1175 }
1158 return self->length++;
1176 return self->length++;
1159 }
1177 }
1160
1178
1161 static int nt_insert(nodetree *self, const char *node, int rev)
1179 static int nt_insert(nodetree *self, const char *node, int rev)
1162 {
1180 {
1163 int level = 0;
1181 int level = 0;
1164 int off = 0;
1182 int off = 0;
1165
1183
1166 while (level < 40) {
1184 while (level < 40) {
1167 int k = nt_level(node, level);
1185 int k = nt_level(node, level);
1168 nodetreenode *n;
1186 nodetreenode *n;
1169 int v;
1187 int v;
1170
1188
1171 n = &self->nodes[off];
1189 n = &self->nodes[off];
1172 v = n->children[k];
1190 v = n->children[k];
1173
1191
1174 if (v == 0) {
1192 if (v == 0) {
1175 n->children[k] = -rev - 2;
1193 n->children[k] = -rev - 2;
1176 return 0;
1194 return 0;
1177 }
1195 }
1178 if (v < 0) {
1196 if (v < 0) {
1179 const char *oldnode =
1197 const char *oldnode =
1180 index_node_existing(self->index, -(v + 2));
1198 index_node_existing(self->index, -(v + 2));
1181 int noff;
1199 int noff;
1182
1200
1183 if (oldnode == NULL)
1201 if (oldnode == NULL)
1184 return -1;
1202 return -1;
1185 if (!memcmp(oldnode, node, 20)) {
1203 if (!memcmp(oldnode, node, 20)) {
1186 n->children[k] = -rev - 2;
1204 n->children[k] = -rev - 2;
1187 return 0;
1205 return 0;
1188 }
1206 }
1189 noff = nt_new(self);
1207 noff = nt_new(self);
1190 if (noff == -1)
1208 if (noff == -1)
1191 return -1;
1209 return -1;
1192 /* self->nodes may have been changed by realloc */
1210 /* self->nodes may have been changed by realloc */
1193 self->nodes[off].children[k] = noff;
1211 self->nodes[off].children[k] = noff;
1194 off = noff;
1212 off = noff;
1195 n = &self->nodes[off];
1213 n = &self->nodes[off];
1196 n->children[nt_level(oldnode, ++level)] = v;
1214 n->children[nt_level(oldnode, ++level)] = v;
1197 if (level > self->depth)
1215 if (level > self->depth)
1198 self->depth = level;
1216 self->depth = level;
1199 self->splits += 1;
1217 self->splits += 1;
1200 } else {
1218 } else {
1201 level += 1;
1219 level += 1;
1202 off = v;
1220 off = v;
1203 }
1221 }
1204 }
1222 }
1205
1223
1206 return -1;
1224 return -1;
1207 }
1225 }
1208
1226
1209 static PyObject *ntobj_insert(nodetreeObject *self, PyObject *args)
1227 static PyObject *ntobj_insert(nodetreeObject *self, PyObject *args)
1210 {
1228 {
1211 Py_ssize_t rev;
1229 Py_ssize_t rev;
1212 const char *node;
1230 const char *node;
1213 Py_ssize_t length;
1231 Py_ssize_t length;
1214 if (!PyArg_ParseTuple(args, "n", &rev))
1232 if (!PyArg_ParseTuple(args, "n", &rev))
1215 return NULL;
1233 return NULL;
1216 length = index_length(self->nt.index);
1234 length = index_length(self->nt.index);
1217 if (rev < 0 || rev >= length) {
1235 if (rev < 0 || rev >= length) {
1218 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1236 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1219 return NULL;
1237 return NULL;
1220 }
1238 }
1221 node = index_node_existing(self->nt.index, rev);
1239 node = index_node_existing(self->nt.index, rev);
1222 if (nt_insert(&self->nt, node, (int)rev) == -1)
1240 if (nt_insert(&self->nt, node, (int)rev) == -1)
1223 return NULL;
1241 return NULL;
1224 Py_RETURN_NONE;
1242 Py_RETURN_NONE;
1225 }
1243 }
1226
1244
1227 static int nt_delete_node(nodetree *self, const char *node)
1245 static int nt_delete_node(nodetree *self, const char *node)
1228 {
1246 {
1229 /* rev==-2 happens to get encoded as 0, which is interpreted as not set
1247 /* rev==-2 happens to get encoded as 0, which is interpreted as not set
1230 */
1248 */
1231 return nt_insert(self, node, -2);
1249 return nt_insert(self, node, -2);
1232 }
1250 }
1233
1251
1234 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1252 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
1235 {
1253 {
1236 /* Initialize before overflow-checking to avoid nt_dealloc() crash. */
1254 /* Initialize before overflow-checking to avoid nt_dealloc() crash. */
1237 self->nodes = NULL;
1255 self->nodes = NULL;
1238
1256
1239 self->index = index;
1257 self->index = index;
1240 /* The input capacity is in terms of revisions, while the field is in
1258 /* The input capacity is in terms of revisions, while the field is in
1241 * terms of nodetree nodes. */
1259 * terms of nodetree nodes. */
1242 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1260 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1243 self->depth = 0;
1261 self->depth = 0;
1244 self->splits = 0;
1262 self->splits = 0;
1245 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1263 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1246 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1264 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1247 return -1;
1265 return -1;
1248 }
1266 }
1249 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1267 self->nodes = calloc(self->capacity, sizeof(nodetreenode));
1250 if (self->nodes == NULL) {
1268 if (self->nodes == NULL) {
1251 PyErr_NoMemory();
1269 PyErr_NoMemory();
1252 return -1;
1270 return -1;
1253 }
1271 }
1254 self->length = 1;
1272 self->length = 1;
1255 return 0;
1273 return 0;
1256 }
1274 }
1257
1275
1258 static PyTypeObject indexType;
1276 static PyTypeObject indexType;
1259
1277
1260 static int ntobj_init(nodetreeObject *self, PyObject *args)
1278 static int ntobj_init(nodetreeObject *self, PyObject *args)
1261 {
1279 {
1262 PyObject *index;
1280 PyObject *index;
1263 unsigned capacity;
1281 unsigned capacity;
1264 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1282 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1265 return -1;
1283 return -1;
1266 Py_INCREF(index);
1284 Py_INCREF(index);
1267 return nt_init(&self->nt, (indexObject *)index, capacity);
1285 return nt_init(&self->nt, (indexObject *)index, capacity);
1268 }
1286 }
1269
1287
1270 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen)
1288 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen)
1271 {
1289 {
1272 return nt_find(self, node, nodelen, 1);
1290 return nt_find(self, node, nodelen, 1);
1273 }
1291 }
1274
1292
1275 /*
1293 /*
1276 * Find the length of the shortest unique prefix of node.
1294 * Find the length of the shortest unique prefix of node.
1277 *
1295 *
1278 * Return values:
1296 * Return values:
1279 *
1297 *
1280 * -3: error (exception set)
1298 * -3: error (exception set)
1281 * -2: not found (no exception set)
1299 * -2: not found (no exception set)
1282 * rest: length of shortest prefix
1300 * rest: length of shortest prefix
1283 */
1301 */
1284 static int nt_shortest(nodetree *self, const char *node)
1302 static int nt_shortest(nodetree *self, const char *node)
1285 {
1303 {
1286 int level, off;
1304 int level, off;
1287
1305
1288 for (level = off = 0; level < 40; level++) {
1306 for (level = off = 0; level < 40; level++) {
1289 int k, v;
1307 int k, v;
1290 nodetreenode *n = &self->nodes[off];
1308 nodetreenode *n = &self->nodes[off];
1291 k = nt_level(node, level);
1309 k = nt_level(node, level);
1292 v = n->children[k];
1310 v = n->children[k];
1293 if (v < 0) {
1311 if (v < 0) {
1294 const char *n;
1312 const char *n;
1295 v = -(v + 2);
1313 v = -(v + 2);
1296 n = index_node_existing(self->index, v);
1314 n = index_node_existing(self->index, v);
1297 if (n == NULL)
1315 if (n == NULL)
1298 return -3;
1316 return -3;
1299 if (memcmp(node, n, 20) != 0)
1317 if (memcmp(node, n, 20) != 0)
1300 /*
1318 /*
1301 * Found a unique prefix, but it wasn't for the
1319 * Found a unique prefix, but it wasn't for the
1302 * requested node (i.e the requested node does
1320 * requested node (i.e the requested node does
1303 * not exist).
1321 * not exist).
1304 */
1322 */
1305 return -2;
1323 return -2;
1306 return level + 1;
1324 return level + 1;
1307 }
1325 }
1308 if (v == 0)
1326 if (v == 0)
1309 return -2;
1327 return -2;
1310 off = v;
1328 off = v;
1311 }
1329 }
1312 /*
1330 /*
1313 * The node was still not unique after 40 hex digits, so this won't
1331 * The node was still not unique after 40 hex digits, so this won't
1314 * happen. Also, if we get here, then there's a programming error in
1332 * happen. Also, if we get here, then there's a programming error in
1315 * this file that made us insert a node longer than 40 hex digits.
1333 * this file that made us insert a node longer than 40 hex digits.
1316 */
1334 */
1317 PyErr_SetString(PyExc_Exception, "broken node tree");
1335 PyErr_SetString(PyExc_Exception, "broken node tree");
1318 return -3;
1336 return -3;
1319 }
1337 }
1320
1338
1321 static PyObject *ntobj_shortest(nodetreeObject *self, PyObject *args)
1339 static PyObject *ntobj_shortest(nodetreeObject *self, PyObject *args)
1322 {
1340 {
1323 PyObject *val;
1341 PyObject *val;
1324 char *node;
1342 char *node;
1325 int length;
1343 int length;
1326
1344
1327 if (!PyArg_ParseTuple(args, "O", &val))
1345 if (!PyArg_ParseTuple(args, "O", &val))
1328 return NULL;
1346 return NULL;
1329 if (node_check(val, &node) == -1)
1347 if (node_check(val, &node) == -1)
1330 return NULL;
1348 return NULL;
1331
1349
1332 length = nt_shortest(&self->nt, node);
1350 length = nt_shortest(&self->nt, node);
1333 if (length == -3)
1351 if (length == -3)
1334 return NULL;
1352 return NULL;
1335 if (length == -2) {
1353 if (length == -2) {
1336 raise_revlog_error();
1354 raise_revlog_error();
1337 return NULL;
1355 return NULL;
1338 }
1356 }
1339 return PyInt_FromLong(length);
1357 return PyInt_FromLong(length);
1340 }
1358 }
1341
1359
1342 static void nt_dealloc(nodetree *self)
1360 static void nt_dealloc(nodetree *self)
1343 {
1361 {
1344 free(self->nodes);
1362 free(self->nodes);
1345 self->nodes = NULL;
1363 self->nodes = NULL;
1346 }
1364 }
1347
1365
1348 static void ntobj_dealloc(nodetreeObject *self)
1366 static void ntobj_dealloc(nodetreeObject *self)
1349 {
1367 {
1350 Py_XDECREF(self->nt.index);
1368 Py_XDECREF(self->nt.index);
1351 nt_dealloc(&self->nt);
1369 nt_dealloc(&self->nt);
1352 PyObject_Del(self);
1370 PyObject_Del(self);
1353 }
1371 }
1354
1372
1355 static PyMethodDef ntobj_methods[] = {
1373 static PyMethodDef ntobj_methods[] = {
1356 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
1374 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
1357 "insert an index entry"},
1375 "insert an index entry"},
1358 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
1376 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
1359 "find length of shortest hex nodeid of a binary ID"},
1377 "find length of shortest hex nodeid of a binary ID"},
1360 {NULL} /* Sentinel */
1378 {NULL} /* Sentinel */
1361 };
1379 };
1362
1380
1363 static PyTypeObject nodetreeType = {
1381 static PyTypeObject nodetreeType = {
1364 PyVarObject_HEAD_INIT(NULL, 0) /* header */
1382 PyVarObject_HEAD_INIT(NULL, 0) /* header */
1365 "parsers.nodetree", /* tp_name */
1383 "parsers.nodetree", /* tp_name */
1366 sizeof(nodetreeObject), /* tp_basicsize */
1384 sizeof(nodetreeObject), /* tp_basicsize */
1367 0, /* tp_itemsize */
1385 0, /* tp_itemsize */
1368 (destructor)ntobj_dealloc, /* tp_dealloc */
1386 (destructor)ntobj_dealloc, /* tp_dealloc */
1369 0, /* tp_print */
1387 0, /* tp_print */
1370 0, /* tp_getattr */
1388 0, /* tp_getattr */
1371 0, /* tp_setattr */
1389 0, /* tp_setattr */
1372 0, /* tp_compare */
1390 0, /* tp_compare */
1373 0, /* tp_repr */
1391 0, /* tp_repr */
1374 0, /* tp_as_number */
1392 0, /* tp_as_number */
1375 0, /* tp_as_sequence */
1393 0, /* tp_as_sequence */
1376 0, /* tp_as_mapping */
1394 0, /* tp_as_mapping */
1377 0, /* tp_hash */
1395 0, /* tp_hash */
1378 0, /* tp_call */
1396 0, /* tp_call */
1379 0, /* tp_str */
1397 0, /* tp_str */
1380 0, /* tp_getattro */
1398 0, /* tp_getattro */
1381 0, /* tp_setattro */
1399 0, /* tp_setattro */
1382 0, /* tp_as_buffer */
1400 0, /* tp_as_buffer */
1383 Py_TPFLAGS_DEFAULT, /* tp_flags */
1401 Py_TPFLAGS_DEFAULT, /* tp_flags */
1384 "nodetree", /* tp_doc */
1402 "nodetree", /* tp_doc */
1385 0, /* tp_traverse */
1403 0, /* tp_traverse */
1386 0, /* tp_clear */
1404 0, /* tp_clear */
1387 0, /* tp_richcompare */
1405 0, /* tp_richcompare */
1388 0, /* tp_weaklistoffset */
1406 0, /* tp_weaklistoffset */
1389 0, /* tp_iter */
1407 0, /* tp_iter */
1390 0, /* tp_iternext */
1408 0, /* tp_iternext */
1391 ntobj_methods, /* tp_methods */
1409 ntobj_methods, /* tp_methods */
1392 0, /* tp_members */
1410 0, /* tp_members */
1393 0, /* tp_getset */
1411 0, /* tp_getset */
1394 0, /* tp_base */
1412 0, /* tp_base */
1395 0, /* tp_dict */
1413 0, /* tp_dict */
1396 0, /* tp_descr_get */
1414 0, /* tp_descr_get */
1397 0, /* tp_descr_set */
1415 0, /* tp_descr_set */
1398 0, /* tp_dictoffset */
1416 0, /* tp_dictoffset */
1399 (initproc)ntobj_init, /* tp_init */
1417 (initproc)ntobj_init, /* tp_init */
1400 0, /* tp_alloc */
1418 0, /* tp_alloc */
1401 };
1419 };
1402
1420
1403 static int index_init_nt(indexObject *self)
1421 static int index_init_nt(indexObject *self)
1404 {
1422 {
1405 if (!self->ntinitialized) {
1423 if (!self->ntinitialized) {
1406 if (nt_init(&self->nt, self, (int)self->raw_length) == -1) {
1424 if (nt_init(&self->nt, self, (int)self->raw_length) == -1) {
1407 nt_dealloc(&self->nt);
1425 nt_dealloc(&self->nt);
1408 return -1;
1426 return -1;
1409 }
1427 }
1410 if (nt_insert(&self->nt, nullid, -1) == -1) {
1428 if (nt_insert(&self->nt, nullid, -1) == -1) {
1411 nt_dealloc(&self->nt);
1429 nt_dealloc(&self->nt);
1412 return -1;
1430 return -1;
1413 }
1431 }
1414 self->ntinitialized = 1;
1432 self->ntinitialized = 1;
1415 self->ntrev = (int)index_length(self);
1433 self->ntrev = (int)index_length(self);
1416 self->ntlookups = 1;
1434 self->ntlookups = 1;
1417 self->ntmisses = 0;
1435 self->ntmisses = 0;
1418 }
1436 }
1419 return 0;
1437 return 0;
1420 }
1438 }
1421
1439
1422 /*
1440 /*
1423 * Return values:
1441 * Return values:
1424 *
1442 *
1425 * -3: error (exception set)
1443 * -3: error (exception set)
1426 * -2: not found (no exception set)
1444 * -2: not found (no exception set)
1427 * rest: valid rev
1445 * rest: valid rev
1428 */
1446 */
1429 static int index_find_node(indexObject *self, const char *node,
1447 static int index_find_node(indexObject *self, const char *node,
1430 Py_ssize_t nodelen)
1448 Py_ssize_t nodelen)
1431 {
1449 {
1432 int rev;
1450 int rev;
1433
1451
1434 if (index_init_nt(self) == -1)
1452 if (index_init_nt(self) == -1)
1435 return -3;
1453 return -3;
1436
1454
1437 self->ntlookups++;
1455 self->ntlookups++;
1438 rev = nt_find(&self->nt, node, nodelen, 0);
1456 rev = nt_find(&self->nt, node, nodelen, 0);
1439 if (rev >= -1)
1457 if (rev >= -1)
1440 return rev;
1458 return rev;
1441
1459
1442 /*
1460 /*
1443 * For the first handful of lookups, we scan the entire index,
1461 * For the first handful of lookups, we scan the entire index,
1444 * and cache only the matching nodes. This optimizes for cases
1462 * and cache only the matching nodes. This optimizes for cases
1445 * like "hg tip", where only a few nodes are accessed.
1463 * like "hg tip", where only a few nodes are accessed.
1446 *
1464 *
1447 * After that, we cache every node we visit, using a single
1465 * After that, we cache every node we visit, using a single
1448 * scan amortized over multiple lookups. This gives the best
1466 * scan amortized over multiple lookups. This gives the best
1449 * bulk performance, e.g. for "hg log".
1467 * bulk performance, e.g. for "hg log".
1450 */
1468 */
1451 if (self->ntmisses++ < 4) {
1469 if (self->ntmisses++ < 4) {
1452 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1470 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1453 const char *n = index_node_existing(self, rev);
1471 const char *n = index_node_existing(self, rev);
1454 if (n == NULL)
1472 if (n == NULL)
1455 return -3;
1473 return -3;
1456 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1474 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1457 if (nt_insert(&self->nt, n, rev) == -1)
1475 if (nt_insert(&self->nt, n, rev) == -1)
1458 return -3;
1476 return -3;
1459 break;
1477 break;
1460 }
1478 }
1461 }
1479 }
1462 } else {
1480 } else {
1463 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1481 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1464 const char *n = index_node_existing(self, rev);
1482 const char *n = index_node_existing(self, rev);
1465 if (n == NULL)
1483 if (n == NULL)
1466 return -3;
1484 return -3;
1467 if (nt_insert(&self->nt, n, rev) == -1) {
1485 if (nt_insert(&self->nt, n, rev) == -1) {
1468 self->ntrev = rev + 1;
1486 self->ntrev = rev + 1;
1469 return -3;
1487 return -3;
1470 }
1488 }
1471 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1489 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1472 break;
1490 break;
1473 }
1491 }
1474 }
1492 }
1475 self->ntrev = rev;
1493 self->ntrev = rev;
1476 }
1494 }
1477
1495
1478 if (rev >= 0)
1496 if (rev >= 0)
1479 return rev;
1497 return rev;
1480 return -2;
1498 return -2;
1481 }
1499 }
1482
1500
1483 static PyObject *index_getitem(indexObject *self, PyObject *value)
1501 static PyObject *index_getitem(indexObject *self, PyObject *value)
1484 {
1502 {
1485 char *node;
1503 char *node;
1486 int rev;
1504 int rev;
1487
1505
1488 if (PyInt_Check(value)) {
1506 if (PyInt_Check(value)) {
1489 long idx;
1507 long idx;
1490 if (!pylong_to_long(value, &idx)) {
1508 if (!pylong_to_long(value, &idx)) {
1491 return NULL;
1509 return NULL;
1492 }
1510 }
1493 return index_get(self, idx);
1511 return index_get(self, idx);
1494 }
1512 }
1495
1513
1496 if (node_check(value, &node) == -1)
1514 if (node_check(value, &node) == -1)
1497 return NULL;
1515 return NULL;
1498 rev = index_find_node(self, node, 20);
1516 rev = index_find_node(self, node, 20);
1499 if (rev >= -1)
1517 if (rev >= -1)
1500 return PyInt_FromLong(rev);
1518 return PyInt_FromLong(rev);
1501 if (rev == -2)
1519 if (rev == -2)
1502 raise_revlog_error();
1520 raise_revlog_error();
1503 return NULL;
1521 return NULL;
1504 }
1522 }
1505
1523
1506 /*
1524 /*
1507 * Fully populate the radix tree.
1525 * Fully populate the radix tree.
1508 */
1526 */
1509 static int index_populate_nt(indexObject *self)
1527 static int index_populate_nt(indexObject *self)
1510 {
1528 {
1511 int rev;
1529 int rev;
1512 if (self->ntrev > 0) {
1530 if (self->ntrev > 0) {
1513 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1531 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1514 const char *n = index_node_existing(self, rev);
1532 const char *n = index_node_existing(self, rev);
1515 if (n == NULL)
1533 if (n == NULL)
1516 return -1;
1534 return -1;
1517 if (nt_insert(&self->nt, n, rev) == -1)
1535 if (nt_insert(&self->nt, n, rev) == -1)
1518 return -1;
1536 return -1;
1519 }
1537 }
1520 self->ntrev = -1;
1538 self->ntrev = -1;
1521 }
1539 }
1522 return 0;
1540 return 0;
1523 }
1541 }
1524
1542
1525 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1543 static PyObject *index_partialmatch(indexObject *self, PyObject *args)
1526 {
1544 {
1527 const char *fullnode;
1545 const char *fullnode;
1528 int nodelen;
1546 int nodelen;
1529 char *node;
1547 char *node;
1530 int rev, i;
1548 int rev, i;
1531
1549
1532 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1550 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &node, &nodelen))
1533 return NULL;
1551 return NULL;
1534
1552
1535 if (nodelen < 1) {
1553 if (nodelen < 1) {
1536 PyErr_SetString(PyExc_ValueError, "key too short");
1554 PyErr_SetString(PyExc_ValueError, "key too short");
1537 return NULL;
1555 return NULL;
1538 }
1556 }
1539
1557
1540 if (nodelen > 40) {
1558 if (nodelen > 40) {
1541 PyErr_SetString(PyExc_ValueError, "key too long");
1559 PyErr_SetString(PyExc_ValueError, "key too long");
1542 return NULL;
1560 return NULL;
1543 }
1561 }
1544
1562
1545 for (i = 0; i < nodelen; i++)
1563 for (i = 0; i < nodelen; i++)
1546 hexdigit(node, i);
1564 hexdigit(node, i);
1547 if (PyErr_Occurred()) {
1565 if (PyErr_Occurred()) {
1548 /* input contains non-hex characters */
1566 /* input contains non-hex characters */
1549 PyErr_Clear();
1567 PyErr_Clear();
1550 Py_RETURN_NONE;
1568 Py_RETURN_NONE;
1551 }
1569 }
1552
1570
1553 if (index_init_nt(self) == -1)
1571 if (index_init_nt(self) == -1)
1554 return NULL;
1572 return NULL;
1555 if (index_populate_nt(self) == -1)
1573 if (index_populate_nt(self) == -1)
1556 return NULL;
1574 return NULL;
1557 rev = nt_partialmatch(&self->nt, node, nodelen);
1575 rev = nt_partialmatch(&self->nt, node, nodelen);
1558
1576
1559 switch (rev) {
1577 switch (rev) {
1560 case -4:
1578 case -4:
1561 raise_revlog_error();
1579 raise_revlog_error();
1562 return NULL;
1580 return NULL;
1563 case -2:
1581 case -2:
1564 Py_RETURN_NONE;
1582 Py_RETURN_NONE;
1565 case -1:
1583 case -1:
1566 return PyBytes_FromStringAndSize(nullid, 20);
1584 return PyBytes_FromStringAndSize(nullid, 20);
1567 }
1585 }
1568
1586
1569 fullnode = index_node_existing(self, rev);
1587 fullnode = index_node_existing(self, rev);
1570 if (fullnode == NULL) {
1588 if (fullnode == NULL) {
1571 return NULL;
1589 return NULL;
1572 }
1590 }
1573 return PyBytes_FromStringAndSize(fullnode, 20);
1591 return PyBytes_FromStringAndSize(fullnode, 20);
1574 }
1592 }
1575
1593
1576 static PyObject *index_shortest(indexObject *self, PyObject *args)
1594 static PyObject *index_shortest(indexObject *self, PyObject *args)
1577 {
1595 {
1578 PyObject *val;
1596 PyObject *val;
1579 char *node;
1597 char *node;
1580 int length;
1598 int length;
1581
1599
1582 if (!PyArg_ParseTuple(args, "O", &val))
1600 if (!PyArg_ParseTuple(args, "O", &val))
1583 return NULL;
1601 return NULL;
1584 if (node_check(val, &node) == -1)
1602 if (node_check(val, &node) == -1)
1585 return NULL;
1603 return NULL;
1586
1604
1587 self->ntlookups++;
1605 self->ntlookups++;
1588 if (index_init_nt(self) == -1)
1606 if (index_init_nt(self) == -1)
1589 return NULL;
1607 return NULL;
1590 if (index_populate_nt(self) == -1)
1608 if (index_populate_nt(self) == -1)
1591 return NULL;
1609 return NULL;
1592 length = nt_shortest(&self->nt, node);
1610 length = nt_shortest(&self->nt, node);
1593 if (length == -3)
1611 if (length == -3)
1594 return NULL;
1612 return NULL;
1595 if (length == -2) {
1613 if (length == -2) {
1596 raise_revlog_error();
1614 raise_revlog_error();
1597 return NULL;
1615 return NULL;
1598 }
1616 }
1599 return PyInt_FromLong(length);
1617 return PyInt_FromLong(length);
1600 }
1618 }
1601
1619
1602 static PyObject *index_m_get(indexObject *self, PyObject *args)
1620 static PyObject *index_m_get(indexObject *self, PyObject *args)
1603 {
1621 {
1604 PyObject *val;
1622 PyObject *val;
1605 char *node;
1623 char *node;
1606 int rev;
1624 int rev;
1607
1625
1608 if (!PyArg_ParseTuple(args, "O", &val))
1626 if (!PyArg_ParseTuple(args, "O", &val))
1609 return NULL;
1627 return NULL;
1610 if (node_check(val, &node) == -1)
1628 if (node_check(val, &node) == -1)
1611 return NULL;
1629 return NULL;
1612 rev = index_find_node(self, node, 20);
1630 rev = index_find_node(self, node, 20);
1613 if (rev == -3)
1631 if (rev == -3)
1614 return NULL;
1632 return NULL;
1615 if (rev == -2)
1633 if (rev == -2)
1616 Py_RETURN_NONE;
1634 Py_RETURN_NONE;
1617 return PyInt_FromLong(rev);
1635 return PyInt_FromLong(rev);
1618 }
1636 }
1619
1637
1620 static int index_contains(indexObject *self, PyObject *value)
1638 static int index_contains(indexObject *self, PyObject *value)
1621 {
1639 {
1622 char *node;
1640 char *node;
1623
1641
1624 if (PyInt_Check(value)) {
1642 if (PyInt_Check(value)) {
1625 long rev;
1643 long rev;
1626 if (!pylong_to_long(value, &rev)) {
1644 if (!pylong_to_long(value, &rev)) {
1627 return -1;
1645 return -1;
1628 }
1646 }
1629 return rev >= -1 && rev < index_length(self);
1647 return rev >= -1 && rev < index_length(self);
1630 }
1648 }
1631
1649
1632 if (node_check(value, &node) == -1)
1650 if (node_check(value, &node) == -1)
1633 return -1;
1651 return -1;
1634
1652
1635 switch (index_find_node(self, node, 20)) {
1653 switch (index_find_node(self, node, 20)) {
1636 case -3:
1654 case -3:
1637 return -1;
1655 return -1;
1638 case -2:
1656 case -2:
1639 return 0;
1657 return 0;
1640 default:
1658 default:
1641 return 1;
1659 return 1;
1642 }
1660 }
1643 }
1661 }
1644
1662
1645 typedef uint64_t bitmask;
1663 typedef uint64_t bitmask;
1646
1664
1647 /*
1665 /*
1648 * Given a disjoint set of revs, return all candidates for the
1666 * Given a disjoint set of revs, return all candidates for the
1649 * greatest common ancestor. In revset notation, this is the set
1667 * greatest common ancestor. In revset notation, this is the set
1650 * "heads(::a and ::b and ...)"
1668 * "heads(::a and ::b and ...)"
1651 */
1669 */
1652 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1670 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
1653 int revcount)
1671 int revcount)
1654 {
1672 {
1655 const bitmask allseen = (1ull << revcount) - 1;
1673 const bitmask allseen = (1ull << revcount) - 1;
1656 const bitmask poison = 1ull << revcount;
1674 const bitmask poison = 1ull << revcount;
1657 PyObject *gca = PyList_New(0);
1675 PyObject *gca = PyList_New(0);
1658 int i, v, interesting;
1676 int i, v, interesting;
1659 int maxrev = -1;
1677 int maxrev = -1;
1660 bitmask sp;
1678 bitmask sp;
1661 bitmask *seen;
1679 bitmask *seen;
1662
1680
1663 if (gca == NULL)
1681 if (gca == NULL)
1664 return PyErr_NoMemory();
1682 return PyErr_NoMemory();
1665
1683
1666 for (i = 0; i < revcount; i++) {
1684 for (i = 0; i < revcount; i++) {
1667 if (revs[i] > maxrev)
1685 if (revs[i] > maxrev)
1668 maxrev = revs[i];
1686 maxrev = revs[i];
1669 }
1687 }
1670
1688
1671 seen = calloc(sizeof(*seen), maxrev + 1);
1689 seen = calloc(sizeof(*seen), maxrev + 1);
1672 if (seen == NULL) {
1690 if (seen == NULL) {
1673 Py_DECREF(gca);
1691 Py_DECREF(gca);
1674 return PyErr_NoMemory();
1692 return PyErr_NoMemory();
1675 }
1693 }
1676
1694
1677 for (i = 0; i < revcount; i++)
1695 for (i = 0; i < revcount; i++)
1678 seen[revs[i]] = 1ull << i;
1696 seen[revs[i]] = 1ull << i;
1679
1697
1680 interesting = revcount;
1698 interesting = revcount;
1681
1699
1682 for (v = maxrev; v >= 0 && interesting; v--) {
1700 for (v = maxrev; v >= 0 && interesting; v--) {
1683 bitmask sv = seen[v];
1701 bitmask sv = seen[v];
1684 int parents[2];
1702 int parents[2];
1685
1703
1686 if (!sv)
1704 if (!sv)
1687 continue;
1705 continue;
1688
1706
1689 if (sv < poison) {
1707 if (sv < poison) {
1690 interesting -= 1;
1708 interesting -= 1;
1691 if (sv == allseen) {
1709 if (sv == allseen) {
1692 PyObject *obj = PyInt_FromLong(v);
1710 PyObject *obj = PyInt_FromLong(v);
1693 if (obj == NULL)
1711 if (obj == NULL)
1694 goto bail;
1712 goto bail;
1695 if (PyList_Append(gca, obj) == -1) {
1713 if (PyList_Append(gca, obj) == -1) {
1696 Py_DECREF(obj);
1714 Py_DECREF(obj);
1697 goto bail;
1715 goto bail;
1698 }
1716 }
1699 sv |= poison;
1717 sv |= poison;
1700 for (i = 0; i < revcount; i++) {
1718 for (i = 0; i < revcount; i++) {
1701 if (revs[i] == v)
1719 if (revs[i] == v)
1702 goto done;
1720 goto done;
1703 }
1721 }
1704 }
1722 }
1705 }
1723 }
1706 if (index_get_parents(self, v, parents, maxrev) < 0)
1724 if (index_get_parents(self, v, parents, maxrev) < 0)
1707 goto bail;
1725 goto bail;
1708
1726
1709 for (i = 0; i < 2; i++) {
1727 for (i = 0; i < 2; i++) {
1710 int p = parents[i];
1728 int p = parents[i];
1711 if (p == -1)
1729 if (p == -1)
1712 continue;
1730 continue;
1713 sp = seen[p];
1731 sp = seen[p];
1714 if (sv < poison) {
1732 if (sv < poison) {
1715 if (sp == 0) {
1733 if (sp == 0) {
1716 seen[p] = sv;
1734 seen[p] = sv;
1717 interesting++;
1735 interesting++;
1718 } else if (sp != sv)
1736 } else if (sp != sv)
1719 seen[p] |= sv;
1737 seen[p] |= sv;
1720 } else {
1738 } else {
1721 if (sp && sp < poison)
1739 if (sp && sp < poison)
1722 interesting--;
1740 interesting--;
1723 seen[p] = sv;
1741 seen[p] = sv;
1724 }
1742 }
1725 }
1743 }
1726 }
1744 }
1727
1745
1728 done:
1746 done:
1729 free(seen);
1747 free(seen);
1730 return gca;
1748 return gca;
1731 bail:
1749 bail:
1732 free(seen);
1750 free(seen);
1733 Py_XDECREF(gca);
1751 Py_XDECREF(gca);
1734 return NULL;
1752 return NULL;
1735 }
1753 }
1736
1754
1737 /*
1755 /*
1738 * Given a disjoint set of revs, return the subset with the longest
1756 * Given a disjoint set of revs, return the subset with the longest
1739 * path to the root.
1757 * path to the root.
1740 */
1758 */
1741 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1759 static PyObject *find_deepest(indexObject *self, PyObject *revs)
1742 {
1760 {
1743 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1761 const Py_ssize_t revcount = PyList_GET_SIZE(revs);
1744 static const Py_ssize_t capacity = 24;
1762 static const Py_ssize_t capacity = 24;
1745 int *depth, *interesting = NULL;
1763 int *depth, *interesting = NULL;
1746 int i, j, v, ninteresting;
1764 int i, j, v, ninteresting;
1747 PyObject *dict = NULL, *keys = NULL;
1765 PyObject *dict = NULL, *keys = NULL;
1748 long *seen = NULL;
1766 long *seen = NULL;
1749 int maxrev = -1;
1767 int maxrev = -1;
1750 long final;
1768 long final;
1751
1769
1752 if (revcount > capacity) {
1770 if (revcount > capacity) {
1753 PyErr_Format(PyExc_OverflowError,
1771 PyErr_Format(PyExc_OverflowError,
1754 "bitset size (%ld) > capacity (%ld)",
1772 "bitset size (%ld) > capacity (%ld)",
1755 (long)revcount, (long)capacity);
1773 (long)revcount, (long)capacity);
1756 return NULL;
1774 return NULL;
1757 }
1775 }
1758
1776
1759 for (i = 0; i < revcount; i++) {
1777 for (i = 0; i < revcount; i++) {
1760 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1778 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1761 if (n > maxrev)
1779 if (n > maxrev)
1762 maxrev = n;
1780 maxrev = n;
1763 }
1781 }
1764
1782
1765 depth = calloc(sizeof(*depth), maxrev + 1);
1783 depth = calloc(sizeof(*depth), maxrev + 1);
1766 if (depth == NULL)
1784 if (depth == NULL)
1767 return PyErr_NoMemory();
1785 return PyErr_NoMemory();
1768
1786
1769 seen = calloc(sizeof(*seen), maxrev + 1);
1787 seen = calloc(sizeof(*seen), maxrev + 1);
1770 if (seen == NULL) {
1788 if (seen == NULL) {
1771 PyErr_NoMemory();
1789 PyErr_NoMemory();
1772 goto bail;
1790 goto bail;
1773 }
1791 }
1774
1792
1775 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1793 interesting = calloc(sizeof(*interesting), ((size_t)1) << revcount);
1776 if (interesting == NULL) {
1794 if (interesting == NULL) {
1777 PyErr_NoMemory();
1795 PyErr_NoMemory();
1778 goto bail;
1796 goto bail;
1779 }
1797 }
1780
1798
1781 if (PyList_Sort(revs) == -1)
1799 if (PyList_Sort(revs) == -1)
1782 goto bail;
1800 goto bail;
1783
1801
1784 for (i = 0; i < revcount; i++) {
1802 for (i = 0; i < revcount; i++) {
1785 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1803 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
1786 long b = 1l << i;
1804 long b = 1l << i;
1787 depth[n] = 1;
1805 depth[n] = 1;
1788 seen[n] = b;
1806 seen[n] = b;
1789 interesting[b] = 1;
1807 interesting[b] = 1;
1790 }
1808 }
1791
1809
1792 /* invariant: ninteresting is the number of non-zero entries in
1810 /* invariant: ninteresting is the number of non-zero entries in
1793 * interesting. */
1811 * interesting. */
1794 ninteresting = (int)revcount;
1812 ninteresting = (int)revcount;
1795
1813
1796 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1814 for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
1797 int dv = depth[v];
1815 int dv = depth[v];
1798 int parents[2];
1816 int parents[2];
1799 long sv;
1817 long sv;
1800
1818
1801 if (dv == 0)
1819 if (dv == 0)
1802 continue;
1820 continue;
1803
1821
1804 sv = seen[v];
1822 sv = seen[v];
1805 if (index_get_parents(self, v, parents, maxrev) < 0)
1823 if (index_get_parents(self, v, parents, maxrev) < 0)
1806 goto bail;
1824 goto bail;
1807
1825
1808 for (i = 0; i < 2; i++) {
1826 for (i = 0; i < 2; i++) {
1809 int p = parents[i];
1827 int p = parents[i];
1810 long sp;
1828 long sp;
1811 int dp;
1829 int dp;
1812
1830
1813 if (p == -1)
1831 if (p == -1)
1814 continue;
1832 continue;
1815
1833
1816 dp = depth[p];
1834 dp = depth[p];
1817 sp = seen[p];
1835 sp = seen[p];
1818 if (dp <= dv) {
1836 if (dp <= dv) {
1819 depth[p] = dv + 1;
1837 depth[p] = dv + 1;
1820 if (sp != sv) {
1838 if (sp != sv) {
1821 interesting[sv] += 1;
1839 interesting[sv] += 1;
1822 seen[p] = sv;
1840 seen[p] = sv;
1823 if (sp) {
1841 if (sp) {
1824 interesting[sp] -= 1;
1842 interesting[sp] -= 1;
1825 if (interesting[sp] == 0)
1843 if (interesting[sp] == 0)
1826 ninteresting -= 1;
1844 ninteresting -= 1;
1827 }
1845 }
1828 }
1846 }
1829 } else if (dv == dp - 1) {
1847 } else if (dv == dp - 1) {
1830 long nsp = sp | sv;
1848 long nsp = sp | sv;
1831 if (nsp == sp)
1849 if (nsp == sp)
1832 continue;
1850 continue;
1833 seen[p] = nsp;
1851 seen[p] = nsp;
1834 interesting[sp] -= 1;
1852 interesting[sp] -= 1;
1835 if (interesting[sp] == 0)
1853 if (interesting[sp] == 0)
1836 ninteresting -= 1;
1854 ninteresting -= 1;
1837 if (interesting[nsp] == 0)
1855 if (interesting[nsp] == 0)
1838 ninteresting += 1;
1856 ninteresting += 1;
1839 interesting[nsp] += 1;
1857 interesting[nsp] += 1;
1840 }
1858 }
1841 }
1859 }
1842 interesting[sv] -= 1;
1860 interesting[sv] -= 1;
1843 if (interesting[sv] == 0)
1861 if (interesting[sv] == 0)
1844 ninteresting -= 1;
1862 ninteresting -= 1;
1845 }
1863 }
1846
1864
1847 final = 0;
1865 final = 0;
1848 j = ninteresting;
1866 j = ninteresting;
1849 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1867 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) {
1850 if (interesting[i] == 0)
1868 if (interesting[i] == 0)
1851 continue;
1869 continue;
1852 final |= i;
1870 final |= i;
1853 j -= 1;
1871 j -= 1;
1854 }
1872 }
1855 if (final == 0) {
1873 if (final == 0) {
1856 keys = PyList_New(0);
1874 keys = PyList_New(0);
1857 goto bail;
1875 goto bail;
1858 }
1876 }
1859
1877
1860 dict = PyDict_New();
1878 dict = PyDict_New();
1861 if (dict == NULL)
1879 if (dict == NULL)
1862 goto bail;
1880 goto bail;
1863
1881
1864 for (i = 0; i < revcount; i++) {
1882 for (i = 0; i < revcount; i++) {
1865 PyObject *key;
1883 PyObject *key;
1866
1884
1867 if ((final & (1 << i)) == 0)
1885 if ((final & (1 << i)) == 0)
1868 continue;
1886 continue;
1869
1887
1870 key = PyList_GET_ITEM(revs, i);
1888 key = PyList_GET_ITEM(revs, i);
1871 Py_INCREF(key);
1889 Py_INCREF(key);
1872 Py_INCREF(Py_None);
1890 Py_INCREF(Py_None);
1873 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1891 if (PyDict_SetItem(dict, key, Py_None) == -1) {
1874 Py_DECREF(key);
1892 Py_DECREF(key);
1875 Py_DECREF(Py_None);
1893 Py_DECREF(Py_None);
1876 goto bail;
1894 goto bail;
1877 }
1895 }
1878 }
1896 }
1879
1897
1880 keys = PyDict_Keys(dict);
1898 keys = PyDict_Keys(dict);
1881
1899
1882 bail:
1900 bail:
1883 free(depth);
1901 free(depth);
1884 free(seen);
1902 free(seen);
1885 free(interesting);
1903 free(interesting);
1886 Py_XDECREF(dict);
1904 Py_XDECREF(dict);
1887
1905
1888 return keys;
1906 return keys;
1889 }
1907 }
1890
1908
1891 /*
1909 /*
1892 * Given a (possibly overlapping) set of revs, return all the
1910 * Given a (possibly overlapping) set of revs, return all the
1893 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1911 * common ancestors heads: heads(::args[0] and ::a[1] and ...)
1894 */
1912 */
1895 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1913 static PyObject *index_commonancestorsheads(indexObject *self, PyObject *args)
1896 {
1914 {
1897 PyObject *ret = NULL;
1915 PyObject *ret = NULL;
1898 Py_ssize_t argcount, i, len;
1916 Py_ssize_t argcount, i, len;
1899 bitmask repeat = 0;
1917 bitmask repeat = 0;
1900 int revcount = 0;
1918 int revcount = 0;
1901 int *revs;
1919 int *revs;
1902
1920
1903 argcount = PySequence_Length(args);
1921 argcount = PySequence_Length(args);
1904 revs = PyMem_Malloc(argcount * sizeof(*revs));
1922 revs = PyMem_Malloc(argcount * sizeof(*revs));
1905 if (argcount > 0 && revs == NULL)
1923 if (argcount > 0 && revs == NULL)
1906 return PyErr_NoMemory();
1924 return PyErr_NoMemory();
1907 len = index_length(self);
1925 len = index_length(self);
1908
1926
1909 for (i = 0; i < argcount; i++) {
1927 for (i = 0; i < argcount; i++) {
1910 static const int capacity = 24;
1928 static const int capacity = 24;
1911 PyObject *obj = PySequence_GetItem(args, i);
1929 PyObject *obj = PySequence_GetItem(args, i);
1912 bitmask x;
1930 bitmask x;
1913 long val;
1931 long val;
1914
1932
1915 if (!PyInt_Check(obj)) {
1933 if (!PyInt_Check(obj)) {
1916 PyErr_SetString(PyExc_TypeError,
1934 PyErr_SetString(PyExc_TypeError,
1917 "arguments must all be ints");
1935 "arguments must all be ints");
1918 Py_DECREF(obj);
1936 Py_DECREF(obj);
1919 goto bail;
1937 goto bail;
1920 }
1938 }
1921 val = PyInt_AsLong(obj);
1939 val = PyInt_AsLong(obj);
1922 Py_DECREF(obj);
1940 Py_DECREF(obj);
1923 if (val == -1) {
1941 if (val == -1) {
1924 ret = PyList_New(0);
1942 ret = PyList_New(0);
1925 goto done;
1943 goto done;
1926 }
1944 }
1927 if (val < 0 || val >= len) {
1945 if (val < 0 || val >= len) {
1928 PyErr_SetString(PyExc_IndexError, "index out of range");
1946 PyErr_SetString(PyExc_IndexError, "index out of range");
1929 goto bail;
1947 goto bail;
1930 }
1948 }
1931 /* this cheesy bloom filter lets us avoid some more
1949 /* this cheesy bloom filter lets us avoid some more
1932 * expensive duplicate checks in the common set-is-disjoint
1950 * expensive duplicate checks in the common set-is-disjoint
1933 * case */
1951 * case */
1934 x = 1ull << (val & 0x3f);
1952 x = 1ull << (val & 0x3f);
1935 if (repeat & x) {
1953 if (repeat & x) {
1936 int k;
1954 int k;
1937 for (k = 0; k < revcount; k++) {
1955 for (k = 0; k < revcount; k++) {
1938 if (val == revs[k])
1956 if (val == revs[k])
1939 goto duplicate;
1957 goto duplicate;
1940 }
1958 }
1941 } else
1959 } else
1942 repeat |= x;
1960 repeat |= x;
1943 if (revcount >= capacity) {
1961 if (revcount >= capacity) {
1944 PyErr_Format(PyExc_OverflowError,
1962 PyErr_Format(PyExc_OverflowError,
1945 "bitset size (%d) > capacity (%d)",
1963 "bitset size (%d) > capacity (%d)",
1946 revcount, capacity);
1964 revcount, capacity);
1947 goto bail;
1965 goto bail;
1948 }
1966 }
1949 revs[revcount++] = (int)val;
1967 revs[revcount++] = (int)val;
1950 duplicate:;
1968 duplicate:;
1951 }
1969 }
1952
1970
1953 if (revcount == 0) {
1971 if (revcount == 0) {
1954 ret = PyList_New(0);
1972 ret = PyList_New(0);
1955 goto done;
1973 goto done;
1956 }
1974 }
1957 if (revcount == 1) {
1975 if (revcount == 1) {
1958 PyObject *obj;
1976 PyObject *obj;
1959 ret = PyList_New(1);
1977 ret = PyList_New(1);
1960 if (ret == NULL)
1978 if (ret == NULL)
1961 goto bail;
1979 goto bail;
1962 obj = PyInt_FromLong(revs[0]);
1980 obj = PyInt_FromLong(revs[0]);
1963 if (obj == NULL)
1981 if (obj == NULL)
1964 goto bail;
1982 goto bail;
1965 PyList_SET_ITEM(ret, 0, obj);
1983 PyList_SET_ITEM(ret, 0, obj);
1966 goto done;
1984 goto done;
1967 }
1985 }
1968
1986
1969 ret = find_gca_candidates(self, revs, revcount);
1987 ret = find_gca_candidates(self, revs, revcount);
1970 if (ret == NULL)
1988 if (ret == NULL)
1971 goto bail;
1989 goto bail;
1972
1990
1973 done:
1991 done:
1974 PyMem_Free(revs);
1992 PyMem_Free(revs);
1975 return ret;
1993 return ret;
1976
1994
1977 bail:
1995 bail:
1978 PyMem_Free(revs);
1996 PyMem_Free(revs);
1979 Py_XDECREF(ret);
1997 Py_XDECREF(ret);
1980 return NULL;
1998 return NULL;
1981 }
1999 }
1982
2000
1983 /*
2001 /*
1984 * Given a (possibly overlapping) set of revs, return the greatest
2002 * Given a (possibly overlapping) set of revs, return the greatest
1985 * common ancestors: those with the longest path to the root.
2003 * common ancestors: those with the longest path to the root.
1986 */
2004 */
1987 static PyObject *index_ancestors(indexObject *self, PyObject *args)
2005 static PyObject *index_ancestors(indexObject *self, PyObject *args)
1988 {
2006 {
1989 PyObject *ret;
2007 PyObject *ret;
1990 PyObject *gca = index_commonancestorsheads(self, args);
2008 PyObject *gca = index_commonancestorsheads(self, args);
1991 if (gca == NULL)
2009 if (gca == NULL)
1992 return NULL;
2010 return NULL;
1993
2011
1994 if (PyList_GET_SIZE(gca) <= 1) {
2012 if (PyList_GET_SIZE(gca) <= 1) {
1995 return gca;
2013 return gca;
1996 }
2014 }
1997
2015
1998 ret = find_deepest(self, gca);
2016 ret = find_deepest(self, gca);
1999 Py_DECREF(gca);
2017 Py_DECREF(gca);
2000 return ret;
2018 return ret;
2001 }
2019 }
2002
2020
2003 /*
2021 /*
2004 * Invalidate any trie entries introduced by added revs.
2022 * Invalidate any trie entries introduced by added revs.
2005 */
2023 */
2006 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
2024 static void index_invalidate_added(indexObject *self, Py_ssize_t start)
2007 {
2025 {
2008 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
2026 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
2009
2027
2010 for (i = start; i < len; i++) {
2028 for (i = start; i < len; i++) {
2011 PyObject *tuple = PyList_GET_ITEM(self->added, i);
2029 PyObject *tuple = PyList_GET_ITEM(self->added, i);
2012 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
2030 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
2013
2031
2014 nt_delete_node(&self->nt, PyBytes_AS_STRING(node));
2032 nt_delete_node(&self->nt, PyBytes_AS_STRING(node));
2015 }
2033 }
2016
2034
2017 if (start == 0)
2035 if (start == 0)
2018 Py_CLEAR(self->added);
2036 Py_CLEAR(self->added);
2019 }
2037 }
2020
2038
2021 /*
2039 /*
2022 * Delete a numeric range of revs, which must be at the end of the
2040 * Delete a numeric range of revs, which must be at the end of the
2023 * range, but exclude the sentinel nullid entry.
2041 * range, but exclude the sentinel nullid entry.
2024 */
2042 */
2025 static int index_slice_del(indexObject *self, PyObject *item)
2043 static int index_slice_del(indexObject *self, PyObject *item)
2026 {
2044 {
2027 Py_ssize_t start, stop, step, slicelength;
2045 Py_ssize_t start, stop, step, slicelength;
2028 Py_ssize_t length = index_length(self) + 1;
2046 Py_ssize_t length = index_length(self) + 1;
2029 int ret = 0;
2047 int ret = 0;
2030
2048
2031 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
2049 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
2032 #ifdef IS_PY3K
2050 #ifdef IS_PY3K
2033 if (PySlice_GetIndicesEx(item, length, &start, &stop, &step,
2051 if (PySlice_GetIndicesEx(item, length, &start, &stop, &step,
2034 &slicelength) < 0)
2052 &slicelength) < 0)
2035 #else
2053 #else
2036 if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop,
2054 if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop,
2037 &step, &slicelength) < 0)
2055 &step, &slicelength) < 0)
2038 #endif
2056 #endif
2039 return -1;
2057 return -1;
2040
2058
2041 if (slicelength <= 0)
2059 if (slicelength <= 0)
2042 return 0;
2060 return 0;
2043
2061
2044 if ((step < 0 && start < stop) || (step > 0 && start > stop))
2062 if ((step < 0 && start < stop) || (step > 0 && start > stop))
2045 stop = start;
2063 stop = start;
2046
2064
2047 if (step < 0) {
2065 if (step < 0) {
2048 stop = start + 1;
2066 stop = start + 1;
2049 start = stop + step * (slicelength - 1) - 1;
2067 start = stop + step * (slicelength - 1) - 1;
2050 step = -step;
2068 step = -step;
2051 }
2069 }
2052
2070
2053 if (step != 1) {
2071 if (step != 1) {
2054 PyErr_SetString(PyExc_ValueError,
2072 PyErr_SetString(PyExc_ValueError,
2055 "revlog index delete requires step size of 1");
2073 "revlog index delete requires step size of 1");
2056 return -1;
2074 return -1;
2057 }
2075 }
2058
2076
2059 if (stop != length - 1) {
2077 if (stop != length - 1) {
2060 PyErr_SetString(PyExc_IndexError,
2078 PyErr_SetString(PyExc_IndexError,
2061 "revlog index deletion indices are invalid");
2079 "revlog index deletion indices are invalid");
2062 return -1;
2080 return -1;
2063 }
2081 }
2064
2082
2065 if (start < self->length) {
2083 if (start < self->length) {
2066 if (self->ntinitialized) {
2084 if (self->ntinitialized) {
2067 Py_ssize_t i;
2085 Py_ssize_t i;
2068
2086
2069 for (i = start + 1; i < self->length; i++) {
2087 for (i = start + 1; i < self->length; i++) {
2070 const char *node = index_node_existing(self, i);
2088 const char *node = index_node_existing(self, i);
2071 if (node == NULL)
2089 if (node == NULL)
2072 return -1;
2090 return -1;
2073
2091
2074 nt_delete_node(&self->nt, node);
2092 nt_delete_node(&self->nt, node);
2075 }
2093 }
2076 if (self->added)
2094 if (self->added)
2077 index_invalidate_added(self, 0);
2095 index_invalidate_added(self, 0);
2078 if (self->ntrev > start)
2096 if (self->ntrev > start)
2079 self->ntrev = (int)start;
2097 self->ntrev = (int)start;
2080 }
2098 }
2081 self->length = start;
2099 self->length = start;
2082 if (start < self->raw_length) {
2100 if (start < self->raw_length) {
2083 if (self->cache) {
2101 if (self->cache) {
2084 Py_ssize_t i;
2102 Py_ssize_t i;
2085 for (i = start; i < self->raw_length; i++)
2103 for (i = start; i < self->raw_length; i++)
2086 Py_CLEAR(self->cache[i]);
2104 Py_CLEAR(self->cache[i]);
2087 }
2105 }
2088 self->raw_length = start;
2106 self->raw_length = start;
2089 }
2107 }
2090 goto done;
2108 goto done;
2091 }
2109 }
2092
2110
2093 if (self->ntinitialized) {
2111 if (self->ntinitialized) {
2094 index_invalidate_added(self, start - self->length);
2112 index_invalidate_added(self, start - self->length);
2095 if (self->ntrev > start)
2113 if (self->ntrev > start)
2096 self->ntrev = (int)start;
2114 self->ntrev = (int)start;
2097 }
2115 }
2098 if (self->added)
2116 if (self->added)
2099 ret = PyList_SetSlice(self->added, start - self->length,
2117 ret = PyList_SetSlice(self->added, start - self->length,
2100 PyList_GET_SIZE(self->added), NULL);
2118 PyList_GET_SIZE(self->added), NULL);
2101 done:
2119 done:
2102 Py_CLEAR(self->headrevs);
2120 Py_CLEAR(self->headrevs);
2103 return ret;
2121 return ret;
2104 }
2122 }
2105
2123
2106 /*
2124 /*
2107 * Supported ops:
2125 * Supported ops:
2108 *
2126 *
2109 * slice deletion
2127 * slice deletion
2110 * string assignment (extend node->rev mapping)
2128 * string assignment (extend node->rev mapping)
2111 * string deletion (shrink node->rev mapping)
2129 * string deletion (shrink node->rev mapping)
2112 */
2130 */
2113 static int index_assign_subscript(indexObject *self, PyObject *item,
2131 static int index_assign_subscript(indexObject *self, PyObject *item,
2114 PyObject *value)
2132 PyObject *value)
2115 {
2133 {
2116 char *node;
2134 char *node;
2117 long rev;
2135 long rev;
2118
2136
2119 if (PySlice_Check(item) && value == NULL)
2137 if (PySlice_Check(item) && value == NULL)
2120 return index_slice_del(self, item);
2138 return index_slice_del(self, item);
2121
2139
2122 if (node_check(item, &node) == -1)
2140 if (node_check(item, &node) == -1)
2123 return -1;
2141 return -1;
2124
2142
2125 if (value == NULL)
2143 if (value == NULL)
2126 return self->ntinitialized ? nt_delete_node(&self->nt, node)
2144 return self->ntinitialized ? nt_delete_node(&self->nt, node)
2127 : 0;
2145 : 0;
2128 rev = PyInt_AsLong(value);
2146 rev = PyInt_AsLong(value);
2129 if (rev > INT_MAX || rev < 0) {
2147 if (rev > INT_MAX || rev < 0) {
2130 if (!PyErr_Occurred())
2148 if (!PyErr_Occurred())
2131 PyErr_SetString(PyExc_ValueError, "rev out of range");
2149 PyErr_SetString(PyExc_ValueError, "rev out of range");
2132 return -1;
2150 return -1;
2133 }
2151 }
2134
2152
2135 if (index_init_nt(self) == -1)
2153 if (index_init_nt(self) == -1)
2136 return -1;
2154 return -1;
2137 return nt_insert(&self->nt, node, (int)rev);
2155 return nt_insert(&self->nt, node, (int)rev);
2138 }
2156 }
2139
2157
2140 /*
2158 /*
2141 * Find all RevlogNG entries in an index that has inline data. Update
2159 * Find all RevlogNG entries in an index that has inline data. Update
2142 * the optional "offsets" table with those entries.
2160 * the optional "offsets" table with those entries.
2143 */
2161 */
2144 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
2162 static Py_ssize_t inline_scan(indexObject *self, const char **offsets)
2145 {
2163 {
2146 const char *data = (const char *)self->buf.buf;
2164 const char *data = (const char *)self->buf.buf;
2147 Py_ssize_t pos = 0;
2165 Py_ssize_t pos = 0;
2148 Py_ssize_t end = self->buf.len;
2166 Py_ssize_t end = self->buf.len;
2149 long incr = v1_hdrsize;
2167 long incr = v1_hdrsize;
2150 Py_ssize_t len = 0;
2168 Py_ssize_t len = 0;
2151
2169
2152 while (pos + v1_hdrsize <= end && pos >= 0) {
2170 while (pos + v1_hdrsize <= end && pos >= 0) {
2153 uint32_t comp_len;
2171 uint32_t comp_len;
2154 /* 3rd element of header is length of compressed inline data */
2172 /* 3rd element of header is length of compressed inline data */
2155 comp_len = getbe32(data + pos + 8);
2173 comp_len = getbe32(data + pos + 8);
2156 incr = v1_hdrsize + comp_len;
2174 incr = v1_hdrsize + comp_len;
2157 if (offsets)
2175 if (offsets)
2158 offsets[len] = data + pos;
2176 offsets[len] = data + pos;
2159 len++;
2177 len++;
2160 pos += incr;
2178 pos += incr;
2161 }
2179 }
2162
2180
2163 if (pos != end) {
2181 if (pos != end) {
2164 if (!PyErr_Occurred())
2182 if (!PyErr_Occurred())
2165 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2183 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2166 return -1;
2184 return -1;
2167 }
2185 }
2168
2186
2169 return len;
2187 return len;
2170 }
2188 }
2171
2189
2172 static int index_init(indexObject *self, PyObject *args)
2190 static int index_init(indexObject *self, PyObject *args)
2173 {
2191 {
2174 PyObject *data_obj, *inlined_obj;
2192 PyObject *data_obj, *inlined_obj;
2175 Py_ssize_t size;
2193 Py_ssize_t size;
2176
2194
2177 /* Initialize before argument-checking to avoid index_dealloc() crash.
2195 /* Initialize before argument-checking to avoid index_dealloc() crash.
2178 */
2196 */
2179 self->raw_length = 0;
2197 self->raw_length = 0;
2180 self->added = NULL;
2198 self->added = NULL;
2181 self->cache = NULL;
2199 self->cache = NULL;
2182 self->data = NULL;
2200 self->data = NULL;
2183 memset(&self->buf, 0, sizeof(self->buf));
2201 memset(&self->buf, 0, sizeof(self->buf));
2184 self->headrevs = NULL;
2202 self->headrevs = NULL;
2185 self->filteredrevs = Py_None;
2203 self->filteredrevs = Py_None;
2186 Py_INCREF(Py_None);
2204 Py_INCREF(Py_None);
2187 self->ntinitialized = 0;
2205 self->ntinitialized = 0;
2188 self->offsets = NULL;
2206 self->offsets = NULL;
2189
2207
2190 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2208 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2191 return -1;
2209 return -1;
2192 if (!PyObject_CheckBuffer(data_obj)) {
2210 if (!PyObject_CheckBuffer(data_obj)) {
2193 PyErr_SetString(PyExc_TypeError,
2211 PyErr_SetString(PyExc_TypeError,
2194 "data does not support buffer interface");
2212 "data does not support buffer interface");
2195 return -1;
2213 return -1;
2196 }
2214 }
2197
2215
2198 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2216 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2199 return -1;
2217 return -1;
2200 size = self->buf.len;
2218 size = self->buf.len;
2201
2219
2202 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
2220 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
2203 self->data = data_obj;
2221 self->data = data_obj;
2204
2222
2205 self->ntlookups = self->ntmisses = 0;
2223 self->ntlookups = self->ntmisses = 0;
2206 self->ntrev = -1;
2224 self->ntrev = -1;
2207 Py_INCREF(self->data);
2225 Py_INCREF(self->data);
2208
2226
2209 if (self->inlined) {
2227 if (self->inlined) {
2210 Py_ssize_t len = inline_scan(self, NULL);
2228 Py_ssize_t len = inline_scan(self, NULL);
2211 if (len == -1)
2229 if (len == -1)
2212 goto bail;
2230 goto bail;
2213 self->raw_length = len;
2231 self->raw_length = len;
2214 self->length = len;
2232 self->length = len;
2215 } else {
2233 } else {
2216 if (size % v1_hdrsize) {
2234 if (size % v1_hdrsize) {
2217 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2235 PyErr_SetString(PyExc_ValueError, "corrupt index file");
2218 goto bail;
2236 goto bail;
2219 }
2237 }
2220 self->raw_length = size / v1_hdrsize;
2238 self->raw_length = size / v1_hdrsize;
2221 self->length = self->raw_length;
2239 self->length = self->raw_length;
2222 }
2240 }
2223
2241
2224 return 0;
2242 return 0;
2225 bail:
2243 bail:
2226 return -1;
2244 return -1;
2227 }
2245 }
2228
2246
2229 static PyObject *index_nodemap(indexObject *self)
2247 static PyObject *index_nodemap(indexObject *self)
2230 {
2248 {
2231 Py_INCREF(self);
2249 Py_INCREF(self);
2232 return (PyObject *)self;
2250 return (PyObject *)self;
2233 }
2251 }
2234
2252
2235 static void _index_clearcaches(indexObject *self)
2253 static void _index_clearcaches(indexObject *self)
2236 {
2254 {
2237 if (self->cache) {
2255 if (self->cache) {
2238 Py_ssize_t i;
2256 Py_ssize_t i;
2239
2257
2240 for (i = 0; i < self->raw_length; i++)
2258 for (i = 0; i < self->raw_length; i++)
2241 Py_CLEAR(self->cache[i]);
2259 Py_CLEAR(self->cache[i]);
2242 free(self->cache);
2260 free(self->cache);
2243 self->cache = NULL;
2261 self->cache = NULL;
2244 }
2262 }
2245 if (self->offsets) {
2263 if (self->offsets) {
2246 PyMem_Free((void *)self->offsets);
2264 PyMem_Free((void *)self->offsets);
2247 self->offsets = NULL;
2265 self->offsets = NULL;
2248 }
2266 }
2249 if (self->ntinitialized) {
2267 if (self->ntinitialized) {
2250 nt_dealloc(&self->nt);
2268 nt_dealloc(&self->nt);
2251 }
2269 }
2252 self->ntinitialized = 0;
2270 self->ntinitialized = 0;
2253 Py_CLEAR(self->headrevs);
2271 Py_CLEAR(self->headrevs);
2254 }
2272 }
2255
2273
2256 static PyObject *index_clearcaches(indexObject *self)
2274 static PyObject *index_clearcaches(indexObject *self)
2257 {
2275 {
2258 _index_clearcaches(self);
2276 _index_clearcaches(self);
2259 self->ntrev = -1;
2277 self->ntrev = -1;
2260 self->ntlookups = self->ntmisses = 0;
2278 self->ntlookups = self->ntmisses = 0;
2261 Py_RETURN_NONE;
2279 Py_RETURN_NONE;
2262 }
2280 }
2263
2281
2264 static void index_dealloc(indexObject *self)
2282 static void index_dealloc(indexObject *self)
2265 {
2283 {
2266 _index_clearcaches(self);
2284 _index_clearcaches(self);
2267 Py_XDECREF(self->filteredrevs);
2285 Py_XDECREF(self->filteredrevs);
2268 if (self->buf.buf) {
2286 if (self->buf.buf) {
2269 PyBuffer_Release(&self->buf);
2287 PyBuffer_Release(&self->buf);
2270 memset(&self->buf, 0, sizeof(self->buf));
2288 memset(&self->buf, 0, sizeof(self->buf));
2271 }
2289 }
2272 Py_XDECREF(self->data);
2290 Py_XDECREF(self->data);
2273 Py_XDECREF(self->added);
2291 Py_XDECREF(self->added);
2274 PyObject_Del(self);
2292 PyObject_Del(self);
2275 }
2293 }
2276
2294
2277 static PySequenceMethods index_sequence_methods = {
2295 static PySequenceMethods index_sequence_methods = {
2278 (lenfunc)index_length, /* sq_length */
2296 (lenfunc)index_length, /* sq_length */
2279 0, /* sq_concat */
2297 0, /* sq_concat */
2280 0, /* sq_repeat */
2298 0, /* sq_repeat */
2281 (ssizeargfunc)index_get, /* sq_item */
2299 (ssizeargfunc)index_get, /* sq_item */
2282 0, /* sq_slice */
2300 0, /* sq_slice */
2283 0, /* sq_ass_item */
2301 0, /* sq_ass_item */
2284 0, /* sq_ass_slice */
2302 0, /* sq_ass_slice */
2285 (objobjproc)index_contains, /* sq_contains */
2303 (objobjproc)index_contains, /* sq_contains */
2286 };
2304 };
2287
2305
2288 static PyMappingMethods index_mapping_methods = {
2306 static PyMappingMethods index_mapping_methods = {
2289 (lenfunc)index_length, /* mp_length */
2307 (lenfunc)index_length, /* mp_length */
2290 (binaryfunc)index_getitem, /* mp_subscript */
2308 (binaryfunc)index_getitem, /* mp_subscript */
2291 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2309 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
2292 };
2310 };
2293
2311
2294 static PyMethodDef index_methods[] = {
2312 static PyMethodDef index_methods[] = {
2295 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2313 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
2296 "return the gca set of the given revs"},
2314 "return the gca set of the given revs"},
2297 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2315 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
2298 METH_VARARGS,
2316 METH_VARARGS,
2299 "return the heads of the common ancestors of the given revs"},
2317 "return the heads of the common ancestors of the given revs"},
2300 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2318 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2301 "clear the index caches"},
2319 "clear the index caches"},
2302 {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"},
2320 {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"},
2303 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS,
2321 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS,
2304 "compute phases"},
2322 "compute phases"},
2305 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2323 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
2306 "reachableroots"},
2324 "reachableroots"},
2307 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2325 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2308 "get head revisions"}, /* Can do filtering since 3.2 */
2326 "get head revisions"}, /* Can do filtering since 3.2 */
2309 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2327 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2310 "get filtered head revisions"}, /* Can always do filtering */
2328 "get filtered head revisions"}, /* Can always do filtering */
2311 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2329 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
2312 "determine revisions with deltas to reconstruct fulltext"},
2330 "determine revisions with deltas to reconstruct fulltext"},
2313 {"append", (PyCFunction)index_append, METH_O, "append an index entry"},
2331 {"append", (PyCFunction)index_append, METH_O, "append an index entry"},
2314 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2332 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
2315 "match a potentially ambiguous node ID"},
2333 "match a potentially ambiguous node ID"},
2316 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2334 {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
2317 "find length of shortest hex nodeid of a binary ID"},
2335 "find length of shortest hex nodeid of a binary ID"},
2318 {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
2336 {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
2319 {NULL} /* Sentinel */
2337 {NULL} /* Sentinel */
2320 };
2338 };
2321
2339
2322 static PyGetSetDef index_getset[] = {
2340 static PyGetSetDef index_getset[] = {
2323 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2341 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
2324 {NULL} /* Sentinel */
2342 {NULL} /* Sentinel */
2325 };
2343 };
2326
2344
2327 static PyTypeObject indexType = {
2345 static PyTypeObject indexType = {
2328 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2346 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2329 "parsers.index", /* tp_name */
2347 "parsers.index", /* tp_name */
2330 sizeof(indexObject), /* tp_basicsize */
2348 sizeof(indexObject), /* tp_basicsize */
2331 0, /* tp_itemsize */
2349 0, /* tp_itemsize */
2332 (destructor)index_dealloc, /* tp_dealloc */
2350 (destructor)index_dealloc, /* tp_dealloc */
2333 0, /* tp_print */
2351 0, /* tp_print */
2334 0, /* tp_getattr */
2352 0, /* tp_getattr */
2335 0, /* tp_setattr */
2353 0, /* tp_setattr */
2336 0, /* tp_compare */
2354 0, /* tp_compare */
2337 0, /* tp_repr */
2355 0, /* tp_repr */
2338 0, /* tp_as_number */
2356 0, /* tp_as_number */
2339 &index_sequence_methods, /* tp_as_sequence */
2357 &index_sequence_methods, /* tp_as_sequence */
2340 &index_mapping_methods, /* tp_as_mapping */
2358 &index_mapping_methods, /* tp_as_mapping */
2341 0, /* tp_hash */
2359 0, /* tp_hash */
2342 0, /* tp_call */
2360 0, /* tp_call */
2343 0, /* tp_str */
2361 0, /* tp_str */
2344 0, /* tp_getattro */
2362 0, /* tp_getattro */
2345 0, /* tp_setattro */
2363 0, /* tp_setattro */
2346 0, /* tp_as_buffer */
2364 0, /* tp_as_buffer */
2347 Py_TPFLAGS_DEFAULT, /* tp_flags */
2365 Py_TPFLAGS_DEFAULT, /* tp_flags */
2348 "revlog index", /* tp_doc */
2366 "revlog index", /* tp_doc */
2349 0, /* tp_traverse */
2367 0, /* tp_traverse */
2350 0, /* tp_clear */
2368 0, /* tp_clear */
2351 0, /* tp_richcompare */
2369 0, /* tp_richcompare */
2352 0, /* tp_weaklistoffset */
2370 0, /* tp_weaklistoffset */
2353 0, /* tp_iter */
2371 0, /* tp_iter */
2354 0, /* tp_iternext */
2372 0, /* tp_iternext */
2355 index_methods, /* tp_methods */
2373 index_methods, /* tp_methods */
2356 0, /* tp_members */
2374 0, /* tp_members */
2357 index_getset, /* tp_getset */
2375 index_getset, /* tp_getset */
2358 0, /* tp_base */
2376 0, /* tp_base */
2359 0, /* tp_dict */
2377 0, /* tp_dict */
2360 0, /* tp_descr_get */
2378 0, /* tp_descr_get */
2361 0, /* tp_descr_set */
2379 0, /* tp_descr_set */
2362 0, /* tp_dictoffset */
2380 0, /* tp_dictoffset */
2363 (initproc)index_init, /* tp_init */
2381 (initproc)index_init, /* tp_init */
2364 0, /* tp_alloc */
2382 0, /* tp_alloc */
2365 };
2383 };
2366
2384
2367 /*
2385 /*
2368 * returns a tuple of the form (index, index, cache) with elements as
2386 * returns a tuple of the form (index, index, cache) with elements as
2369 * follows:
2387 * follows:
2370 *
2388 *
2371 * index: an index object that lazily parses RevlogNG records
2389 * index: an index object that lazily parses RevlogNG records
2372 * cache: if data is inlined, a tuple (0, index_file_content), else None
2390 * cache: if data is inlined, a tuple (0, index_file_content), else None
2373 * index_file_content could be a string, or a buffer
2391 * index_file_content could be a string, or a buffer
2374 *
2392 *
2375 * added complications are for backwards compatibility
2393 * added complications are for backwards compatibility
2376 */
2394 */
2377 PyObject *parse_index2(PyObject *self, PyObject *args)
2395 PyObject *parse_index2(PyObject *self, PyObject *args)
2378 {
2396 {
2379 PyObject *tuple = NULL, *cache = NULL;
2397 PyObject *tuple = NULL, *cache = NULL;
2380 indexObject *idx;
2398 indexObject *idx;
2381 int ret;
2399 int ret;
2382
2400
2383 idx = PyObject_New(indexObject, &indexType);
2401 idx = PyObject_New(indexObject, &indexType);
2384 if (idx == NULL)
2402 if (idx == NULL)
2385 goto bail;
2403 goto bail;
2386
2404
2387 ret = index_init(idx, args);
2405 ret = index_init(idx, args);
2388 if (ret == -1)
2406 if (ret == -1)
2389 goto bail;
2407 goto bail;
2390
2408
2391 if (idx->inlined) {
2409 if (idx->inlined) {
2392 cache = Py_BuildValue("iO", 0, idx->data);
2410 cache = Py_BuildValue("iO", 0, idx->data);
2393 if (cache == NULL)
2411 if (cache == NULL)
2394 goto bail;
2412 goto bail;
2395 } else {
2413 } else {
2396 cache = Py_None;
2414 cache = Py_None;
2397 Py_INCREF(cache);
2415 Py_INCREF(cache);
2398 }
2416 }
2399
2417
2400 tuple = Py_BuildValue("NN", idx, cache);
2418 tuple = Py_BuildValue("NN", idx, cache);
2401 if (!tuple)
2419 if (!tuple)
2402 goto bail;
2420 goto bail;
2403 return tuple;
2421 return tuple;
2404
2422
2405 bail:
2423 bail:
2406 Py_XDECREF(idx);
2424 Py_XDECREF(idx);
2407 Py_XDECREF(cache);
2425 Py_XDECREF(cache);
2408 Py_XDECREF(tuple);
2426 Py_XDECREF(tuple);
2409 return NULL;
2427 return NULL;
2410 }
2428 }
2411
2429
2412 #ifdef WITH_RUST
2430 #ifdef WITH_RUST
2413
2431
2414 /* rustlazyancestors: iteration over ancestors implemented in Rust
2432 /* rustlazyancestors: iteration over ancestors implemented in Rust
2415 *
2433 *
2416 * This class holds a reference to an index and to the Rust iterator.
2434 * This class holds a reference to an index and to the Rust iterator.
2417 */
2435 */
2418 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
2436 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
2419
2437
2420 struct rustlazyancestorsObjectStruct {
2438 struct rustlazyancestorsObjectStruct {
2421 PyObject_HEAD
2439 PyObject_HEAD
2422 /* Type-specific fields go here. */
2440 /* Type-specific fields go here. */
2423 indexObject *index; /* Ref kept to avoid GC'ing the index */
2441 indexObject *index; /* Ref kept to avoid GC'ing the index */
2424 void *iter; /* Rust iterator */
2442 void *iter; /* Rust iterator */
2425 };
2443 };
2426
2444
2427 /* FFI exposed from Rust code */
2445 /* FFI exposed from Rust code */
2428 rustlazyancestorsObject *
2446 rustlazyancestorsObject *
2429 rustlazyancestors_init(indexObject *index,
2447 rustlazyancestors_init(indexObject *index,
2430 /* to pass index_get_parents() */
2448 /* to pass index_get_parents() */
2431 int (*)(indexObject *, Py_ssize_t, int *, int),
2449 int (*)(indexObject *, Py_ssize_t, int *, int),
2432 /* intrevs vector */
2450 /* intrevs vector */
2433 Py_ssize_t initrevslen, long *initrevs, long stoprev,
2451 Py_ssize_t initrevslen, long *initrevs, long stoprev,
2434 int inclusive);
2452 int inclusive);
2435 void rustlazyancestors_drop(rustlazyancestorsObject *self);
2453 void rustlazyancestors_drop(rustlazyancestorsObject *self);
2436 int rustlazyancestors_next(rustlazyancestorsObject *self);
2454 int rustlazyancestors_next(rustlazyancestorsObject *self);
2437 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
2455 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
2438
2456
2439 /* CPython instance methods */
2457 /* CPython instance methods */
2440 static int rustla_init(rustlazyancestorsObject *self, PyObject *args)
2458 static int rustla_init(rustlazyancestorsObject *self, PyObject *args)
2441 {
2459 {
2442 PyObject *initrevsarg = NULL;
2460 PyObject *initrevsarg = NULL;
2443 PyObject *inclusivearg = NULL;
2461 PyObject *inclusivearg = NULL;
2444 long stoprev = 0;
2462 long stoprev = 0;
2445 long *initrevs = NULL;
2463 long *initrevs = NULL;
2446 int inclusive = 0;
2464 int inclusive = 0;
2447 Py_ssize_t i;
2465 Py_ssize_t i;
2448
2466
2449 indexObject *index;
2467 indexObject *index;
2450 if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type,
2468 if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type,
2451 &initrevsarg, &stoprev, &PyBool_Type,
2469 &initrevsarg, &stoprev, &PyBool_Type,
2452 &inclusivearg))
2470 &inclusivearg))
2453 return -1;
2471 return -1;
2454
2472
2455 Py_INCREF(index);
2473 Py_INCREF(index);
2456 self->index = index;
2474 self->index = index;
2457
2475
2458 if (inclusivearg == Py_True)
2476 if (inclusivearg == Py_True)
2459 inclusive = 1;
2477 inclusive = 1;
2460
2478
2461 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
2479 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
2462
2480
2463 initrevs = (long *)calloc(linit, sizeof(long));
2481 initrevs = (long *)calloc(linit, sizeof(long));
2464
2482
2465 if (initrevs == NULL) {
2483 if (initrevs == NULL) {
2466 PyErr_NoMemory();
2484 PyErr_NoMemory();
2467 goto bail;
2485 goto bail;
2468 }
2486 }
2469
2487
2470 for (i = 0; i < linit; i++) {
2488 for (i = 0; i < linit; i++) {
2471 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
2489 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
2472 }
2490 }
2473 if (PyErr_Occurred())
2491 if (PyErr_Occurred())
2474 goto bail;
2492 goto bail;
2475
2493
2476 self->iter = rustlazyancestors_init(index, index_get_parents, linit,
2494 self->iter = rustlazyancestors_init(index, index_get_parents, linit,
2477 initrevs, stoprev, inclusive);
2495 initrevs, stoprev, inclusive);
2478 if (self->iter == NULL) {
2496 if (self->iter == NULL) {
2479 /* if this is because of GraphError::ParentOutOfRange
2497 /* if this is because of GraphError::ParentOutOfRange
2480 * index_get_parents() has already set the proper ValueError */
2498 * index_get_parents() has already set the proper ValueError */
2481 goto bail;
2499 goto bail;
2482 }
2500 }
2483
2501
2484 free(initrevs);
2502 free(initrevs);
2485 return 0;
2503 return 0;
2486
2504
2487 bail:
2505 bail:
2488 free(initrevs);
2506 free(initrevs);
2489 return -1;
2507 return -1;
2490 };
2508 };
2491
2509
2492 static void rustla_dealloc(rustlazyancestorsObject *self)
2510 static void rustla_dealloc(rustlazyancestorsObject *self)
2493 {
2511 {
2494 Py_XDECREF(self->index);
2512 Py_XDECREF(self->index);
2495 if (self->iter != NULL) { /* can happen if rustla_init failed */
2513 if (self->iter != NULL) { /* can happen if rustla_init failed */
2496 rustlazyancestors_drop(self->iter);
2514 rustlazyancestors_drop(self->iter);
2497 }
2515 }
2498 PyObject_Del(self);
2516 PyObject_Del(self);
2499 }
2517 }
2500
2518
2501 static PyObject *rustla_next(rustlazyancestorsObject *self)
2519 static PyObject *rustla_next(rustlazyancestorsObject *self)
2502 {
2520 {
2503 int res = rustlazyancestors_next(self->iter);
2521 int res = rustlazyancestors_next(self->iter);
2504 if (res == -1) {
2522 if (res == -1) {
2505 /* Setting an explicit exception seems unnecessary
2523 /* Setting an explicit exception seems unnecessary
2506 * as examples from Python source code (Objects/rangeobjets.c
2524 * as examples from Python source code (Objects/rangeobjets.c
2507 * and Modules/_io/stringio.c) seem to demonstrate.
2525 * and Modules/_io/stringio.c) seem to demonstrate.
2508 */
2526 */
2509 return NULL;
2527 return NULL;
2510 }
2528 }
2511 return PyInt_FromLong(res);
2529 return PyInt_FromLong(res);
2512 }
2530 }
2513
2531
2514 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev)
2532 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev)
2515 {
2533 {
2516 long lrev;
2534 long lrev;
2517 if (!pylong_to_long(rev, &lrev)) {
2535 if (!pylong_to_long(rev, &lrev)) {
2518 PyErr_Clear();
2536 PyErr_Clear();
2519 return 0;
2537 return 0;
2520 }
2538 }
2521 return rustlazyancestors_contains(self->iter, lrev);
2539 return rustlazyancestors_contains(self->iter, lrev);
2522 }
2540 }
2523
2541
2524 static PySequenceMethods rustla_sequence_methods = {
2542 static PySequenceMethods rustla_sequence_methods = {
2525 0, /* sq_length */
2543 0, /* sq_length */
2526 0, /* sq_concat */
2544 0, /* sq_concat */
2527 0, /* sq_repeat */
2545 0, /* sq_repeat */
2528 0, /* sq_item */
2546 0, /* sq_item */
2529 0, /* sq_slice */
2547 0, /* sq_slice */
2530 0, /* sq_ass_item */
2548 0, /* sq_ass_item */
2531 0, /* sq_ass_slice */
2549 0, /* sq_ass_slice */
2532 (objobjproc)rustla_contains, /* sq_contains */
2550 (objobjproc)rustla_contains, /* sq_contains */
2533 };
2551 };
2534
2552
2535 static PyTypeObject rustlazyancestorsType = {
2553 static PyTypeObject rustlazyancestorsType = {
2536 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2554 PyVarObject_HEAD_INIT(NULL, 0) /* header */
2537 "parsers.rustlazyancestors", /* tp_name */
2555 "parsers.rustlazyancestors", /* tp_name */
2538 sizeof(rustlazyancestorsObject), /* tp_basicsize */
2556 sizeof(rustlazyancestorsObject), /* tp_basicsize */
2539 0, /* tp_itemsize */
2557 0, /* tp_itemsize */
2540 (destructor)rustla_dealloc, /* tp_dealloc */
2558 (destructor)rustla_dealloc, /* tp_dealloc */
2541 0, /* tp_print */
2559 0, /* tp_print */
2542 0, /* tp_getattr */
2560 0, /* tp_getattr */
2543 0, /* tp_setattr */
2561 0, /* tp_setattr */
2544 0, /* tp_compare */
2562 0, /* tp_compare */
2545 0, /* tp_repr */
2563 0, /* tp_repr */
2546 0, /* tp_as_number */
2564 0, /* tp_as_number */
2547 &rustla_sequence_methods, /* tp_as_sequence */
2565 &rustla_sequence_methods, /* tp_as_sequence */
2548 0, /* tp_as_mapping */
2566 0, /* tp_as_mapping */
2549 0, /* tp_hash */
2567 0, /* tp_hash */
2550 0, /* tp_call */
2568 0, /* tp_call */
2551 0, /* tp_str */
2569 0, /* tp_str */
2552 0, /* tp_getattro */
2570 0, /* tp_getattro */
2553 0, /* tp_setattro */
2571 0, /* tp_setattro */
2554 0, /* tp_as_buffer */
2572 0, /* tp_as_buffer */
2555 Py_TPFLAGS_DEFAULT, /* tp_flags */
2573 Py_TPFLAGS_DEFAULT, /* tp_flags */
2556 "Iterator over ancestors, implemented in Rust", /* tp_doc */
2574 "Iterator over ancestors, implemented in Rust", /* tp_doc */
2557 0, /* tp_traverse */
2575 0, /* tp_traverse */
2558 0, /* tp_clear */
2576 0, /* tp_clear */
2559 0, /* tp_richcompare */
2577 0, /* tp_richcompare */
2560 0, /* tp_weaklistoffset */
2578 0, /* tp_weaklistoffset */
2561 0, /* tp_iter */
2579 0, /* tp_iter */
2562 (iternextfunc)rustla_next, /* tp_iternext */
2580 (iternextfunc)rustla_next, /* tp_iternext */
2563 0, /* tp_methods */
2581 0, /* tp_methods */
2564 0, /* tp_members */
2582 0, /* tp_members */
2565 0, /* tp_getset */
2583 0, /* tp_getset */
2566 0, /* tp_base */
2584 0, /* tp_base */
2567 0, /* tp_dict */
2585 0, /* tp_dict */
2568 0, /* tp_descr_get */
2586 0, /* tp_descr_get */
2569 0, /* tp_descr_set */
2587 0, /* tp_descr_set */
2570 0, /* tp_dictoffset */
2588 0, /* tp_dictoffset */
2571 (initproc)rustla_init, /* tp_init */
2589 (initproc)rustla_init, /* tp_init */
2572 0, /* tp_alloc */
2590 0, /* tp_alloc */
2573 };
2591 };
2574 #endif /* WITH_RUST */
2592 #endif /* WITH_RUST */
2575
2593
2576 void revlog_module_init(PyObject *mod)
2594 void revlog_module_init(PyObject *mod)
2577 {
2595 {
2578 indexType.tp_new = PyType_GenericNew;
2596 indexType.tp_new = PyType_GenericNew;
2579 if (PyType_Ready(&indexType) < 0)
2597 if (PyType_Ready(&indexType) < 0)
2580 return;
2598 return;
2581 Py_INCREF(&indexType);
2599 Py_INCREF(&indexType);
2582 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2600 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
2583
2601
2584 nodetreeType.tp_new = PyType_GenericNew;
2602 nodetreeType.tp_new = PyType_GenericNew;
2585 if (PyType_Ready(&nodetreeType) < 0)
2603 if (PyType_Ready(&nodetreeType) < 0)
2586 return;
2604 return;
2587 Py_INCREF(&nodetreeType);
2605 Py_INCREF(&nodetreeType);
2588 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2606 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2589
2607
2590 if (!nullentry) {
2608 if (!nullentry) {
2591 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0,
2609 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0,
2592 0, -1, -1, -1, -1, nullid, 20);
2610 0, -1, -1, -1, -1, nullid, 20);
2593 }
2611 }
2594 if (nullentry)
2612 if (nullentry)
2595 PyObject_GC_UnTrack(nullentry);
2613 PyObject_GC_UnTrack(nullentry);
2596
2614
2597 #ifdef WITH_RUST
2615 #ifdef WITH_RUST
2598 rustlazyancestorsType.tp_new = PyType_GenericNew;
2616 rustlazyancestorsType.tp_new = PyType_GenericNew;
2599 if (PyType_Ready(&rustlazyancestorsType) < 0)
2617 if (PyType_Ready(&rustlazyancestorsType) < 0)
2600 return;
2618 return;
2601 Py_INCREF(&rustlazyancestorsType);
2619 Py_INCREF(&rustlazyancestorsType);
2602 PyModule_AddObject(mod, "rustlazyancestors",
2620 PyModule_AddObject(mod, "rustlazyancestors",
2603 (PyObject *)&rustlazyancestorsType);
2621 (PyObject *)&rustlazyancestorsType);
2604 #endif
2622 #endif
2605 }
2623 }
General Comments 0
You need to be logged in to leave comments. Login now