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