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