Mercurial > hg
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 } |