Show More
@@ -638,7 +638,7 b' static char parsers_doc[] = "Efficient c' | |||
|
638 | 638 | PyObject *encodedir(PyObject *self, PyObject *args); |
|
639 | 639 | PyObject *pathencode(PyObject *self, PyObject *args); |
|
640 | 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 | 643 | static PyMethodDef methods[] = { |
|
644 | 644 | {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, |
@@ -646,7 +646,8 b' static PyMethodDef methods[] = {' | |||
|
646 | 646 | "create a set containing non-normal and other parent entries of given " |
|
647 | 647 | "dirstate\n"}, |
|
648 | 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 | 651 | {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"}, |
|
651 | 652 | {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, |
|
652 | 653 | {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"}, |
@@ -98,6 +98,7 b' struct indexObjectStruct {' | |||
|
98 | 98 | int ntlookups; /* # lookups */ |
|
99 | 99 | int ntmisses; /* # lookups that miss the cache */ |
|
100 | 100 | int inlined; |
|
101 | long hdrsize; /* size of index headers. Differs in v1 v.s. v2 format */ | |
|
101 | 102 | }; |
|
102 | 103 | |
|
103 | 104 | static Py_ssize_t index_length(const indexObject *self) |
@@ -113,14 +114,21 b' static Py_ssize_t inline_scan(indexObjec' | |||
|
113 | 114 | static int index_find_node(indexObject *self, const char *node); |
|
114 | 115 | |
|
115 | 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 | 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 | 124 | #endif |
|
120 | 125 | |
|
121 | 126 | /* A RevlogNG v1 index entry is 64 bytes long. */ |
|
122 | 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 | 132 | static void raise_revlog_error(void) |
|
125 | 133 | { |
|
126 | 134 | PyObject *mod = NULL, *dict = NULL, *errclass = NULL; |
@@ -157,7 +165,7 b' cleanup:' | |||
|
157 | 165 | static const char *index_deref(indexObject *self, Py_ssize_t pos) |
|
158 | 166 | { |
|
159 | 167 | if (pos >= self->length) |
|
160 |
return self->added + (pos - self->length) * |
|
|
168 | return self->added + (pos - self->length) * self->hdrsize; | |
|
161 | 169 | |
|
162 | 170 | if (self->inlined && pos > 0) { |
|
163 | 171 | if (self->offsets == NULL) { |
@@ -174,7 +182,7 b' static const char *index_deref(indexObje' | |||
|
174 | 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 | 289 | static PyObject *index_get(indexObject *self, Py_ssize_t pos) |
|
282 | 290 | { |
|
283 | uint64_t offset_flags; | |
|
284 |
int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2 |
|
|
291 | uint64_t offset_flags, sidedata_offset; | |
|
292 | int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2, | |
|
293 | sidedata_comp_len; | |
|
285 | 294 | const char *c_node_id; |
|
286 | 295 | const char *data; |
|
287 | 296 | Py_ssize_t length = index_length(self); |
@@ -320,9 +329,19 b' static PyObject *index_get(indexObject *' | |||
|
320 | 329 | parent_2 = getbe32(data + 28); |
|
321 | 330 | c_node_id = data + 32; |
|
322 | 331 | |
|
323 | return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, | |
|
324 | base_rev, link_rev, parent_1, parent_2, c_node_id, | |
|
325 | self->nodelen); | |
|
332 | if (self->hdrsize == v1_hdrsize) { | |
|
333 | return Py_BuildValue(v1_tuple_format, offset_flags, comp_len, | |
|
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 | 393 | static PyObject *index_append(indexObject *self, PyObject *obj) |
|
375 | 394 | { |
|
376 | uint64_t offset_flags; | |
|
395 | uint64_t offset_flags, sidedata_offset; | |
|
377 | 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 | 398 | const char *c_node_id; |
|
380 | 399 | char *data; |
|
381 | 400 | |
|
382 | if (!PyArg_ParseTuple(obj, tuple_format, &offset_flags, &comp_len, | |
|
383 | &uncomp_len, &base_rev, &link_rev, &parent_1, | |
|
384 | &parent_2, &c_node_id, &c_node_id_len)) { | |
|
385 | PyErr_SetString(PyExc_TypeError, "8-tuple required"); | |
|
386 | return NULL; | |
|
401 | if (self->hdrsize == v1_hdrsize) { | |
|
402 | if (!PyArg_ParseTuple(obj, v1_tuple_format, &offset_flags, | |
|
403 | &comp_len, &uncomp_len, &base_rev, | |
|
404 | &link_rev, &parent_1, &parent_2, | |
|
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 | 419 | if (c_node_id_len != self->nodelen) { |
|
389 | 420 | PyErr_SetString(PyExc_TypeError, "invalid node"); |
|
390 | 421 | return NULL; |
@@ -393,15 +424,15 b' static PyObject *index_append(indexObjec' | |||
|
393 | 424 | if (self->new_length == self->added_length) { |
|
394 | 425 | size_t new_added_length = |
|
395 | 426 | self->added_length ? self->added_length * 2 : 4096; |
|
396 | void *new_added = | |
|
397 | PyMem_Realloc(self->added, new_added_length * v1_hdrsize); | |
|
427 | void *new_added = PyMem_Realloc(self->added, new_added_length * | |
|
428 | self->hdrsize); | |
|
398 | 429 | if (!new_added) |
|
399 | 430 | return PyErr_NoMemory(); |
|
400 | 431 | self->added = new_added; |
|
401 | 432 | self->added_length = new_added_length; |
|
402 | 433 | } |
|
403 | 434 | rev = self->length + self->new_length; |
|
404 |
data = self->added + |
|
|
435 | data = self->added + self->hdrsize * self->new_length++; | |
|
405 | 436 | putbe32(offset_flags >> 32, data); |
|
406 | 437 | putbe32(offset_flags & 0xffffffffU, data + 4); |
|
407 | 438 | putbe32(comp_len, data + 8); |
@@ -411,7 +442,14 b' static PyObject *index_append(indexObjec' | |||
|
411 | 442 | putbe32(parent_1, data + 24); |
|
412 | 443 | putbe32(parent_2, data + 28); |
|
413 | 444 | memcpy(data + 32, c_node_id, c_node_id_len); |
|
445 | /* Padding since SHA-1 is only 20 bytes for now */ | |
|
414 | 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 | 454 | if (self->ntinitialized) |
|
417 | 455 | nt_insert(&self->nt, c_node_id, rev); |
@@ -2563,14 +2601,17 b' static Py_ssize_t inline_scan(indexObjec' | |||
|
2563 | 2601 | const char *data = (const char *)self->buf.buf; |
|
2564 | 2602 | Py_ssize_t pos = 0; |
|
2565 | 2603 | Py_ssize_t end = self->buf.len; |
|
2566 |
long incr = |
|
|
2604 | long incr = self->hdrsize; | |
|
2567 | 2605 | Py_ssize_t len = 0; |
|
2568 | 2606 | |
|
2569 |
while (pos + |
|
|
2570 | uint32_t comp_len; | |
|
2607 | while (pos + self->hdrsize <= end && pos >= 0) { | |
|
2608 | uint32_t comp_len, sidedata_comp_len = 0; | |
|
2571 | 2609 | /* 3rd element of header is length of compressed inline data */ |
|
2572 | 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 | 2615 | if (offsets) |
|
2575 | 2616 | offsets[len] = data + pos; |
|
2576 | 2617 | len++; |
@@ -2586,11 +2627,13 b' static Py_ssize_t inline_scan(indexObjec' | |||
|
2586 | 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 | 2633 | Py_ssize_t size; |
|
2593 | 2634 | |
|
2635 | static char *kwlist[] = {"data", "inlined", "revlogv2", NULL}; | |
|
2636 | ||
|
2594 | 2637 | /* Initialize before argument-checking to avoid index_dealloc() crash. |
|
2595 | 2638 | */ |
|
2596 | 2639 | self->added = NULL; |
@@ -2606,7 +2649,9 b' static int index_init(indexObject *self,' | |||
|
2606 | 2649 | self->nodelen = 20; |
|
2607 | 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 | 2655 | return -1; |
|
2611 | 2656 | if (!PyObject_CheckBuffer(data_obj)) { |
|
2612 | 2657 | PyErr_SetString(PyExc_TypeError, |
@@ -2618,8 +2663,22 b' static int index_init(indexObject *self,' | |||
|
2618 | 2663 | return -1; |
|
2619 | 2664 | } |
|
2620 | 2665 | |
|
2621 | self->nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, | |
|
2622 | -1, -1, -1, -1, nullid, self->nodelen); | |
|
2666 | if (revlogv2 && PyObject_IsTrue(revlogv2)) { | |
|
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 | 2682 | if (!self->nullentry) |
|
2624 | 2683 | return -1; |
|
2625 | 2684 | PyObject_GC_UnTrack(self->nullentry); |
@@ -2641,11 +2700,11 b' static int index_init(indexObject *self,' | |||
|
2641 | 2700 | goto bail; |
|
2642 | 2701 | self->length = len; |
|
2643 | 2702 | } else { |
|
2644 |
if (size % |
|
|
2703 | if (size % self->hdrsize) { | |
|
2645 | 2704 | PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
|
2646 | 2705 | goto bail; |
|
2647 | 2706 | } |
|
2648 |
self->length = size / |
|
|
2707 | self->length = size / self->hdrsize; | |
|
2649 | 2708 | } |
|
2650 | 2709 | |
|
2651 | 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 | 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 | 2863 | * cache: if data is inlined, a tuple (0, index_file_content), else None |
|
2805 | 2864 | * index_file_content could be a string, or a buffer |
|
2806 | 2865 | * |
|
2807 | 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 | 2870 | PyObject *cache = NULL; |
|
2812 | 2871 | indexObject *idx; |
@@ -2816,7 +2875,7 b' PyObject *parse_index2(PyObject *self, P' | |||
|
2816 | 2875 | if (idx == NULL) |
|
2817 | 2876 | goto bail; |
|
2818 | 2877 | |
|
2819 | ret = index_init(idx, args); | |
|
2878 | ret = index_init(idx, args, kwargs); | |
|
2820 | 2879 | if (ret == -1) |
|
2821 | 2880 | goto bail; |
|
2822 | 2881 |
General Comments 0
You need to be logged in to leave comments.
Login now