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