Show More
@@ -638,7 +638,7 b' static char parsers_doc[] = "Efficient c' | |||||
638 | PyObject *encodedir(PyObject *self, PyObject *args); |
|
638 | PyObject *encodedir(PyObject *self, PyObject *args); | |
639 | PyObject *pathencode(PyObject *self, PyObject *args); |
|
639 | PyObject *pathencode(PyObject *self, PyObject *args); | |
640 | PyObject *lowerencode(PyObject *self, PyObject *args); |
|
640 | PyObject *lowerencode(PyObject *self, PyObject *args); | |
641 | PyObject *parse_index2(PyObject *self, PyObject *args); |
|
641 | PyObject *parse_index2(PyObject *self, PyObject *args, PyObject *kwargs); | |
642 |
|
642 | |||
643 | static PyMethodDef methods[] = { |
|
643 | static PyMethodDef methods[] = { | |
644 | {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, |
|
644 | {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, | |
@@ -646,7 +646,8 b' static PyMethodDef methods[] = {' | |||||
646 | "create a set containing non-normal and other parent entries of given " |
|
646 | "create a set containing non-normal and other parent entries of given " | |
647 | "dirstate\n"}, |
|
647 | "dirstate\n"}, | |
648 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, |
|
648 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, | |
649 |
{"parse_index2", parse_index2, METH_VARARGS |
|
649 | {"parse_index2", (PyCFunction)parse_index2, METH_VARARGS | METH_KEYWORDS, | |
|
650 | "parse a revlog index\n"}, | |||
650 | {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"}, |
|
651 | {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"}, | |
651 | {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, |
|
652 | {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, | |
652 | {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"}, |
|
653 | {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"}, |
@@ -98,6 +98,7 b' struct indexObjectStruct {' | |||||
98 | int ntlookups; /* # lookups */ |
|
98 | int ntlookups; /* # lookups */ | |
99 | int ntmisses; /* # lookups that miss the cache */ |
|
99 | int ntmisses; /* # lookups that miss the cache */ | |
100 | int inlined; |
|
100 | int inlined; | |
|
101 | long hdrsize; /* size of index headers. Differs in v1 v.s. v2 format */ | |||
101 | }; |
|
102 | }; | |
102 |
|
103 | |||
103 | static Py_ssize_t index_length(const indexObject *self) |
|
104 | static Py_ssize_t index_length(const indexObject *self) | |
@@ -113,14 +114,21 b' static Py_ssize_t inline_scan(indexObjec' | |||||
113 | static int index_find_node(indexObject *self, const char *node); |
|
114 | static int index_find_node(indexObject *self, const char *node); | |
114 |
|
115 | |||
115 | #if LONG_MAX == 0x7fffffffL |
|
116 | #if LONG_MAX == 0x7fffffffL | |
116 | static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#"); |
|
117 | static const char *const v1_tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#"); | |
|
118 | static const char *const v2_tuple_format = | |||
|
119 | PY23("Kiiiiiis#Ki", "Kiiiiiiy#Ki"); | |||
117 | #else |
|
120 | #else | |
118 | static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#"); |
|
121 | static const char *const v1_tuple_format = PY23("kiiiiiis#", "kiiiiiiy#"); | |
|
122 | static const char *const v2_tuple_format = | |||
|
123 | PY23("kiiiiiis#ki", "kiiiiiiy#ki"); | |||
119 | #endif |
|
124 | #endif | |
120 |
|
125 | |||
121 | /* A RevlogNG v1 index entry is 64 bytes long. */ |
|
126 | /* A RevlogNG v1 index entry is 64 bytes long. */ | |
122 | static const long v1_hdrsize = 64; |
|
127 | static const long v1_hdrsize = 64; | |
123 |
|
128 | |||
|
129 | /* A Revlogv2 index entry is 96 bytes long. */ | |||
|
130 | static const long v2_hdrsize = 96; | |||
|
131 | ||||
124 | static void raise_revlog_error(void) |
|
132 | static void raise_revlog_error(void) | |
125 | { |
|
133 | { | |
126 | PyObject *mod = NULL, *dict = NULL, *errclass = NULL; |
|
134 | PyObject *mod = NULL, *dict = NULL, *errclass = NULL; | |
@@ -157,7 +165,7 b' cleanup:' | |||||
157 | static const char *index_deref(indexObject *self, Py_ssize_t pos) |
|
165 | static const char *index_deref(indexObject *self, Py_ssize_t pos) | |
158 | { |
|
166 | { | |
159 | if (pos >= self->length) |
|
167 | if (pos >= self->length) | |
160 |
return self->added + (pos - self->length) * |
|
168 | return self->added + (pos - self->length) * self->hdrsize; | |
161 |
|
169 | |||
162 | if (self->inlined && pos > 0) { |
|
170 | if (self->inlined && pos > 0) { | |
163 | if (self->offsets == NULL) { |
|
171 | if (self->offsets == NULL) { | |
@@ -174,7 +182,7 b' static const char *index_deref(indexObje' | |||||
174 | return self->offsets[pos]; |
|
182 | return self->offsets[pos]; | |
175 | } |
|
183 | } | |
176 |
|
184 | |||
177 |
return (const char *)(self->buf.buf) + pos * |
|
185 | return (const char *)(self->buf.buf) + pos * self->hdrsize; | |
178 | } |
|
186 | } | |
179 |
|
187 | |||
180 | /* |
|
188 | /* | |
@@ -280,8 +288,9 b' static inline int index_get_length(index' | |||||
280 | */ |
|
288 | */ | |
281 | static PyObject *index_get(indexObject *self, Py_ssize_t pos) |
|
289 | static PyObject *index_get(indexObject *self, Py_ssize_t pos) | |
282 | { |
|
290 | { | |
283 | uint64_t offset_flags; |
|
291 | uint64_t offset_flags, sidedata_offset; | |
284 |
int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2 |
|
292 | int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2, | |
|
293 | sidedata_comp_len; | |||
285 | const char *c_node_id; |
|
294 | const char *c_node_id; | |
286 | const char *data; |
|
295 | const char *data; | |
287 | Py_ssize_t length = index_length(self); |
|
296 | Py_ssize_t length = index_length(self); | |
@@ -320,9 +329,19 b' static PyObject *index_get(indexObject *' | |||||
320 | parent_2 = getbe32(data + 28); |
|
329 | parent_2 = getbe32(data + 28); | |
321 | c_node_id = data + 32; |
|
330 | c_node_id = data + 32; | |
322 |
|
331 | |||
323 | return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, |
|
332 | if (self->hdrsize == v1_hdrsize) { | |
324 | base_rev, link_rev, parent_1, parent_2, c_node_id, |
|
333 | return Py_BuildValue(v1_tuple_format, offset_flags, comp_len, | |
325 | self->nodelen); |
|
334 | uncomp_len, base_rev, link_rev, parent_1, | |
|
335 | parent_2, c_node_id, self->nodelen); | |||
|
336 | } else { | |||
|
337 | sidedata_offset = getbe64(data + 64); | |||
|
338 | sidedata_comp_len = getbe32(data + 72); | |||
|
339 | ||||
|
340 | return Py_BuildValue(v2_tuple_format, offset_flags, comp_len, | |||
|
341 | uncomp_len, base_rev, link_rev, parent_1, | |||
|
342 | parent_2, c_node_id, self->nodelen, | |||
|
343 | sidedata_offset, sidedata_comp_len); | |||
|
344 | } | |||
326 | } |
|
345 | } | |
327 |
|
346 | |||
328 | /* |
|
347 | /* | |
@@ -373,18 +392,30 b' static int node_check(Py_ssize_t nodelen' | |||||
373 |
|
392 | |||
374 | static PyObject *index_append(indexObject *self, PyObject *obj) |
|
393 | static PyObject *index_append(indexObject *self, PyObject *obj) | |
375 | { |
|
394 | { | |
376 | uint64_t offset_flags; |
|
395 | uint64_t offset_flags, sidedata_offset; | |
377 | int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; |
|
396 | int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; | |
378 | Py_ssize_t c_node_id_len; |
|
397 | Py_ssize_t c_node_id_len, sidedata_comp_len; | |
379 | const char *c_node_id; |
|
398 | const char *c_node_id; | |
380 | char *data; |
|
399 | char *data; | |
381 |
|
400 | |||
382 | if (!PyArg_ParseTuple(obj, tuple_format, &offset_flags, &comp_len, |
|
401 | if (self->hdrsize == v1_hdrsize) { | |
383 | &uncomp_len, &base_rev, &link_rev, &parent_1, |
|
402 | if (!PyArg_ParseTuple(obj, v1_tuple_format, &offset_flags, | |
384 | &parent_2, &c_node_id, &c_node_id_len)) { |
|
403 | &comp_len, &uncomp_len, &base_rev, | |
385 | PyErr_SetString(PyExc_TypeError, "8-tuple required"); |
|
404 | &link_rev, &parent_1, &parent_2, | |
386 | return NULL; |
|
405 | &c_node_id, &c_node_id_len)) { | |
|
406 | PyErr_SetString(PyExc_TypeError, "8-tuple required"); | |||
|
407 | return NULL; | |||
|
408 | } | |||
|
409 | } else { | |||
|
410 | if (!PyArg_ParseTuple( | |||
|
411 | obj, v2_tuple_format, &offset_flags, &comp_len, | |||
|
412 | &uncomp_len, &base_rev, &link_rev, &parent_1, &parent_2, | |||
|
413 | &c_node_id, &c_node_id_len, &sidedata_offset, &sidedata_comp_len)) { | |||
|
414 | PyErr_SetString(PyExc_TypeError, "10-tuple required"); | |||
|
415 | return NULL; | |||
|
416 | } | |||
387 | } |
|
417 | } | |
|
418 | ||||
388 | if (c_node_id_len != self->nodelen) { |
|
419 | if (c_node_id_len != self->nodelen) { | |
389 | PyErr_SetString(PyExc_TypeError, "invalid node"); |
|
420 | PyErr_SetString(PyExc_TypeError, "invalid node"); | |
390 | return NULL; |
|
421 | return NULL; | |
@@ -393,15 +424,15 b' static PyObject *index_append(indexObjec' | |||||
393 | if (self->new_length == self->added_length) { |
|
424 | if (self->new_length == self->added_length) { | |
394 | size_t new_added_length = |
|
425 | size_t new_added_length = | |
395 | self->added_length ? self->added_length * 2 : 4096; |
|
426 | self->added_length ? self->added_length * 2 : 4096; | |
396 | void *new_added = |
|
427 | void *new_added = PyMem_Realloc(self->added, new_added_length * | |
397 | PyMem_Realloc(self->added, new_added_length * v1_hdrsize); |
|
428 | self->hdrsize); | |
398 | if (!new_added) |
|
429 | if (!new_added) | |
399 | return PyErr_NoMemory(); |
|
430 | return PyErr_NoMemory(); | |
400 | self->added = new_added; |
|
431 | self->added = new_added; | |
401 | self->added_length = new_added_length; |
|
432 | self->added_length = new_added_length; | |
402 | } |
|
433 | } | |
403 | rev = self->length + self->new_length; |
|
434 | rev = self->length + self->new_length; | |
404 |
data = self->added + |
|
435 | data = self->added + self->hdrsize * self->new_length++; | |
405 | putbe32(offset_flags >> 32, data); |
|
436 | putbe32(offset_flags >> 32, data); | |
406 | putbe32(offset_flags & 0xffffffffU, data + 4); |
|
437 | putbe32(offset_flags & 0xffffffffU, data + 4); | |
407 | putbe32(comp_len, data + 8); |
|
438 | putbe32(comp_len, data + 8); | |
@@ -411,7 +442,14 b' static PyObject *index_append(indexObjec' | |||||
411 | putbe32(parent_1, data + 24); |
|
442 | putbe32(parent_1, data + 24); | |
412 | putbe32(parent_2, data + 28); |
|
443 | putbe32(parent_2, data + 28); | |
413 | memcpy(data + 32, c_node_id, c_node_id_len); |
|
444 | memcpy(data + 32, c_node_id, c_node_id_len); | |
|
445 | /* Padding since SHA-1 is only 20 bytes for now */ | |||
414 | memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); |
|
446 | memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); | |
|
447 | if (self->hdrsize != v1_hdrsize) { | |||
|
448 | putbe64(sidedata_offset, data + 64); | |||
|
449 | putbe32(sidedata_comp_len, data + 72); | |||
|
450 | /* Padding for 96 bytes alignment */ | |||
|
451 | memset(data + 76, 0, self->hdrsize - 76); | |||
|
452 | } | |||
415 |
|
453 | |||
416 | if (self->ntinitialized) |
|
454 | if (self->ntinitialized) | |
417 | nt_insert(&self->nt, c_node_id, rev); |
|
455 | nt_insert(&self->nt, c_node_id, rev); | |
@@ -2563,14 +2601,17 b' static Py_ssize_t inline_scan(indexObjec' | |||||
2563 | const char *data = (const char *)self->buf.buf; |
|
2601 | const char *data = (const char *)self->buf.buf; | |
2564 | Py_ssize_t pos = 0; |
|
2602 | Py_ssize_t pos = 0; | |
2565 | Py_ssize_t end = self->buf.len; |
|
2603 | Py_ssize_t end = self->buf.len; | |
2566 |
long incr = |
|
2604 | long incr = self->hdrsize; | |
2567 | Py_ssize_t len = 0; |
|
2605 | Py_ssize_t len = 0; | |
2568 |
|
2606 | |||
2569 |
while (pos + |
|
2607 | while (pos + self->hdrsize <= end && pos >= 0) { | |
2570 | uint32_t comp_len; |
|
2608 | uint32_t comp_len, sidedata_comp_len = 0; | |
2571 | /* 3rd element of header is length of compressed inline data */ |
|
2609 | /* 3rd element of header is length of compressed inline data */ | |
2572 | comp_len = getbe32(data + pos + 8); |
|
2610 | comp_len = getbe32(data + pos + 8); | |
2573 | incr = v1_hdrsize + comp_len; |
|
2611 | if (self->hdrsize == v2_hdrsize) { | |
|
2612 | sidedata_comp_len = getbe32(data + pos + 72); | |||
|
2613 | } | |||
|
2614 | incr = self->hdrsize + comp_len + sidedata_comp_len; | |||
2574 | if (offsets) |
|
2615 | if (offsets) | |
2575 | offsets[len] = data + pos; |
|
2616 | offsets[len] = data + pos; | |
2576 | len++; |
|
2617 | len++; | |
@@ -2586,11 +2627,13 b' static Py_ssize_t inline_scan(indexObjec' | |||||
2586 | return len; |
|
2627 | return len; | |
2587 | } |
|
2628 | } | |
2588 |
|
2629 | |||
2589 | static int index_init(indexObject *self, PyObject *args) |
|
2630 | static int index_init(indexObject *self, PyObject *args, PyObject *kwargs) | |
2590 | { |
|
2631 | { | |
2591 | PyObject *data_obj, *inlined_obj; |
|
2632 | PyObject *data_obj, *inlined_obj, *revlogv2; | |
2592 | Py_ssize_t size; |
|
2633 | Py_ssize_t size; | |
2593 |
|
2634 | |||
|
2635 | static char *kwlist[] = {"data", "inlined", "revlogv2", NULL}; | |||
|
2636 | ||||
2594 | /* Initialize before argument-checking to avoid index_dealloc() crash. |
|
2637 | /* Initialize before argument-checking to avoid index_dealloc() crash. | |
2595 | */ |
|
2638 | */ | |
2596 | self->added = NULL; |
|
2639 | self->added = NULL; | |
@@ -2606,7 +2649,9 b' static int index_init(indexObject *self,' | |||||
2606 | self->nodelen = 20; |
|
2649 | self->nodelen = 20; | |
2607 | self->nullentry = NULL; |
|
2650 | self->nullentry = NULL; | |
2608 |
|
2651 | |||
2609 | if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) |
|
2652 | revlogv2 = NULL; | |
|
2653 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", kwlist, | |||
|
2654 | &data_obj, &inlined_obj, &revlogv2)) | |||
2610 | return -1; |
|
2655 | return -1; | |
2611 | if (!PyObject_CheckBuffer(data_obj)) { |
|
2656 | if (!PyObject_CheckBuffer(data_obj)) { | |
2612 | PyErr_SetString(PyExc_TypeError, |
|
2657 | PyErr_SetString(PyExc_TypeError, | |
@@ -2618,8 +2663,22 b' static int index_init(indexObject *self,' | |||||
2618 | return -1; |
|
2663 | return -1; | |
2619 | } |
|
2664 | } | |
2620 |
|
2665 | |||
2621 | self->nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, |
|
2666 | if (revlogv2 && PyObject_IsTrue(revlogv2)) { | |
2622 | -1, -1, -1, -1, nullid, self->nodelen); |
|
2667 | self->hdrsize = v2_hdrsize; | |
|
2668 | } else { | |||
|
2669 | self->hdrsize = v1_hdrsize; | |||
|
2670 | } | |||
|
2671 | ||||
|
2672 | if (self->hdrsize == v1_hdrsize) { | |||
|
2673 | self->nullentry = | |||
|
2674 | Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, -1, | |||
|
2675 | -1, -1, -1, nullid, self->nodelen); | |||
|
2676 | } else { | |||
|
2677 | self->nullentry = Py_BuildValue( | |||
|
2678 | PY23("iiiiiiis#ii", "iiiiiiiy#ii"), 0, 0, 0, -1, -1, -1, | |||
|
2679 | -1, nullid, self->nodelen, 0, 0); | |||
|
2680 | } | |||
|
2681 | ||||
2623 | if (!self->nullentry) |
|
2682 | if (!self->nullentry) | |
2624 | return -1; |
|
2683 | return -1; | |
2625 | PyObject_GC_UnTrack(self->nullentry); |
|
2684 | PyObject_GC_UnTrack(self->nullentry); | |
@@ -2641,11 +2700,11 b' static int index_init(indexObject *self,' | |||||
2641 | goto bail; |
|
2700 | goto bail; | |
2642 | self->length = len; |
|
2701 | self->length = len; | |
2643 | } else { |
|
2702 | } else { | |
2644 |
if (size % |
|
2703 | if (size % self->hdrsize) { | |
2645 | PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
|
2704 | PyErr_SetString(PyExc_ValueError, "corrupt index file"); | |
2646 | goto bail; |
|
2705 | goto bail; | |
2647 | } |
|
2706 | } | |
2648 |
self->length = size / |
|
2707 | self->length = size / self->hdrsize; | |
2649 | } |
|
2708 | } | |
2650 |
|
2709 | |||
2651 | return 0; |
|
2710 | return 0; | |
@@ -2797,16 +2856,16 b' PyTypeObject HgRevlogIndex_Type = {' | |||||
2797 | }; |
|
2856 | }; | |
2798 |
|
2857 | |||
2799 | /* |
|
2858 | /* | |
2800 |
* returns a tuple of the form (index, |
|
2859 | * returns a tuple of the form (index, cache) with elements as | |
2801 | * follows: |
|
2860 | * follows: | |
2802 | * |
|
2861 | * | |
2803 |
* index: an index object that lazily parses Revlog |
|
2862 | * index: an index object that lazily parses Revlog (v1 or v2) records | |
2804 | * cache: if data is inlined, a tuple (0, index_file_content), else None |
|
2863 | * cache: if data is inlined, a tuple (0, index_file_content), else None | |
2805 | * index_file_content could be a string, or a buffer |
|
2864 | * index_file_content could be a string, or a buffer | |
2806 | * |
|
2865 | * | |
2807 | * added complications are for backwards compatibility |
|
2866 | * added complications are for backwards compatibility | |
2808 | */ |
|
2867 | */ | |
2809 | PyObject *parse_index2(PyObject *self, PyObject *args) |
|
2868 | PyObject *parse_index2(PyObject *self, PyObject *args, PyObject *kwargs) | |
2810 | { |
|
2869 | { | |
2811 | PyObject *cache = NULL; |
|
2870 | PyObject *cache = NULL; | |
2812 | indexObject *idx; |
|
2871 | indexObject *idx; | |
@@ -2816,7 +2875,7 b' PyObject *parse_index2(PyObject *self, P' | |||||
2816 | if (idx == NULL) |
|
2875 | if (idx == NULL) | |
2817 | goto bail; |
|
2876 | goto bail; | |
2818 |
|
2877 | |||
2819 | ret = index_init(idx, args); |
|
2878 | ret = index_init(idx, args, kwargs); | |
2820 | if (ret == -1) |
|
2879 | if (ret == -1) | |
2821 | goto bail; |
|
2880 | goto bail; | |
2822 |
|
2881 |
General Comments 0
You need to be logged in to leave comments.
Login now