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