mercurial/cext/revlog.c
changeset 46141 41733a1c3532
parent 46078 c581b9ee22b1
child 46144 e4f6dae01b3b
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 }