comparison mercurial/cext/revlog.c @ 46141:41733a1c3532

cext: isolate hash size in the revlog handling in a single place Differential Revision: https://phab.mercurial-scm.org/D9450
author Joerg Sonnenberger <joerg@bec.de>
date Sat, 28 Nov 2020 22:27:12 +0100
parents c581b9ee22b1
children e4f6dae01b3b
comparison
equal deleted inserted replaced
46140:ec14c37958ec 46141:41733a1c3532
52 * Zero is empty 52 * Zero is empty
53 */ 53 */
54 typedef struct { 54 typedef struct {
55 indexObject *index; 55 indexObject *index;
56 nodetreenode *nodes; 56 nodetreenode *nodes;
57 Py_ssize_t nodelen;
57 unsigned length; /* # nodes in use */ 58 unsigned length; /* # nodes in use */
58 unsigned capacity; /* # nodes allocated */ 59 unsigned capacity; /* # nodes allocated */
59 int depth; /* maximum depth of tree */ 60 int depth; /* maximum depth of tree */
60 int splits; /* # splits performed */ 61 int splits; /* # splits performed */
61 } nodetree; 62 } nodetree;
78 */ 79 */
79 struct indexObjectStruct { 80 struct indexObjectStruct {
80 PyObject_HEAD 81 PyObject_HEAD
81 /* Type-specific fields go here. */ 82 /* Type-specific fields go here. */
82 PyObject *data; /* raw bytes of index */ 83 PyObject *data; /* raw bytes of index */
84 Py_ssize_t nodelen; /* digest size of the hash, 20 for SHA-1 */
85 PyObject *nullentry; /* fast path for references to null */
83 Py_buffer buf; /* buffer of data */ 86 Py_buffer buf; /* buffer of data */
84 const char **offsets; /* populated on demand */ 87 const char **offsets; /* populated on demand */
85 Py_ssize_t length; /* current on-disk number of elements */ 88 Py_ssize_t length; /* current on-disk number of elements */
86 unsigned new_length; /* number of added elements */ 89 unsigned new_length; /* number of added elements */
87 unsigned added_length; /* space reserved for added elements */ 90 unsigned added_length; /* space reserved for added elements */
99 static Py_ssize_t index_length(const indexObject *self) 102 static Py_ssize_t index_length(const indexObject *self)
100 { 103 {
101 return self->length + self->new_length; 104 return self->length + self->new_length;
102 } 105 }
103 106
104 static PyObject *nullentry = NULL; 107 static const char nullid[32] = {0};
105 static const char nullid[20] = {0};
106 static const Py_ssize_t nullrev = -1; 108 static const Py_ssize_t nullrev = -1;
107 109
108 static Py_ssize_t inline_scan(indexObject *self, const char **offsets); 110 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
109 111
110 static int index_find_node(indexObject *self, const char *node, 112 static int index_find_node(indexObject *self, const char *node);
111 Py_ssize_t nodelen);
112 113
113 #if LONG_MAX == 0x7fffffffL 114 #if LONG_MAX == 0x7fffffffL
114 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#"); 115 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
115 #else 116 #else
116 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#"); 117 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
272 * 4 bytes: uncompressed length 273 * 4 bytes: uncompressed length
273 * 4 bytes: base revision 274 * 4 bytes: base revision
274 * 4 bytes: link revision 275 * 4 bytes: link revision
275 * 4 bytes: parent 1 revision 276 * 4 bytes: parent 1 revision
276 * 4 bytes: parent 2 revision 277 * 4 bytes: parent 2 revision
277 * 32 bytes: nodeid (only 20 bytes used) 278 * 32 bytes: nodeid (only 20 bytes used with SHA-1)
278 */ 279 */
279 static PyObject *index_get(indexObject *self, Py_ssize_t pos) 280 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
280 { 281 {
281 uint64_t offset_flags; 282 uint64_t offset_flags;
282 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; 283 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
283 const char *c_node_id; 284 const char *c_node_id;
284 const char *data; 285 const char *data;
285 Py_ssize_t length = index_length(self); 286 Py_ssize_t length = index_length(self);
286 287
287 if (pos == nullrev) { 288 if (pos == nullrev) {
288 Py_INCREF(nullentry); 289 Py_INCREF(self->nullentry);
289 return nullentry; 290 return self->nullentry;
290 } 291 }
291 292
292 if (pos < 0 || pos >= length) { 293 if (pos < 0 || pos >= length) {
293 PyErr_SetString(PyExc_IndexError, "revlog index out of range"); 294 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
294 return NULL; 295 return NULL;
318 parent_2 = getbe32(data + 28); 319 parent_2 = getbe32(data + 28);
319 c_node_id = data + 32; 320 c_node_id = data + 32;
320 321
321 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, 322 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
322 base_rev, link_rev, parent_1, parent_2, c_node_id, 323 base_rev, link_rev, parent_1, parent_2, c_node_id,
323 (Py_ssize_t)20); 324 self->nodelen);
324 } 325 }
325 326
326 /* 327 /*
327 * Return the 20-byte SHA of the node corresponding to the given rev. 328 * Return the hash of node corresponding to the given rev.
328 */ 329 */
329 static const char *index_node(indexObject *self, Py_ssize_t pos) 330 static const char *index_node(indexObject *self, Py_ssize_t pos)
330 { 331 {
331 Py_ssize_t length = index_length(self); 332 Py_ssize_t length = index_length(self);
332 const char *data; 333 const char *data;
340 data = index_deref(self, pos); 341 data = index_deref(self, pos);
341 return data ? data + 32 : NULL; 342 return data ? data + 32 : NULL;
342 } 343 }
343 344
344 /* 345 /*
345 * Return the 20-byte SHA of the node corresponding to the given rev. The 346 * Return the hash of the node corresponding to the given rev. The
346 * rev is assumed to be existing. If not, an exception is set. 347 * rev is assumed to be existing. If not, an exception is set.
347 */ 348 */
348 static const char *index_node_existing(indexObject *self, Py_ssize_t pos) 349 static const char *index_node_existing(indexObject *self, Py_ssize_t pos)
349 { 350 {
350 const char *node = index_node(self, pos); 351 const char *node = index_node(self, pos);
355 return node; 356 return node;
356 } 357 }
357 358
358 static int nt_insert(nodetree *self, const char *node, int rev); 359 static int nt_insert(nodetree *self, const char *node, int rev);
359 360
360 static int node_check(PyObject *obj, char **node) 361 static int node_check(Py_ssize_t nodelen, PyObject *obj, char **node)
361 { 362 {
362 Py_ssize_t nodelen; 363 Py_ssize_t thisnodelen;
363 if (PyBytes_AsStringAndSize(obj, node, &nodelen) == -1) 364 if (PyBytes_AsStringAndSize(obj, node, &thisnodelen) == -1)
364 return -1; 365 return -1;
365 if (nodelen == 20) 366 if (nodelen == thisnodelen)
366 return 0; 367 return 0;
367 PyErr_SetString(PyExc_ValueError, "20-byte hash required"); 368 PyErr_Format(PyExc_ValueError, "node len %zd != expected node len %zd",
369 thisnodelen, nodelen);
368 return -1; 370 return -1;
369 } 371 }
370 372
371 static PyObject *index_append(indexObject *self, PyObject *obj) 373 static PyObject *index_append(indexObject *self, PyObject *obj)
372 { 374 {
380 &uncomp_len, &base_rev, &link_rev, &parent_1, 382 &uncomp_len, &base_rev, &link_rev, &parent_1,
381 &parent_2, &c_node_id, &c_node_id_len)) { 383 &parent_2, &c_node_id, &c_node_id_len)) {
382 PyErr_SetString(PyExc_TypeError, "8-tuple required"); 384 PyErr_SetString(PyExc_TypeError, "8-tuple required");
383 return NULL; 385 return NULL;
384 } 386 }
385 if (c_node_id_len != 20 && c_node_id_len != 32) { 387 if (c_node_id_len != self->nodelen) {
386 PyErr_SetString(PyExc_TypeError, "invalid node"); 388 PyErr_SetString(PyExc_TypeError, "invalid node");
387 return NULL; 389 return NULL;
388 } 390 }
389 391
390 if (self->new_length == self->added_length) { 392 if (self->new_length == self->added_length) {
695 } 697 }
696 iterator = PyObject_GetIter(roots); 698 iterator = PyObject_GetIter(roots);
697 if (iterator == NULL) 699 if (iterator == NULL)
698 return -2; 700 return -2;
699 while ((item = PyIter_Next(iterator))) { 701 while ((item = PyIter_Next(iterator))) {
700 if (node_check(item, &node) == -1) 702 if (node_check(self->nodelen, item, &node) == -1)
701 goto failed; 703 goto failed;
702 rev = index_find_node(self, node, 20); 704 rev = index_find_node(self, node);
703 /* null is implicitly public, so negative is invalid */ 705 /* null is implicitly public, so negative is invalid */
704 if (rev < 0 || rev >= len) 706 if (rev < 0 || rev >= len)
705 goto failed; 707 goto failed;
706 phases[rev] = phase; 708 phases[rev] = phase;
707 if (minrev == -1 || minrev > rev) 709 if (minrev == -1 || minrev > rev)
1491 int hex) 1493 int hex)
1492 { 1494 {
1493 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level; 1495 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
1494 int level, maxlevel, off; 1496 int level, maxlevel, off;
1495 1497
1496 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0) 1498 /* If the input is binary, do a fast check for the nullid first. */
1499 if (!hex && nodelen == self->nodelen && node[0] == '\0' &&
1500 node[1] == '\0' && memcmp(node, nullid, self->nodelen) == 0)
1497 return -1; 1501 return -1;
1498 1502
1499 if (hex) 1503 if (hex)
1500 maxlevel = nodelen > 40 ? 40 : (int)nodelen; 1504 maxlevel = nodelen;
1501 else 1505 else
1502 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2); 1506 maxlevel = 2 * nodelen;
1507 if (maxlevel > 2 * self->nodelen)
1508 maxlevel = 2 * self->nodelen;
1503 1509
1504 for (level = off = 0; level < maxlevel; level++) { 1510 for (level = off = 0; level < maxlevel; level++) {
1505 int k = getnybble(node, level); 1511 int k = getnybble(node, level);
1506 nodetreenode *n = &self->nodes[off]; 1512 nodetreenode *n = &self->nodes[off];
1507 int v = n->children[k]; 1513 int v = n->children[k];
1555 static int nt_insert(nodetree *self, const char *node, int rev) 1561 static int nt_insert(nodetree *self, const char *node, int rev)
1556 { 1562 {
1557 int level = 0; 1563 int level = 0;
1558 int off = 0; 1564 int off = 0;
1559 1565
1560 while (level < 40) { 1566 while (level < 2 * self->nodelen) {
1561 int k = nt_level(node, level); 1567 int k = nt_level(node, level);
1562 nodetreenode *n; 1568 nodetreenode *n;
1563 int v; 1569 int v;
1564 1570
1565 n = &self->nodes[off]; 1571 n = &self->nodes[off];
1574 index_node_existing(self->index, -(v + 2)); 1580 index_node_existing(self->index, -(v + 2));
1575 int noff; 1581 int noff;
1576 1582
1577 if (oldnode == NULL) 1583 if (oldnode == NULL)
1578 return -1; 1584 return -1;
1579 if (!memcmp(oldnode, node, 20)) { 1585 if (!memcmp(oldnode, node, self->nodelen)) {
1580 n->children[k] = -rev - 2; 1586 n->children[k] = -rev - 2;
1581 return 0; 1587 return 0;
1582 } 1588 }
1583 noff = nt_new(self); 1589 noff = nt_new(self);
1584 if (noff == -1) 1590 if (noff == -1)
1632 1638
1633 self->index = index; 1639 self->index = index;
1634 /* The input capacity is in terms of revisions, while the field is in 1640 /* The input capacity is in terms of revisions, while the field is in
1635 * terms of nodetree nodes. */ 1641 * terms of nodetree nodes. */
1636 self->capacity = (capacity < 4 ? 4 : capacity / 2); 1642 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1643 self->nodelen = index->nodelen;
1637 self->depth = 0; 1644 self->depth = 0;
1638 self->splits = 0; 1645 self->splits = 0;
1639 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) { 1646 if ((size_t)self->capacity > INT_MAX / sizeof(nodetreenode)) {
1640 PyErr_SetString(PyExc_ValueError, "overflow in init_nt"); 1647 PyErr_SetString(PyExc_ValueError, "overflow in init_nt");
1641 return -1; 1648 return -1;
1676 */ 1683 */
1677 static int nt_shortest(nodetree *self, const char *node) 1684 static int nt_shortest(nodetree *self, const char *node)
1678 { 1685 {
1679 int level, off; 1686 int level, off;
1680 1687
1681 for (level = off = 0; level < 40; level++) { 1688 for (level = off = 0; level < 2 * self->nodelen; level++) {
1682 int k, v; 1689 int k, v;
1683 nodetreenode *n = &self->nodes[off]; 1690 nodetreenode *n = &self->nodes[off];
1684 k = nt_level(node, level); 1691 k = nt_level(node, level);
1685 v = n->children[k]; 1692 v = n->children[k];
1686 if (v < 0) { 1693 if (v < 0) {
1687 const char *n; 1694 const char *n;
1688 v = -(v + 2); 1695 v = -(v + 2);
1689 n = index_node_existing(self->index, v); 1696 n = index_node_existing(self->index, v);
1690 if (n == NULL) 1697 if (n == NULL)
1691 return -3; 1698 return -3;
1692 if (memcmp(node, n, 20) != 0) 1699 if (memcmp(node, n, self->nodelen) != 0)
1693 /* 1700 /*
1694 * Found a unique prefix, but it wasn't for the 1701 * Found a unique prefix, but it wasn't for the
1695 * requested node (i.e the requested node does 1702 * requested node (i.e the requested node does
1696 * not exist). 1703 * not exist).
1697 */ 1704 */
1717 char *node; 1724 char *node;
1718 int length; 1725 int length;
1719 1726
1720 if (!PyArg_ParseTuple(args, "O", &val)) 1727 if (!PyArg_ParseTuple(args, "O", &val))
1721 return NULL; 1728 return NULL;
1722 if (node_check(val, &node) == -1) 1729 if (node_check(self->nt.nodelen, val, &node) == -1)
1723 return NULL; 1730 return NULL;
1724 1731
1725 length = nt_shortest(&self->nt, node); 1732 length = nt_shortest(&self->nt, node);
1726 if (length == -3) 1733 if (length == -3)
1727 return NULL; 1734 return NULL;
1817 * 1824 *
1818 * -3: error (exception set) 1825 * -3: error (exception set)
1819 * -2: not found (no exception set) 1826 * -2: not found (no exception set)
1820 * rest: valid rev 1827 * rest: valid rev
1821 */ 1828 */
1822 static int index_find_node(indexObject *self, const char *node, 1829 static int index_find_node(indexObject *self, const char *node)
1823 Py_ssize_t nodelen)
1824 { 1830 {
1825 int rev; 1831 int rev;
1826 1832
1827 if (index_init_nt(self) == -1) 1833 if (index_init_nt(self) == -1)
1828 return -3; 1834 return -3;
1829 1835
1830 self->ntlookups++; 1836 self->ntlookups++;
1831 rev = nt_find(&self->nt, node, nodelen, 0); 1837 rev = nt_find(&self->nt, node, self->nodelen, 0);
1832 if (rev >= -1) 1838 if (rev >= -1)
1833 return rev; 1839 return rev;
1834 1840
1835 /* 1841 /*
1836 * For the first handful of lookups, we scan the entire index, 1842 * For the first handful of lookups, we scan the entire index,
1844 if (self->ntmisses++ < 4) { 1850 if (self->ntmisses++ < 4) {
1845 for (rev = self->ntrev - 1; rev >= 0; rev--) { 1851 for (rev = self->ntrev - 1; rev >= 0; rev--) {
1846 const char *n = index_node_existing(self, rev); 1852 const char *n = index_node_existing(self, rev);
1847 if (n == NULL) 1853 if (n == NULL)
1848 return -3; 1854 return -3;
1849 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) { 1855 if (memcmp(node, n, self->nodelen) == 0) {
1850 if (nt_insert(&self->nt, n, rev) == -1) 1856 if (nt_insert(&self->nt, n, rev) == -1)
1851 return -3; 1857 return -3;
1852 break; 1858 break;
1853 } 1859 }
1854 } 1860 }
1859 return -3; 1865 return -3;
1860 if (nt_insert(&self->nt, n, rev) == -1) { 1866 if (nt_insert(&self->nt, n, rev) == -1) {
1861 self->ntrev = rev + 1; 1867 self->ntrev = rev + 1;
1862 return -3; 1868 return -3;
1863 } 1869 }
1864 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) { 1870 if (memcmp(node, n, self->nodelen) == 0) {
1865 break; 1871 break;
1866 } 1872 }
1867 } 1873 }
1868 self->ntrev = rev; 1874 self->ntrev = rev;
1869 } 1875 }
1884 return NULL; 1890 return NULL;
1885 } 1891 }
1886 return index_get(self, idx); 1892 return index_get(self, idx);
1887 } 1893 }
1888 1894
1889 if (node_check(value, &node) == -1) 1895 if (node_check(self->nodelen, value, &node) == -1)
1890 return NULL; 1896 return NULL;
1891 rev = index_find_node(self, node, 20); 1897 rev = index_find_node(self, node);
1892 if (rev >= -1) 1898 if (rev >= -1)
1893 return PyInt_FromLong(rev); 1899 return PyInt_FromLong(rev);
1894 if (rev == -2) 1900 if (rev == -2)
1895 raise_revlog_error(); 1901 raise_revlog_error();
1896 return NULL; 1902 return NULL;
1928 if (nodelen < 1) { 1934 if (nodelen < 1) {
1929 PyErr_SetString(PyExc_ValueError, "key too short"); 1935 PyErr_SetString(PyExc_ValueError, "key too short");
1930 return NULL; 1936 return NULL;
1931 } 1937 }
1932 1938
1933 if (nodelen > 40) { 1939 if (nodelen > 2 * self->nodelen) {
1934 PyErr_SetString(PyExc_ValueError, "key too long"); 1940 PyErr_SetString(PyExc_ValueError, "key too long");
1935 return NULL; 1941 return NULL;
1936 } 1942 }
1937 1943
1938 for (i = 0; i < nodelen; i++) 1944 for (i = 0; i < nodelen; i++)
1954 raise_revlog_error(); 1960 raise_revlog_error();
1955 return NULL; 1961 return NULL;
1956 case -2: 1962 case -2:
1957 Py_RETURN_NONE; 1963 Py_RETURN_NONE;
1958 case -1: 1964 case -1:
1959 return PyBytes_FromStringAndSize(nullid, 20); 1965 return PyBytes_FromStringAndSize(nullid, self->nodelen);
1960 } 1966 }
1961 1967
1962 fullnode = index_node_existing(self, rev); 1968 fullnode = index_node_existing(self, rev);
1963 if (fullnode == NULL) { 1969 if (fullnode == NULL) {
1964 return NULL; 1970 return NULL;
1965 } 1971 }
1966 return PyBytes_FromStringAndSize(fullnode, 20); 1972 return PyBytes_FromStringAndSize(fullnode, self->nodelen);
1967 } 1973 }
1968 1974
1969 static PyObject *index_shortest(indexObject *self, PyObject *args) 1975 static PyObject *index_shortest(indexObject *self, PyObject *args)
1970 { 1976 {
1971 PyObject *val; 1977 PyObject *val;
1972 char *node; 1978 char *node;
1973 int length; 1979 int length;
1974 1980
1975 if (!PyArg_ParseTuple(args, "O", &val)) 1981 if (!PyArg_ParseTuple(args, "O", &val))
1976 return NULL; 1982 return NULL;
1977 if (node_check(val, &node) == -1) 1983 if (node_check(self->nodelen, val, &node) == -1)
1978 return NULL; 1984 return NULL;
1979 1985
1980 self->ntlookups++; 1986 self->ntlookups++;
1981 if (index_init_nt(self) == -1) 1987 if (index_init_nt(self) == -1)
1982 return NULL; 1988 return NULL;
1998 char *node; 2004 char *node;
1999 int rev; 2005 int rev;
2000 2006
2001 if (!PyArg_ParseTuple(args, "O", &val)) 2007 if (!PyArg_ParseTuple(args, "O", &val))
2002 return NULL; 2008 return NULL;
2003 if (node_check(val, &node) == -1) 2009 if (node_check(self->nodelen, val, &node) == -1)
2004 return NULL; 2010 return NULL;
2005 rev = index_find_node(self, node, 20); 2011 rev = index_find_node(self, node);
2006 if (rev == -3) 2012 if (rev == -3)
2007 return NULL; 2013 return NULL;
2008 if (rev == -2) 2014 if (rev == -2)
2009 Py_RETURN_NONE; 2015 Py_RETURN_NONE;
2010 return PyInt_FromLong(rev); 2016 return PyInt_FromLong(rev);
2020 return -1; 2026 return -1;
2021 } 2027 }
2022 return rev >= -1 && rev < index_length(self); 2028 return rev >= -1 && rev < index_length(self);
2023 } 2029 }
2024 2030
2025 if (node_check(value, &node) == -1) 2031 if (node_check(self->nodelen, value, &node) == -1)
2026 return -1; 2032 return -1;
2027 2033
2028 switch (index_find_node(self, node, 20)) { 2034 switch (index_find_node(self, node)) {
2029 case -3: 2035 case -3:
2030 return -1; 2036 return -1;
2031 case -2: 2037 case -2:
2032 return 0; 2038 return 0;
2033 default: 2039 default:
2046 static PyObject *index_m_rev(indexObject *self, PyObject *val) 2052 static PyObject *index_m_rev(indexObject *self, PyObject *val)
2047 { 2053 {
2048 char *node; 2054 char *node;
2049 int rev; 2055 int rev;
2050 2056
2051 if (node_check(val, &node) == -1) 2057 if (node_check(self->nodelen, val, &node) == -1)
2052 return NULL; 2058 return NULL;
2053 rev = index_find_node(self, node, 20); 2059 rev = index_find_node(self, node);
2054 if (rev >= -1) 2060 if (rev >= -1)
2055 return PyInt_FromLong(rev); 2061 return PyInt_FromLong(rev);
2056 if (rev == -2) 2062 if (rev == -2)
2057 raise_revlog_error(); 2063 raise_revlog_error();
2058 return NULL; 2064 return NULL;
2527 long rev; 2533 long rev;
2528 2534
2529 if (PySlice_Check(item) && value == NULL) 2535 if (PySlice_Check(item) && value == NULL)
2530 return index_slice_del(self, item); 2536 return index_slice_del(self, item);
2531 2537
2532 if (node_check(item, &node) == -1) 2538 if (node_check(self->nodelen, item, &node) == -1)
2533 return -1; 2539 return -1;
2534 2540
2535 if (value == NULL) 2541 if (value == NULL)
2536 return self->ntinitialized ? nt_delete_node(&self->nt, node) 2542 return self->ntinitialized ? nt_delete_node(&self->nt, node)
2537 : 0; 2543 : 0;
2594 self->headrevs = NULL; 2600 self->headrevs = NULL;
2595 self->filteredrevs = Py_None; 2601 self->filteredrevs = Py_None;
2596 Py_INCREF(Py_None); 2602 Py_INCREF(Py_None);
2597 self->ntinitialized = 0; 2603 self->ntinitialized = 0;
2598 self->offsets = NULL; 2604 self->offsets = NULL;
2605 self->nodelen = 20;
2606 self->nullentry = NULL;
2599 2607
2600 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) 2608 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2601 return -1; 2609 return -1;
2602 if (!PyObject_CheckBuffer(data_obj)) { 2610 if (!PyObject_CheckBuffer(data_obj)) {
2603 PyErr_SetString(PyExc_TypeError, 2611 PyErr_SetString(PyExc_TypeError,
2604 "data does not support buffer interface"); 2612 "data does not support buffer interface");
2605 return -1; 2613 return -1;
2606 } 2614 }
2615 if (self->nodelen < 20 || self->nodelen > sizeof(nullid)) {
2616 PyErr_SetString(PyExc_RuntimeError, "unsupported node size");
2617 return -1;
2618 }
2619
2620 self->nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
2621 -1, -1, -1, -1, nullid, self->nodelen);
2622 if (!self->nullentry)
2623 return -1;
2624 PyObject_GC_UnTrack(self->nullentry);
2607 2625
2608 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1) 2626 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
2609 return -1; 2627 return -1;
2610 size = self->buf.len; 2628 size = self->buf.len;
2611 2629
2669 PyBuffer_Release(&self->buf); 2687 PyBuffer_Release(&self->buf);
2670 memset(&self->buf, 0, sizeof(self->buf)); 2688 memset(&self->buf, 0, sizeof(self->buf));
2671 } 2689 }
2672 Py_XDECREF(self->data); 2690 Py_XDECREF(self->data);
2673 PyMem_Free(self->added); 2691 PyMem_Free(self->added);
2692 Py_XDECREF(self->nullentry);
2674 PyObject_Del(self); 2693 PyObject_Del(self);
2675 } 2694 }
2676 2695
2677 static PySequenceMethods index_sequence_methods = { 2696 static PySequenceMethods index_sequence_methods = {
2678 (lenfunc)index_length, /* sq_length */ 2697 (lenfunc)index_length, /* sq_length */
2839 if (PyType_Ready(&nodetreeType) < 0) 2858 if (PyType_Ready(&nodetreeType) < 0)
2840 return; 2859 return;
2841 Py_INCREF(&nodetreeType); 2860 Py_INCREF(&nodetreeType);
2842 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType); 2861 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
2843 2862
2844 if (!nullentry) {
2845 nullentry =
2846 Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, -1,
2847 -1, -1, -1, nullid, (Py_ssize_t)20);
2848 }
2849 if (nullentry)
2850 PyObject_GC_UnTrack(nullentry);
2851
2852 caps = PyCapsule_New(&CAPI, "mercurial.cext.parsers.revlog_CAPI", NULL); 2863 caps = PyCapsule_New(&CAPI, "mercurial.cext.parsers.revlog_CAPI", NULL);
2853 if (caps != NULL) 2864 if (caps != NULL)
2854 PyModule_AddObject(mod, "revlog_CAPI", caps); 2865 PyModule_AddObject(mod, "revlog_CAPI", caps);
2855 } 2866 }