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