mercurial/cext/revlog.c
changeset 40562 e5ad3ef90aa1
parent 40561 5c14bf0c5be3
child 40598 fa33196088c4
equal deleted inserted replaced
40561:5c14bf0c5be3 40562:e5ad3ef90aa1
    42  * Zero is empty
    42  * Zero is empty
    43  */
    43  */
    44 typedef struct {
    44 typedef struct {
    45 	indexObject *index;
    45 	indexObject *index;
    46 	nodetreenode *nodes;
    46 	nodetreenode *nodes;
    47 	unsigned length;     /* # nodes in use */
    47 	unsigned length;   /* # nodes in use */
    48 	unsigned capacity;   /* # nodes allocated */
    48 	unsigned capacity; /* # nodes allocated */
    49 	int depth;           /* maximum depth of tree */
    49 	int depth;         /* maximum depth of tree */
    50 	int splits;          /* # splits performed */
    50 	int splits;        /* # splits performed */
    51 } nodetree;
    51 } nodetree;
    52 
    52 
    53 typedef struct {
    53 typedef struct {
    54 	PyObject_HEAD /* ; */
    54 	PyObject_HEAD /* ; */
    55 	nodetree nt;
    55 	    nodetree nt;
    56 } nodetreeObject;
    56 } nodetreeObject;
    57 
    57 
    58 /*
    58 /*
    59  * This class has two behaviors.
    59  * This class has two behaviors.
    60  *
    60  *
    67  * With string keys, we lazily perform a reverse mapping from node to
    67  * With string keys, we lazily perform a reverse mapping from node to
    68  * rev, using a base-16 trie.
    68  * rev, using a base-16 trie.
    69  */
    69  */
    70 struct indexObjectStruct {
    70 struct indexObjectStruct {
    71 	PyObject_HEAD
    71 	PyObject_HEAD
    72 	/* Type-specific fields go here. */
    72 	    /* Type-specific fields go here. */
    73 	PyObject *data;        /* raw bytes of index */
    73 	    PyObject *data;     /* raw bytes of index */
    74 	Py_buffer buf;         /* buffer of data */
    74 	Py_buffer buf;          /* buffer of data */
    75 	PyObject **cache;      /* cached tuples */
    75 	PyObject **cache;       /* cached tuples */
    76 	const char **offsets;  /* populated on demand */
    76 	const char **offsets;   /* populated on demand */
    77 	Py_ssize_t raw_length; /* original number of elements */
    77 	Py_ssize_t raw_length;  /* original number of elements */
    78 	Py_ssize_t length;     /* current number of elements */
    78 	Py_ssize_t length;      /* current number of elements */
    79 	PyObject *added;       /* populated on demand */
    79 	PyObject *added;        /* populated on demand */
    80 	PyObject *headrevs;    /* cache, invalidated on changes */
    80 	PyObject *headrevs;     /* cache, invalidated on changes */
    81 	PyObject *filteredrevs;/* filtered revs set */
    81 	PyObject *filteredrevs; /* filtered revs set */
    82 	nodetree nt;           /* base-16 trie */
    82 	nodetree nt;            /* base-16 trie */
    83 	int ntinitialized;     /* 0 or 1 */
    83 	int ntinitialized;      /* 0 or 1 */
    84 	int ntrev;             /* last rev scanned */
    84 	int ntrev;              /* last rev scanned */
    85 	int ntlookups;         /* # lookups */
    85 	int ntlookups;          /* # lookups */
    86 	int ntmisses;          /* # lookups that miss the cache */
    86 	int ntmisses;           /* # lookups that miss the cache */
    87 	int inlined;
    87 	int inlined;
    88 };
    88 };
    89 
    89 
    90 static Py_ssize_t index_length(const indexObject *self)
    90 static Py_ssize_t index_length(const indexObject *self)
    91 {
    91 {
   124 	Py_INCREF(dict);
   124 	Py_INCREF(dict);
   125 
   125 
   126 	errclass = PyDict_GetItemString(dict, "RevlogError");
   126 	errclass = PyDict_GetItemString(dict, "RevlogError");
   127 	if (errclass == NULL) {
   127 	if (errclass == NULL) {
   128 		PyErr_SetString(PyExc_SystemError,
   128 		PyErr_SetString(PyExc_SystemError,
   129 				"could not find RevlogError");
   129 		                "could not find RevlogError");
   130 		goto cleanup;
   130 		goto cleanup;
   131 	}
   131 	}
   132 
   132 
   133 	/* value of exception is ignored by callers */
   133 	/* value of exception is ignored by callers */
   134 	PyErr_SetString(errclass, "RevlogError");
   134 	PyErr_SetString(errclass, "RevlogError");
   144 static const char *index_deref(indexObject *self, Py_ssize_t pos)
   144 static const char *index_deref(indexObject *self, Py_ssize_t pos)
   145 {
   145 {
   146 	if (self->inlined && pos > 0) {
   146 	if (self->inlined && pos > 0) {
   147 		if (self->offsets == NULL) {
   147 		if (self->offsets == NULL) {
   148 			self->offsets = PyMem_Malloc(self->raw_length *
   148 			self->offsets = PyMem_Malloc(self->raw_length *
   149 					             sizeof(*self->offsets));
   149 			                             sizeof(*self->offsets));
   150 			if (self->offsets == NULL)
   150 			if (self->offsets == NULL)
   151 				return (const char *)PyErr_NoMemory();
   151 				return (const char *)PyErr_NoMemory();
   152 			inline_scan(self, self->offsets);
   152 			inline_scan(self, self->offsets);
   153 		}
   153 		}
   154 		return self->offsets[pos];
   154 		return self->offsets[pos];
   155 	}
   155 	}
   156 
   156 
   157 	return (const char *)(self->buf.buf) + pos * v1_hdrsize;
   157 	return (const char *)(self->buf.buf) + pos * v1_hdrsize;
   158 }
   158 }
   159 
   159 
   160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev,
   160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps,
   161 				    int *ps, int maxrev)
   161                                     int maxrev)
   162 {
   162 {
   163 	if (rev >= self->length) {
   163 	if (rev >= self->length) {
   164 		PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
   164 		PyObject *tuple =
       
   165 		    PyList_GET_ITEM(self->added, rev - self->length);
   165 		ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5));
   166 		ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5));
   166 		ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6));
   167 		ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6));
   167 	} else {
   168 	} else {
   168 		const char *data = index_deref(self, rev);
   169 		const char *data = index_deref(self, rev);
   169 		ps[0] = getbe32(data + 24);
   170 		ps[0] = getbe32(data + 24);
   175 		PyErr_SetString(PyExc_ValueError, "parent out of range");
   176 		PyErr_SetString(PyExc_ValueError, "parent out of range");
   176 		return -1;
   177 		return -1;
   177 	}
   178 	}
   178 	return 0;
   179 	return 0;
   179 }
   180 }
   180 
       
   181 
   181 
   182 /*
   182 /*
   183  * RevlogNG format (all in big endian, data may be inlined):
   183  * RevlogNG format (all in big endian, data may be inlined):
   184  *    6 bytes: offset
   184  *    6 bytes: offset
   185  *    2 bytes: flags
   185  *    2 bytes: flags
   246 	link_rev = getbe32(data + 20);
   246 	link_rev = getbe32(data + 20);
   247 	parent_1 = getbe32(data + 24);
   247 	parent_1 = getbe32(data + 24);
   248 	parent_2 = getbe32(data + 28);
   248 	parent_2 = getbe32(data + 28);
   249 	c_node_id = data + 32;
   249 	c_node_id = data + 32;
   250 
   250 
   251 	entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
   251 	entry = Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
   252 			      uncomp_len, base_rev, link_rev,
   252 	                      base_rev, link_rev, parent_1, parent_2, c_node_id,
   253 			      parent_1, parent_2, c_node_id, 20);
   253 	                      20);
   254 
   254 
   255 	if (entry) {
   255 	if (entry) {
   256 		PyObject_GC_UnTrack(entry);
   256 		PyObject_GC_UnTrack(entry);
   257 		Py_INCREF(entry);
   257 		Py_INCREF(entry);
   258 	}
   258 	}
   352 	PyObject *t = NULL;
   352 	PyObject *t = NULL;
   353 
   353 
   354 	if (obj == NULL)
   354 	if (obj == NULL)
   355 		return NULL;
   355 		return NULL;
   356 
   356 
   357 #define istat(__n, __d) \
   357 #define istat(__n, __d)                                                        \
   358 	do { \
   358 	do {                                                                   \
   359 		s = PyBytes_FromString(__d); \
   359 		s = PyBytes_FromString(__d);                                   \
   360 		t = PyInt_FromSsize_t(self->__n); \
   360 		t = PyInt_FromSsize_t(self->__n);                              \
   361 		if (!s || !t) \
   361 		if (!s || !t)                                                  \
   362 			goto bail; \
   362 			goto bail;                                             \
   363 		if (PyDict_SetItem(obj, s, t) == -1) \
   363 		if (PyDict_SetItem(obj, s, t) == -1)                           \
   364 			goto bail; \
   364 			goto bail;                                             \
   365 		Py_CLEAR(s); \
   365 		Py_CLEAR(s);                                                   \
   366 		Py_CLEAR(t); \
   366 		Py_CLEAR(t);                                                   \
   367 	} while (0)
   367 	} while (0)
   368 
   368 
   369 	if (self->added) {
   369 	if (self->added) {
   370 		Py_ssize_t len = PyList_GET_SIZE(self->added);
   370 		Py_ssize_t len = PyList_GET_SIZE(self->added);
   371 		s = PyBytes_FromString("index entries added");
   371 		s = PyBytes_FromString("index entries added");
   505 	Py_ssize_t l;
   505 	Py_ssize_t l;
   506 	int r;
   506 	int r;
   507 	int parents[2];
   507 	int parents[2];
   508 
   508 
   509 	/* Internal data structure:
   509 	/* Internal data structure:
   510 	 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit
   510 	 * tovisit: array of length len+1 (all revs + nullrev), filled upto
       
   511 	 * lentovisit
   511 	 *
   512 	 *
   512 	 * revstates: array of length len+1 (all revs + nullrev) */
   513 	 * revstates: array of length len+1 (all revs + nullrev) */
   513 	int *tovisit = NULL;
   514 	int *tovisit = NULL;
   514 	long lentovisit = 0;
   515 	long lentovisit = 0;
   515 	enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
   516 	enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
   516 	char *revstates = NULL;
   517 	char *revstates = NULL;
   517 
   518 
   518 	/* Get arguments */
   519 	/* Get arguments */
   519 	if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
   520 	if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads,
   520 			      &PyList_Type, &roots,
   521 	                      &PyList_Type, &roots, &PyBool_Type,
   521 			      &PyBool_Type, &includepatharg))
   522 	                      &includepatharg))
   522 		goto bail;
   523 		goto bail;
   523 
   524 
   524 	if (includepatharg == Py_True)
   525 	if (includepatharg == Py_True)
   525 		includepath = 1;
   526 		includepath = 1;
   526 
   527 
   593 			continue;
   594 			continue;
   594 		r = index_get_parents(self, revnum, parents, (int)len - 1);
   595 		r = index_get_parents(self, revnum, parents, (int)len - 1);
   595 		if (r < 0)
   596 		if (r < 0)
   596 			goto bail;
   597 			goto bail;
   597 		for (i = 0; i < 2; i++) {
   598 		for (i = 0; i < 2; i++) {
   598 			if (!(revstates[parents[i] + 1] & RS_SEEN)
   599 			if (!(revstates[parents[i] + 1] & RS_SEEN) &&
   599 			    && parents[i] >= minroot) {
   600 			    parents[i] >= minroot) {
   600 				tovisit[lentovisit++] = parents[i];
   601 				tovisit[lentovisit++] = parents[i];
   601 				revstates[parents[i] + 1] |= RS_SEEN;
   602 				revstates[parents[i] + 1] |= RS_SEEN;
   602 			}
   603 			}
   603 		}
   604 		}
   604 	}
   605 	}
   616 			/* Corrupted index file, error is set from
   617 			/* Corrupted index file, error is set from
   617 			 * index_get_parents */
   618 			 * index_get_parents */
   618 			if (r < 0)
   619 			if (r < 0)
   619 				goto bail;
   620 				goto bail;
   620 			if (((revstates[parents[0] + 1] |
   621 			if (((revstates[parents[0] + 1] |
   621 			      revstates[parents[1] + 1]) & RS_REACHABLE)
   622 			      revstates[parents[1] + 1]) &
   622 			    && !(revstates[i + 1] & RS_REACHABLE)) {
   623 			     RS_REACHABLE) &&
       
   624 			    !(revstates[i + 1] & RS_REACHABLE)) {
   623 				revstates[i + 1] |= RS_REACHABLE;
   625 				revstates[i + 1] |= RS_REACHABLE;
   624 				val = PyInt_FromSsize_t(i);
   626 				val = PyInt_FromSsize_t(i);
   625 				if (val == NULL)
   627 				if (val == NULL)
   626 					goto bail;
   628 					goto bail;
   627 				r = PyList_Append(reachable, val);
   629 				r = PyList_Append(reachable, val);
   664 	if (roots == NULL || !PyList_Check(roots)) {
   666 	if (roots == NULL || !PyList_Check(roots)) {
   665 		PyErr_SetString(PyExc_TypeError, "roots must be a list");
   667 		PyErr_SetString(PyExc_TypeError, "roots must be a list");
   666 		goto done;
   668 		goto done;
   667 	}
   669 	}
   668 
   670 
   669 	phases = calloc(len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
   671 	phases = calloc(
       
   672 	    len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
   670 	if (phases == NULL) {
   673 	if (phases == NULL) {
   671 		PyErr_NoMemory();
   674 		PyErr_NoMemory();
   672 		goto done;
   675 		goto done;
   673 	}
   676 	}
   674 	/* Put the phase information of all the roots in phases */
   677 	/* Put the phase information of all the roots in phases */
   675 	numphase = PyList_GET_SIZE(roots)+1;
   678 	numphase = PyList_GET_SIZE(roots) + 1;
   676 	minrevallphases = len + 1;
   679 	minrevallphases = len + 1;
   677 	phasessetlist = PyList_New(numphase);
   680 	phasessetlist = PyList_New(numphase);
   678 	if (phasessetlist == NULL)
   681 	if (phasessetlist == NULL)
   679 		goto done;
   682 		goto done;
   680 
   683 
   681 	PyList_SET_ITEM(phasessetlist, 0, Py_None);
   684 	PyList_SET_ITEM(phasessetlist, 0, Py_None);
   682 	Py_INCREF(Py_None);
   685 	Py_INCREF(Py_None);
   683 
   686 
   684 	for (i = 0; i < numphase-1; i++) {
   687 	for (i = 0; i < numphase - 1; i++) {
   685 		phaseroots = PyList_GET_ITEM(roots, i);
   688 		phaseroots = PyList_GET_ITEM(roots, i);
   686 		phaseset = PySet_New(NULL);
   689 		phaseset = PySet_New(NULL);
   687 		if (phaseset == NULL)
   690 		if (phaseset == NULL)
   688 			goto release;
   691 			goto release;
   689 		PyList_SET_ITEM(phasessetlist, i+1, phaseset);
   692 		PyList_SET_ITEM(phasessetlist, i + 1, phaseset);
   690 		if (!PyList_Check(phaseroots)) {
   693 		if (!PyList_Check(phaseroots)) {
   691 			PyErr_SetString(PyExc_TypeError,
   694 			PyErr_SetString(PyExc_TypeError,
   692 					"roots item must be a list");
   695 			                "roots item must be a list");
   693 			goto release;
   696 			goto release;
   694 		}
   697 		}
   695 		minrevphase = add_roots_get_min(self, phaseroots, i+1, phases);
   698 		minrevphase =
       
   699 		    add_roots_get_min(self, phaseroots, i + 1, phases);
   696 		if (minrevphase == -2) /* Error from add_roots_get_min */
   700 		if (minrevphase == -2) /* Error from add_roots_get_min */
   697 			goto release;
   701 			goto release;
   698 		minrevallphases = MIN(minrevallphases, minrevphase);
   702 		minrevallphases = MIN(minrevallphases, minrevphase);
   699 	}
   703 	}
   700 	/* Propagate the phase information from the roots to the revs */
   704 	/* Propagate the phase information from the roots to the revs */
   701 	if (minrevallphases != -1) {
   705 	if (minrevallphases != -1) {
   702 		int parents[2];
   706 		int parents[2];
   703 		for (i = minrevallphases; i < len; i++) {
   707 		for (i = minrevallphases; i < len; i++) {
   704 			if (index_get_parents(self, i, parents,
   708 			if (index_get_parents(self, i, parents, (int)len - 1) <
   705 					      (int)len - 1) < 0)
   709 			    0)
   706 				goto release;
   710 				goto release;
   707 			set_phase_from_parents(phases, parents[0], parents[1], i);
   711 			set_phase_from_parents(phases, parents[0], parents[1],
       
   712 			                       i);
   708 		}
   713 		}
   709 	}
   714 	}
   710 	/* Transform phase list to a python list */
   715 	/* Transform phase list to a python list */
   711 	phasessize = PyInt_FromSsize_t(len);
   716 	phasessize = PyInt_FromSsize_t(len);
   712 	if (phasessize == NULL)
   717 	if (phasessize == NULL)
   713 		goto release;
   718 		goto release;
   714 	for (i = 0; i < len; i++) {
   719 	for (i = 0; i < len; i++) {
   715 		phase = phases[i];
   720 		phase = phases[i];
   716 		/* We only store the sets of phase for non public phase, the public phase
   721 		/* We only store the sets of phase for non public phase, the
   717 		 * is computed as a difference */
   722 		 * public phase is computed as a difference */
   718 		if (phase != 0) {
   723 		if (phase != 0) {
   719 			phaseset = PyList_GET_ITEM(phasessetlist, phase);
   724 			phaseset = PyList_GET_ITEM(phasessetlist, phase);
   720 			rev = PyInt_FromSsize_t(i);
   725 			rev = PyInt_FromSsize_t(i);
   721 			if (rev == NULL)
   726 			if (rev == NULL)
   722 				goto release;
   727 				goto release;
   754 	Py_INCREF(filteredrevs);
   759 	Py_INCREF(filteredrevs);
   755 
   760 
   756 	if (filteredrevs != Py_None) {
   761 	if (filteredrevs != Py_None) {
   757 		filter = PyObject_GetAttrString(filteredrevs, "__contains__");
   762 		filter = PyObject_GetAttrString(filteredrevs, "__contains__");
   758 		if (!filter) {
   763 		if (!filter) {
   759 			PyErr_SetString(PyExc_TypeError,
   764 			PyErr_SetString(
   760 				"filteredrevs has no attribute __contains__");
   765 			    PyExc_TypeError,
       
   766 			    "filteredrevs has no attribute __contains__");
   761 			goto bail;
   767 			goto bail;
   762 		}
   768 		}
   763 	}
   769 	}
   764 
   770 
   765 	len = index_length(self);
   771 	len = index_length(self);
   783 
   789 
   784 	for (i = len - 1; i >= 0; i--) {
   790 	for (i = len - 1; i >= 0; i--) {
   785 		int isfiltered;
   791 		int isfiltered;
   786 		int parents[2];
   792 		int parents[2];
   787 
   793 
   788 		/* If nothead[i] == 1, it means we've seen an unfiltered child of this
   794 		/* If nothead[i] == 1, it means we've seen an unfiltered child
   789 		 * node already, and therefore this node is not filtered. So we can skip
   795 		 * of this node already, and therefore this node is not
   790 		 * the expensive check_filter step.
   796 		 * filtered. So we can skip the expensive check_filter step.
   791 		 */
   797 		 */
   792 		if (nothead[i] != 1) {
   798 		if (nothead[i] != 1) {
   793 			isfiltered = check_filter(filter, i);
   799 			isfiltered = check_filter(filter, i);
   794 			if (isfiltered == -1) {
   800 			if (isfiltered == -1) {
   795 				PyErr_SetString(PyExc_TypeError,
   801 				PyErr_SetString(PyExc_TypeError,
   796 					"unable to check filter");
   802 				                "unable to check filter");
   797 				goto bail;
   803 				goto bail;
   798 			}
   804 			}
   799 
   805 
   800 			if (isfiltered) {
   806 			if (isfiltered) {
   801 				nothead[i] = 1;
   807 				nothead[i] = 1;
   843 static inline int index_baserev(indexObject *self, int rev)
   849 static inline int index_baserev(indexObject *self, int rev)
   844 {
   850 {
   845 	const char *data;
   851 	const char *data;
   846 
   852 
   847 	if (rev >= self->length) {
   853 	if (rev >= self->length) {
   848 		PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
   854 		PyObject *tuple =
       
   855 		    PyList_GET_ITEM(self->added, rev - self->length);
   849 		return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
   856 		return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
   850 	}
   857 	} else {
   851 	else {
       
   852 		data = index_deref(self, rev);
   858 		data = index_deref(self, rev);
   853 		if (data == NULL) {
   859 		if (data == NULL) {
   854 			return -2;
   860 			return -2;
   855 		}
   861 		}
   856 
   862 
   874 	if (PyInt_Check(stoparg)) {
   880 	if (PyInt_Check(stoparg)) {
   875 		stoprev = (int)PyInt_AsLong(stoparg);
   881 		stoprev = (int)PyInt_AsLong(stoparg);
   876 		if (stoprev == -1 && PyErr_Occurred()) {
   882 		if (stoprev == -1 && PyErr_Occurred()) {
   877 			return NULL;
   883 			return NULL;
   878 		}
   884 		}
   879 	}
   885 	} else if (stoparg == Py_None) {
   880 	else if (stoparg == Py_None) {
       
   881 		stoprev = -2;
   886 		stoprev = -2;
   882 	}
   887 	} else {
   883 	else {
       
   884 		PyErr_SetString(PyExc_ValueError,
   888 		PyErr_SetString(PyExc_ValueError,
   885 			"stoprev must be integer or None");
   889 		                "stoprev must be integer or None");
   886 		return NULL;
   890 		return NULL;
   887 	}
   891 	}
   888 
   892 
   889 	if (rev < 0 || rev >= length) {
   893 	if (rev < 0 || rev >= length) {
   890 		PyErr_SetString(PyExc_ValueError, "revlog index out of range");
   894 		PyErr_SetString(PyExc_ValueError, "revlog index out of range");
   918 		}
   922 		}
   919 		Py_DECREF(value);
   923 		Py_DECREF(value);
   920 
   924 
   921 		if (generaldelta) {
   925 		if (generaldelta) {
   922 			iterrev = baserev;
   926 			iterrev = baserev;
   923 		}
   927 		} else {
   924 		else {
       
   925 			iterrev--;
   928 			iterrev--;
   926 		}
   929 		}
   927 
   930 
   928 		if (iterrev < 0) {
   931 		if (iterrev < 0) {
   929 			break;
   932 			break;
   930 		}
   933 		}
   931 
   934 
   932 		if (iterrev >= length) {
   935 		if (iterrev >= length) {
   933 			PyErr_SetString(PyExc_IndexError, "revision outside index");
   936 			PyErr_SetString(PyExc_IndexError,
       
   937 			                "revision outside index");
   934 			return NULL;
   938 			return NULL;
   935 		}
   939 		}
   936 
   940 
   937 		baserev = index_baserev(self, iterrev);
   941 		baserev = index_baserev(self, iterrev);
   938 
   942 
   944 		}
   948 		}
   945 	}
   949 	}
   946 
   950 
   947 	if (iterrev == stoprev) {
   951 	if (iterrev == stoprev) {
   948 		stopped = 1;
   952 		stopped = 1;
   949 	}
   953 	} else {
   950 	else {
       
   951 		PyObject *value = PyInt_FromLong(iterrev);
   954 		PyObject *value = PyInt_FromLong(iterrev);
   952 		if (value == NULL) {
   955 		if (value == NULL) {
   953 			goto bail;
   956 			goto bail;
   954 		}
   957 		}
   955 		if (PyList_Append(chain, value)) {
   958 		if (PyList_Append(chain, value)) {
   974 	return NULL;
   977 	return NULL;
   975 }
   978 }
   976 
   979 
   977 static inline int nt_level(const char *node, Py_ssize_t level)
   980 static inline int nt_level(const char *node, Py_ssize_t level)
   978 {
   981 {
   979 	int v = node[level>>1];
   982 	int v = node[level >> 1];
   980 	if (!(level & 1))
   983 	if (!(level & 1))
   981 		v >>= 4;
   984 		v >>= 4;
   982 	return v & 0xf;
   985 	return v & 0xf;
   983 }
   986 }
   984 
   987 
   988  *   -4: match is ambiguous (multiple candidates)
   991  *   -4: match is ambiguous (multiple candidates)
   989  *   -2: not found
   992  *   -2: not found
   990  * rest: valid rev
   993  * rest: valid rev
   991  */
   994  */
   992 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
   995 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen,
   993 		   int hex)
   996                    int hex)
   994 {
   997 {
   995 	int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
   998 	int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
   996 	int level, maxlevel, off;
   999 	int level, maxlevel, off;
   997 
  1000 
   998 	if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
  1001 	if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
  1034 	if (self->length == self->capacity) {
  1037 	if (self->length == self->capacity) {
  1035 		unsigned newcapacity;
  1038 		unsigned newcapacity;
  1036 		nodetreenode *newnodes;
  1039 		nodetreenode *newnodes;
  1037 		newcapacity = self->capacity * 2;
  1040 		newcapacity = self->capacity * 2;
  1038 		if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
  1041 		if (newcapacity >= INT_MAX / sizeof(nodetreenode)) {
  1039 			PyErr_SetString(PyExc_MemoryError, "overflow in nt_new");
  1042 			PyErr_SetString(PyExc_MemoryError,
       
  1043 			                "overflow in nt_new");
  1040 			return -1;
  1044 			return -1;
  1041 		}
  1045 		}
  1042 		newnodes = realloc(self->nodes, newcapacity * sizeof(nodetreenode));
  1046 		newnodes =
       
  1047 		    realloc(self->nodes, newcapacity * sizeof(nodetreenode));
  1043 		if (newnodes == NULL) {
  1048 		if (newnodes == NULL) {
  1044 			PyErr_SetString(PyExc_MemoryError, "out of memory");
  1049 			PyErr_SetString(PyExc_MemoryError, "out of memory");
  1045 			return -1;
  1050 			return -1;
  1046 		}
  1051 		}
  1047 		self->capacity = newcapacity;
  1052 		self->capacity = newcapacity;
  1068 		if (v == 0) {
  1073 		if (v == 0) {
  1069 			n->children[k] = -rev - 2;
  1074 			n->children[k] = -rev - 2;
  1070 			return 0;
  1075 			return 0;
  1071 		}
  1076 		}
  1072 		if (v < 0) {
  1077 		if (v < 0) {
  1073 			const char *oldnode = index_node_existing(self->index, -(v + 2));
  1078 			const char *oldnode =
       
  1079 			    index_node_existing(self->index, -(v + 2));
  1074 			int noff;
  1080 			int noff;
  1075 
  1081 
  1076 			if (oldnode == NULL)
  1082 			if (oldnode == NULL)
  1077 				return -1;
  1083 				return -1;
  1078 			if (!memcmp(oldnode, node, 20)) {
  1084 			if (!memcmp(oldnode, node, 20)) {
  1117 	Py_RETURN_NONE;
  1123 	Py_RETURN_NONE;
  1118 }
  1124 }
  1119 
  1125 
  1120 static int nt_delete_node(nodetree *self, const char *node)
  1126 static int nt_delete_node(nodetree *self, const char *node)
  1121 {
  1127 {
  1122 	/* rev==-2 happens to get encoded as 0, which is interpreted as not set */
  1128 	/* rev==-2 happens to get encoded as 0, which is interpreted as not set
       
  1129 	 */
  1123 	return nt_insert(self, node, -2);
  1130 	return nt_insert(self, node, -2);
  1124 }
  1131 }
  1125 
  1132 
  1126 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
  1133 static int nt_init(nodetree *self, indexObject *index, unsigned capacity)
  1127 {
  1134 {
  1154 	PyObject *index;
  1161 	PyObject *index;
  1155 	unsigned capacity;
  1162 	unsigned capacity;
  1156 	if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
  1163 	if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
  1157 		return -1;
  1164 		return -1;
  1158 	Py_INCREF(index);
  1165 	Py_INCREF(index);
  1159 	return nt_init(&self->nt, (indexObject*)index, capacity);
  1166 	return nt_init(&self->nt, (indexObject *)index, capacity);
  1160 }
  1167 }
  1161 
  1168 
  1162 static int nt_partialmatch(nodetree *self, const char *node,
  1169 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen)
  1163 			   Py_ssize_t nodelen)
       
  1164 {
  1170 {
  1165 	return nt_find(self, node, nodelen, 1);
  1171 	return nt_find(self, node, nodelen, 1);
  1166 }
  1172 }
  1167 
  1173 
  1168 /*
  1174 /*
  1244 	nt_dealloc(&self->nt);
  1250 	nt_dealloc(&self->nt);
  1245 	PyObject_Del(self);
  1251 	PyObject_Del(self);
  1246 }
  1252 }
  1247 
  1253 
  1248 static PyMethodDef ntobj_methods[] = {
  1254 static PyMethodDef ntobj_methods[] = {
  1249 	{"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
  1255     {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
  1250 	 "insert an index entry"},
  1256      "insert an index entry"},
  1251 	{"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
  1257     {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
  1252 	 "find length of shortest hex nodeid of a binary ID"},
  1258      "find length of shortest hex nodeid of a binary ID"},
  1253 	{NULL} /* Sentinel */
  1259     {NULL} /* Sentinel */
  1254 };
  1260 };
  1255 
  1261 
  1256 static PyTypeObject nodetreeType = {
  1262 static PyTypeObject nodetreeType = {
  1257 	PyVarObject_HEAD_INIT(NULL, 0) /* header */
  1263     PyVarObject_HEAD_INIT(NULL, 0) /* header */
  1258 	"parsers.nodetree",        /* tp_name */
  1264     "parsers.nodetree",            /* tp_name */
  1259 	sizeof(nodetreeObject) ,   /* tp_basicsize */
  1265     sizeof(nodetreeObject),        /* tp_basicsize */
  1260 	0,                         /* tp_itemsize */
  1266     0,                             /* tp_itemsize */
  1261 	(destructor)ntobj_dealloc, /* tp_dealloc */
  1267     (destructor)ntobj_dealloc,     /* tp_dealloc */
  1262 	0,                         /* tp_print */
  1268     0,                             /* tp_print */
  1263 	0,                         /* tp_getattr */
  1269     0,                             /* tp_getattr */
  1264 	0,                         /* tp_setattr */
  1270     0,                             /* tp_setattr */
  1265 	0,                         /* tp_compare */
  1271     0,                             /* tp_compare */
  1266 	0,                         /* tp_repr */
  1272     0,                             /* tp_repr */
  1267 	0,                         /* tp_as_number */
  1273     0,                             /* tp_as_number */
  1268 	0,                         /* tp_as_sequence */
  1274     0,                             /* tp_as_sequence */
  1269 	0,                         /* tp_as_mapping */
  1275     0,                             /* tp_as_mapping */
  1270 	0,                         /* tp_hash */
  1276     0,                             /* tp_hash */
  1271 	0,                         /* tp_call */
  1277     0,                             /* tp_call */
  1272 	0,                         /* tp_str */
  1278     0,                             /* tp_str */
  1273 	0,                         /* tp_getattro */
  1279     0,                             /* tp_getattro */
  1274 	0,                         /* tp_setattro */
  1280     0,                             /* tp_setattro */
  1275 	0,                         /* tp_as_buffer */
  1281     0,                             /* tp_as_buffer */
  1276 	Py_TPFLAGS_DEFAULT,        /* tp_flags */
  1282     Py_TPFLAGS_DEFAULT,            /* tp_flags */
  1277 	"nodetree",                /* tp_doc */
  1283     "nodetree",                    /* tp_doc */
  1278 	0,                         /* tp_traverse */
  1284     0,                             /* tp_traverse */
  1279 	0,                         /* tp_clear */
  1285     0,                             /* tp_clear */
  1280 	0,                         /* tp_richcompare */
  1286     0,                             /* tp_richcompare */
  1281 	0,                         /* tp_weaklistoffset */
  1287     0,                             /* tp_weaklistoffset */
  1282 	0,                         /* tp_iter */
  1288     0,                             /* tp_iter */
  1283 	0,                         /* tp_iternext */
  1289     0,                             /* tp_iternext */
  1284 	ntobj_methods,             /* tp_methods */
  1290     ntobj_methods,                 /* tp_methods */
  1285 	0,                         /* tp_members */
  1291     0,                             /* tp_members */
  1286 	0,                         /* tp_getset */
  1292     0,                             /* tp_getset */
  1287 	0,                         /* tp_base */
  1293     0,                             /* tp_base */
  1288 	0,                         /* tp_dict */
  1294     0,                             /* tp_dict */
  1289 	0,                         /* tp_descr_get */
  1295     0,                             /* tp_descr_get */
  1290 	0,                         /* tp_descr_set */
  1296     0,                             /* tp_descr_set */
  1291 	0,                         /* tp_dictoffset */
  1297     0,                             /* tp_dictoffset */
  1292 	(initproc)ntobj_init,      /* tp_init */
  1298     (initproc)ntobj_init,          /* tp_init */
  1293 	0,                         /* tp_alloc */
  1299     0,                             /* tp_alloc */
  1294 };
  1300 };
  1295 
  1301 
  1296 static int index_init_nt(indexObject *self)
  1302 static int index_init_nt(indexObject *self)
  1297 {
  1303 {
  1298 	if (!self->ntinitialized) {
  1304 	if (!self->ntinitialized) {
  1317  *
  1323  *
  1318  *   -3: error (exception set)
  1324  *   -3: error (exception set)
  1319  *   -2: not found (no exception set)
  1325  *   -2: not found (no exception set)
  1320  * rest: valid rev
  1326  * rest: valid rev
  1321  */
  1327  */
  1322 static int index_find_node(indexObject *self,
  1328 static int index_find_node(indexObject *self, const char *node,
  1323 			   const char *node, Py_ssize_t nodelen)
  1329                            Py_ssize_t nodelen)
  1324 {
  1330 {
  1325 	int rev;
  1331 	int rev;
  1326 
  1332 
  1327 	if (index_init_nt(self) == -1)
  1333 	if (index_init_nt(self) == -1)
  1328 		return -3;
  1334 		return -3;
  1392 }
  1398 }
  1393 
  1399 
  1394 /*
  1400 /*
  1395  * Fully populate the radix tree.
  1401  * Fully populate the radix tree.
  1396  */
  1402  */
  1397 static int index_populate_nt(indexObject *self) {
  1403 static int index_populate_nt(indexObject *self)
       
  1404 {
  1398 	int rev;
  1405 	int rev;
  1399 	if (self->ntrev > 0) {
  1406 	if (self->ntrev > 0) {
  1400 		for (rev = self->ntrev - 1; rev >= 0; rev--) {
  1407 		for (rev = self->ntrev - 1; rev >= 0; rev--) {
  1401 			const char *n = index_node_existing(self, rev);
  1408 			const char *n = index_node_existing(self, rev);
  1402 			if (n == NULL)
  1409 			if (n == NULL)
  1532  * Given a disjoint set of revs, return all candidates for the
  1539  * Given a disjoint set of revs, return all candidates for the
  1533  * greatest common ancestor. In revset notation, this is the set
  1540  * greatest common ancestor. In revset notation, this is the set
  1534  * "heads(::a and ::b and ...)"
  1541  * "heads(::a and ::b and ...)"
  1535  */
  1542  */
  1536 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
  1543 static PyObject *find_gca_candidates(indexObject *self, const int *revs,
  1537 				     int revcount)
  1544                                      int revcount)
  1538 {
  1545 {
  1539 	const bitmask allseen = (1ull << revcount) - 1;
  1546 	const bitmask allseen = (1ull << revcount) - 1;
  1540 	const bitmask poison = 1ull << revcount;
  1547 	const bitmask poison = 1ull << revcount;
  1541 	PyObject *gca = PyList_New(0);
  1548 	PyObject *gca = PyList_New(0);
  1542 	int i, v, interesting;
  1549 	int i, v, interesting;
  1597 			sp = seen[p];
  1604 			sp = seen[p];
  1598 			if (sv < poison) {
  1605 			if (sv < poison) {
  1599 				if (sp == 0) {
  1606 				if (sp == 0) {
  1600 					seen[p] = sv;
  1607 					seen[p] = sv;
  1601 					interesting++;
  1608 					interesting++;
  1602 				}
  1609 				} else if (sp != sv)
  1603 				else if (sp != sv)
       
  1604 					seen[p] |= sv;
  1610 					seen[p] |= sv;
  1605 			} else {
  1611 			} else {
  1606 				if (sp && sp < poison)
  1612 				if (sp && sp < poison)
  1607 					interesting--;
  1613 					interesting--;
  1608 				seen[p] = sv;
  1614 				seen[p] = sv;
  1634 	int maxrev = -1;
  1640 	int maxrev = -1;
  1635 	long final;
  1641 	long final;
  1636 
  1642 
  1637 	if (revcount > capacity) {
  1643 	if (revcount > capacity) {
  1638 		PyErr_Format(PyExc_OverflowError,
  1644 		PyErr_Format(PyExc_OverflowError,
  1639 			     "bitset size (%ld) > capacity (%ld)",
  1645 		             "bitset size (%ld) > capacity (%ld)",
  1640 			     (long)revcount, (long)capacity);
  1646 		             (long)revcount, (long)capacity);
  1641 		return NULL;
  1647 		return NULL;
  1642 	}
  1648 	}
  1643 
  1649 
  1644 	for (i = 0; i < revcount; i++) {
  1650 	for (i = 0; i < revcount; i++) {
  1645 		int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
  1651 		int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i));
  1709 						interesting[sp] -= 1;
  1715 						interesting[sp] -= 1;
  1710 						if (interesting[sp] == 0)
  1716 						if (interesting[sp] == 0)
  1711 							ninteresting -= 1;
  1717 							ninteresting -= 1;
  1712 					}
  1718 					}
  1713 				}
  1719 				}
  1714 			}
  1720 			} else if (dv == dp - 1) {
  1715 			else if (dv == dp - 1) {
       
  1716 				long nsp = sp | sv;
  1721 				long nsp = sp | sv;
  1717 				if (nsp == sp)
  1722 				if (nsp == sp)
  1718 					continue;
  1723 					continue;
  1719 				seen[p] = nsp;
  1724 				seen[p] = nsp;
  1720 				interesting[sp] -= 1;
  1725 				interesting[sp] -= 1;
  1798 		bitmask x;
  1803 		bitmask x;
  1799 		long val;
  1804 		long val;
  1800 
  1805 
  1801 		if (!PyInt_Check(obj)) {
  1806 		if (!PyInt_Check(obj)) {
  1802 			PyErr_SetString(PyExc_TypeError,
  1807 			PyErr_SetString(PyExc_TypeError,
  1803 					"arguments must all be ints");
  1808 			                "arguments must all be ints");
  1804 			Py_DECREF(obj);
  1809 			Py_DECREF(obj);
  1805 			goto bail;
  1810 			goto bail;
  1806 		}
  1811 		}
  1807 		val = PyInt_AsLong(obj);
  1812 		val = PyInt_AsLong(obj);
  1808 		Py_DECREF(obj);
  1813 		Py_DECREF(obj);
  1809 		if (val == -1) {
  1814 		if (val == -1) {
  1810 			ret = PyList_New(0);
  1815 			ret = PyList_New(0);
  1811 			goto done;
  1816 			goto done;
  1812 		}
  1817 		}
  1813 		if (val < 0 || val >= len) {
  1818 		if (val < 0 || val >= len) {
  1814 			PyErr_SetString(PyExc_IndexError,
  1819 			PyErr_SetString(PyExc_IndexError, "index out of range");
  1815 					"index out of range");
       
  1816 			goto bail;
  1820 			goto bail;
  1817 		}
  1821 		}
  1818 		/* this cheesy bloom filter lets us avoid some more
  1822 		/* this cheesy bloom filter lets us avoid some more
  1819 		 * expensive duplicate checks in the common set-is-disjoint
  1823 		 * expensive duplicate checks in the common set-is-disjoint
  1820 		 * case */
  1824 		 * case */
  1823 			int k;
  1827 			int k;
  1824 			for (k = 0; k < revcount; k++) {
  1828 			for (k = 0; k < revcount; k++) {
  1825 				if (val == revs[k])
  1829 				if (val == revs[k])
  1826 					goto duplicate;
  1830 					goto duplicate;
  1827 			}
  1831 			}
  1828 		}
  1832 		} else
  1829 		else repeat |= x;
  1833 			repeat |= x;
  1830 		if (revcount >= capacity) {
  1834 		if (revcount >= capacity) {
  1831 			PyErr_Format(PyExc_OverflowError,
  1835 			PyErr_Format(PyExc_OverflowError,
  1832 				     "bitset size (%d) > capacity (%d)",
  1836 			             "bitset size (%d) > capacity (%d)",
  1833 				     revcount, capacity);
  1837 			             revcount, capacity);
  1834 			goto bail;
  1838 			goto bail;
  1835 		}
  1839 		}
  1836 		revs[revcount++] = (int)val;
  1840 		revs[revcount++] = (int)val;
  1837 	duplicate:;
  1841 	duplicate:;
  1838 	}
  1842 	}
  1915 	Py_ssize_t length = index_length(self) + 1;
  1919 	Py_ssize_t length = index_length(self) + 1;
  1916 	int ret = 0;
  1920 	int ret = 0;
  1917 
  1921 
  1918 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
  1922 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
  1919 #ifdef IS_PY3K
  1923 #ifdef IS_PY3K
  1920 	if (PySlice_GetIndicesEx(item, length,
  1924 	if (PySlice_GetIndicesEx(item, length, &start, &stop, &step,
  1921 				 &start, &stop, &step, &slicelength) < 0)
  1925 	                         &slicelength) < 0)
  1922 #else
  1926 #else
  1923 	if (PySlice_GetIndicesEx((PySliceObject*)item, length,
  1927 	if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop,
  1924 				 &start, &stop, &step, &slicelength) < 0)
  1928 	                         &step, &slicelength) < 0)
  1925 #endif
  1929 #endif
  1926 		return -1;
  1930 		return -1;
  1927 
  1931 
  1928 	if (slicelength <= 0)
  1932 	if (slicelength <= 0)
  1929 		return 0;
  1933 		return 0;
  1931 	if ((step < 0 && start < stop) || (step > 0 && start > stop))
  1935 	if ((step < 0 && start < stop) || (step > 0 && start > stop))
  1932 		stop = start;
  1936 		stop = start;
  1933 
  1937 
  1934 	if (step < 0) {
  1938 	if (step < 0) {
  1935 		stop = start + 1;
  1939 		stop = start + 1;
  1936 		start = stop + step*(slicelength - 1) - 1;
  1940 		start = stop + step * (slicelength - 1) - 1;
  1937 		step = -step;
  1941 		step = -step;
  1938 	}
  1942 	}
  1939 
  1943 
  1940 	if (step != 1) {
  1944 	if (step != 1) {
  1941 		PyErr_SetString(PyExc_ValueError,
  1945 		PyErr_SetString(PyExc_ValueError,
  1942 				"revlog index delete requires step size of 1");
  1946 		                "revlog index delete requires step size of 1");
  1943 		return -1;
  1947 		return -1;
  1944 	}
  1948 	}
  1945 
  1949 
  1946 	if (stop != length - 1) {
  1950 	if (stop != length - 1) {
  1947 		PyErr_SetString(PyExc_IndexError,
  1951 		PyErr_SetString(PyExc_IndexError,
  1948 				"revlog index deletion indices are invalid");
  1952 		                "revlog index deletion indices are invalid");
  1949 		return -1;
  1953 		return -1;
  1950 	}
  1954 	}
  1951 
  1955 
  1952 	if (start < self->length) {
  1956 	if (start < self->length) {
  1953 		if (self->ntinitialized) {
  1957 		if (self->ntinitialized) {
  1982 		if (self->ntrev > start)
  1986 		if (self->ntrev > start)
  1983 			self->ntrev = (int)start;
  1987 			self->ntrev = (int)start;
  1984 	}
  1988 	}
  1985 	if (self->added)
  1989 	if (self->added)
  1986 		ret = PyList_SetSlice(self->added, start - self->length,
  1990 		ret = PyList_SetSlice(self->added, start - self->length,
  1987 				      PyList_GET_SIZE(self->added), NULL);
  1991 		                      PyList_GET_SIZE(self->added), NULL);
  1988 done:
  1992 done:
  1989 	Py_CLEAR(self->headrevs);
  1993 	Py_CLEAR(self->headrevs);
  1990 	return ret;
  1994 	return ret;
  1991 }
  1995 }
  1992 
  1996 
  1996  * slice deletion
  2000  * slice deletion
  1997  * string assignment (extend node->rev mapping)
  2001  * string assignment (extend node->rev mapping)
  1998  * string deletion (shrink node->rev mapping)
  2002  * string deletion (shrink node->rev mapping)
  1999  */
  2003  */
  2000 static int index_assign_subscript(indexObject *self, PyObject *item,
  2004 static int index_assign_subscript(indexObject *self, PyObject *item,
  2001 				  PyObject *value)
  2005                                   PyObject *value)
  2002 {
  2006 {
  2003 	char *node;
  2007 	char *node;
  2004 	long rev;
  2008 	long rev;
  2005 
  2009 
  2006 	if (PySlice_Check(item) && value == NULL)
  2010 	if (PySlice_Check(item) && value == NULL)
  2008 
  2012 
  2009 	if (node_check(item, &node) == -1)
  2013 	if (node_check(item, &node) == -1)
  2010 		return -1;
  2014 		return -1;
  2011 
  2015 
  2012 	if (value == NULL)
  2016 	if (value == NULL)
  2013 		return self->ntinitialized ? nt_delete_node(&self->nt, node) : 0;
  2017 		return self->ntinitialized ? nt_delete_node(&self->nt, node)
       
  2018 		                           : 0;
  2014 	rev = PyInt_AsLong(value);
  2019 	rev = PyInt_AsLong(value);
  2015 	if (rev > INT_MAX || rev < 0) {
  2020 	if (rev > INT_MAX || rev < 0) {
  2016 		if (!PyErr_Occurred())
  2021 		if (!PyErr_Occurred())
  2017 			PyErr_SetString(PyExc_ValueError, "rev out of range");
  2022 			PyErr_SetString(PyExc_ValueError, "rev out of range");
  2018 		return -1;
  2023 		return -1;
  2058 static int index_init(indexObject *self, PyObject *args)
  2063 static int index_init(indexObject *self, PyObject *args)
  2059 {
  2064 {
  2060 	PyObject *data_obj, *inlined_obj;
  2065 	PyObject *data_obj, *inlined_obj;
  2061 	Py_ssize_t size;
  2066 	Py_ssize_t size;
  2062 
  2067 
  2063 	/* Initialize before argument-checking to avoid index_dealloc() crash. */
  2068 	/* Initialize before argument-checking to avoid index_dealloc() crash.
       
  2069 	 */
  2064 	self->raw_length = 0;
  2070 	self->raw_length = 0;
  2065 	self->added = NULL;
  2071 	self->added = NULL;
  2066 	self->cache = NULL;
  2072 	self->cache = NULL;
  2067 	self->data = NULL;
  2073 	self->data = NULL;
  2068 	memset(&self->buf, 0, sizeof(self->buf));
  2074 	memset(&self->buf, 0, sizeof(self->buf));
  2074 
  2080 
  2075 	if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
  2081 	if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
  2076 		return -1;
  2082 		return -1;
  2077 	if (!PyObject_CheckBuffer(data_obj)) {
  2083 	if (!PyObject_CheckBuffer(data_obj)) {
  2078 		PyErr_SetString(PyExc_TypeError,
  2084 		PyErr_SetString(PyExc_TypeError,
  2079 				"data does not support buffer interface");
  2085 		                "data does not support buffer interface");
  2080 		return -1;
  2086 		return -1;
  2081 	}
  2087 	}
  2082 
  2088 
  2083 	if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
  2089 	if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1)
  2084 		return -1;
  2090 		return -1;
  2158 	Py_XDECREF(self->added);
  2164 	Py_XDECREF(self->added);
  2159 	PyObject_Del(self);
  2165 	PyObject_Del(self);
  2160 }
  2166 }
  2161 
  2167 
  2162 static PySequenceMethods index_sequence_methods = {
  2168 static PySequenceMethods index_sequence_methods = {
  2163 	(lenfunc)index_length,   /* sq_length */
  2169     (lenfunc)index_length,      /* sq_length */
  2164 	0,                       /* sq_concat */
  2170     0,                          /* sq_concat */
  2165 	0,                       /* sq_repeat */
  2171     0,                          /* sq_repeat */
  2166 	(ssizeargfunc)index_get, /* sq_item */
  2172     (ssizeargfunc)index_get,    /* sq_item */
  2167 	0,                       /* sq_slice */
  2173     0,                          /* sq_slice */
  2168 	0,                       /* sq_ass_item */
  2174     0,                          /* sq_ass_item */
  2169 	0,                       /* sq_ass_slice */
  2175     0,                          /* sq_ass_slice */
  2170 	(objobjproc)index_contains, /* sq_contains */
  2176     (objobjproc)index_contains, /* sq_contains */
  2171 };
  2177 };
  2172 
  2178 
  2173 static PyMappingMethods index_mapping_methods = {
  2179 static PyMappingMethods index_mapping_methods = {
  2174 	(lenfunc)index_length,                 /* mp_length */
  2180     (lenfunc)index_length,                 /* mp_length */
  2175 	(binaryfunc)index_getitem,             /* mp_subscript */
  2181     (binaryfunc)index_getitem,             /* mp_subscript */
  2176 	(objobjargproc)index_assign_subscript, /* mp_ass_subscript */
  2182     (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
  2177 };
  2183 };
  2178 
  2184 
  2179 static PyMethodDef index_methods[] = {
  2185 static PyMethodDef index_methods[] = {
  2180 	{"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
  2186     {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS,
  2181 	 "return the gca set of the given revs"},
  2187      "return the gca set of the given revs"},
  2182 	{"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
  2188     {"commonancestorsheads", (PyCFunction)index_commonancestorsheads,
  2183 	  METH_VARARGS,
  2189      METH_VARARGS,
  2184 	  "return the heads of the common ancestors of the given revs"},
  2190      "return the heads of the common ancestors of the given revs"},
  2185 	{"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
  2191     {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
  2186 	 "clear the index caches"},
  2192      "clear the index caches"},
  2187 	{"get", (PyCFunction)index_m_get, METH_VARARGS,
  2193     {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"},
  2188 	 "get an index entry"},
  2194     {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS,
  2189 	{"computephasesmapsets", (PyCFunction)compute_phases_map_sets,
  2195      "compute phases"},
  2190 			METH_VARARGS, "compute phases"},
  2196     {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
  2191 	{"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS,
  2197      "reachableroots"},
  2192 		"reachableroots"},
  2198     {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
  2193 	{"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
  2199      "get head revisions"}, /* Can do filtering since 3.2 */
  2194 	 "get head revisions"}, /* Can do filtering since 3.2 */
  2200     {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
  2195 	{"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
  2201      "get filtered head revisions"}, /* Can always do filtering */
  2196 	 "get filtered head revisions"}, /* Can always do filtering */
  2202     {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
  2197 	{"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
  2203      "determine revisions with deltas to reconstruct fulltext"},
  2198 	 "determine revisions with deltas to reconstruct fulltext"},
  2204     {"append", (PyCFunction)index_append, METH_O, "append an index entry"},
  2199 	{"append", (PyCFunction)index_append, METH_O,
  2205     {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
  2200 	 "append an index entry"},
  2206      "match a potentially ambiguous node ID"},
  2201 	{"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
  2207     {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
  2202 	 "match a potentially ambiguous node ID"},
  2208      "find length of shortest hex nodeid of a binary ID"},
  2203 	{"shortest", (PyCFunction)index_shortest, METH_VARARGS,
  2209     {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
  2204 	 "find length of shortest hex nodeid of a binary ID"},
  2210     {NULL} /* Sentinel */
  2205 	{"stats", (PyCFunction)index_stats, METH_NOARGS,
       
  2206 	 "stats for the index"},
       
  2207 	{NULL} /* Sentinel */
       
  2208 };
  2211 };
  2209 
  2212 
  2210 static PyGetSetDef index_getset[] = {
  2213 static PyGetSetDef index_getset[] = {
  2211 	{"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
  2214     {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
  2212 	{NULL} /* Sentinel */
  2215     {NULL} /* Sentinel */
  2213 };
  2216 };
  2214 
  2217 
  2215 static PyTypeObject indexType = {
  2218 static PyTypeObject indexType = {
  2216 	PyVarObject_HEAD_INIT(NULL, 0) /* header */
  2219     PyVarObject_HEAD_INIT(NULL, 0) /* header */
  2217 	"parsers.index",           /* tp_name */
  2220     "parsers.index",               /* tp_name */
  2218 	sizeof(indexObject),       /* tp_basicsize */
  2221     sizeof(indexObject),           /* tp_basicsize */
  2219 	0,                         /* tp_itemsize */
  2222     0,                             /* tp_itemsize */
  2220 	(destructor)index_dealloc, /* tp_dealloc */
  2223     (destructor)index_dealloc,     /* tp_dealloc */
  2221 	0,                         /* tp_print */
  2224     0,                             /* tp_print */
  2222 	0,                         /* tp_getattr */
  2225     0,                             /* tp_getattr */
  2223 	0,                         /* tp_setattr */
  2226     0,                             /* tp_setattr */
  2224 	0,                         /* tp_compare */
  2227     0,                             /* tp_compare */
  2225 	0,                         /* tp_repr */
  2228     0,                             /* tp_repr */
  2226 	0,                         /* tp_as_number */
  2229     0,                             /* tp_as_number */
  2227 	&index_sequence_methods,   /* tp_as_sequence */
  2230     &index_sequence_methods,       /* tp_as_sequence */
  2228 	&index_mapping_methods,    /* tp_as_mapping */
  2231     &index_mapping_methods,        /* tp_as_mapping */
  2229 	0,                         /* tp_hash */
  2232     0,                             /* tp_hash */
  2230 	0,                         /* tp_call */
  2233     0,                             /* tp_call */
  2231 	0,                         /* tp_str */
  2234     0,                             /* tp_str */
  2232 	0,                         /* tp_getattro */
  2235     0,                             /* tp_getattro */
  2233 	0,                         /* tp_setattro */
  2236     0,                             /* tp_setattro */
  2234 	0,                         /* tp_as_buffer */
  2237     0,                             /* tp_as_buffer */
  2235 	Py_TPFLAGS_DEFAULT,        /* tp_flags */
  2238     Py_TPFLAGS_DEFAULT,            /* tp_flags */
  2236 	"revlog index",            /* tp_doc */
  2239     "revlog index",                /* tp_doc */
  2237 	0,                         /* tp_traverse */
  2240     0,                             /* tp_traverse */
  2238 	0,                         /* tp_clear */
  2241     0,                             /* tp_clear */
  2239 	0,                         /* tp_richcompare */
  2242     0,                             /* tp_richcompare */
  2240 	0,                         /* tp_weaklistoffset */
  2243     0,                             /* tp_weaklistoffset */
  2241 	0,                         /* tp_iter */
  2244     0,                             /* tp_iter */
  2242 	0,                         /* tp_iternext */
  2245     0,                             /* tp_iternext */
  2243 	index_methods,             /* tp_methods */
  2246     index_methods,                 /* tp_methods */
  2244 	0,                         /* tp_members */
  2247     0,                             /* tp_members */
  2245 	index_getset,              /* tp_getset */
  2248     index_getset,                  /* tp_getset */
  2246 	0,                         /* tp_base */
  2249     0,                             /* tp_base */
  2247 	0,                         /* tp_dict */
  2250     0,                             /* tp_dict */
  2248 	0,                         /* tp_descr_get */
  2251     0,                             /* tp_descr_get */
  2249 	0,                         /* tp_descr_set */
  2252     0,                             /* tp_descr_set */
  2250 	0,                         /* tp_dictoffset */
  2253     0,                             /* tp_dictoffset */
  2251 	(initproc)index_init,      /* tp_init */
  2254     (initproc)index_init,          /* tp_init */
  2252 	0,                         /* tp_alloc */
  2255     0,                             /* tp_alloc */
  2253 };
  2256 };
  2254 
  2257 
  2255 /*
  2258 /*
  2256  * returns a tuple of the form (index, index, cache) with elements as
  2259  * returns a tuple of the form (index, index, cache) with elements as
  2257  * follows:
  2260  * follows:
  2305  */
  2308  */
  2306 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
  2309 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
  2307 
  2310 
  2308 struct rustlazyancestorsObjectStruct {
  2311 struct rustlazyancestorsObjectStruct {
  2309 	PyObject_HEAD
  2312 	PyObject_HEAD
  2310 	/* Type-specific fields go here. */
  2313 	    /* Type-specific fields go here. */
  2311 	indexObject *index;    /* Ref kept to avoid GC'ing the index */
  2314 	    indexObject *index; /* Ref kept to avoid GC'ing the index */
  2312 	void *iter;        /* Rust iterator */
  2315 	void *iter;             /* Rust iterator */
  2313 };
  2316 };
  2314 
  2317 
  2315 /* FFI exposed from Rust code */
  2318 /* FFI exposed from Rust code */
  2316 rustlazyancestorsObject *rustlazyancestors_init(
  2319 rustlazyancestorsObject *
  2317 	indexObject *index,
  2320 rustlazyancestors_init(indexObject *index,
  2318 	/* to pass index_get_parents() */
  2321                        /* to pass index_get_parents() */
  2319 	int (*)(indexObject *, Py_ssize_t, int*, int),
  2322                        int (*)(indexObject *, Py_ssize_t, int *, int),
  2320 	/* intrevs vector */
  2323                        /* intrevs vector */
  2321 	Py_ssize_t initrevslen, long *initrevs,
  2324                        Py_ssize_t initrevslen, long *initrevs, long stoprev,
  2322 	long stoprev,
  2325                        int inclusive);
  2323 	int inclusive);
       
  2324 void rustlazyancestors_drop(rustlazyancestorsObject *self);
  2326 void rustlazyancestors_drop(rustlazyancestorsObject *self);
  2325 int rustlazyancestors_next(rustlazyancestorsObject *self);
  2327 int rustlazyancestors_next(rustlazyancestorsObject *self);
  2326 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
  2328 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
  2327 
  2329 
  2328 /* CPython instance methods */
  2330 /* CPython instance methods */
  2329 static int rustla_init(rustlazyancestorsObject *self,
  2331 static int rustla_init(rustlazyancestorsObject *self, PyObject *args)
  2330                        PyObject *args) {
  2332 {
  2331 	PyObject *initrevsarg = NULL;
  2333 	PyObject *initrevsarg = NULL;
  2332 	PyObject *inclusivearg = NULL;
  2334 	PyObject *inclusivearg = NULL;
  2333 	long stoprev = 0;
  2335 	long stoprev = 0;
  2334 	long *initrevs = NULL;
  2336 	long *initrevs = NULL;
  2335 	int inclusive = 0;
  2337 	int inclusive = 0;
  2336 	Py_ssize_t i;
  2338 	Py_ssize_t i;
  2337 
  2339 
  2338 	indexObject *index;
  2340 	indexObject *index;
  2339 	if (!PyArg_ParseTuple(args, "O!O!lO!",
  2341 	if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type,
  2340 			      &indexType, &index,
  2342 	                      &initrevsarg, &stoprev, &PyBool_Type,
  2341                               &PyList_Type, &initrevsarg,
  2343 	                      &inclusivearg))
  2342                               &stoprev,
  2344 		return -1;
  2343                               &PyBool_Type, &inclusivearg))
       
  2344 	return -1;
       
  2345 
  2345 
  2346 	Py_INCREF(index);
  2346 	Py_INCREF(index);
  2347 	self->index = index;
  2347 	self->index = index;
  2348 
  2348 
  2349 	if (inclusivearg == Py_True)
  2349 	if (inclusivearg == Py_True)
  2350 		inclusive = 1;
  2350 		inclusive = 1;
  2351 
  2351 
  2352 	Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
  2352 	Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
  2353 
  2353 
  2354 	initrevs = (long*)calloc(linit, sizeof(long));
  2354 	initrevs = (long *)calloc(linit, sizeof(long));
  2355 
  2355 
  2356 	if (initrevs == NULL) {
  2356 	if (initrevs == NULL) {
  2357 		PyErr_NoMemory();
  2357 		PyErr_NoMemory();
  2358 		goto bail;
  2358 		goto bail;
  2359 	}
  2359 	}
  2360 
  2360 
  2361 	for (i=0; i<linit; i++) {
  2361 	for (i = 0; i < linit; i++) {
  2362 		initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
  2362 		initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
  2363 	}
  2363 	}
  2364 	if (PyErr_Occurred())
  2364 	if (PyErr_Occurred())
  2365 		goto bail;
  2365 		goto bail;
  2366 
  2366 
  2367 	self->iter = rustlazyancestors_init(index,
  2367 	self->iter = rustlazyancestors_init(index, index_get_parents, linit,
  2368 		                            index_get_parents,
  2368 	                                    initrevs, stoprev, inclusive);
  2369 		                            linit, initrevs,
       
  2370 		                            stoprev, inclusive);
       
  2371 	if (self->iter == NULL) {
  2369 	if (self->iter == NULL) {
  2372 		/* if this is because of GraphError::ParentOutOfRange
  2370 		/* if this is because of GraphError::ParentOutOfRange
  2373 		 * index_get_parents() has already set the proper ValueError */
  2371 		 * index_get_parents() has already set the proper ValueError */
  2374 		goto bail;
  2372 		goto bail;
  2375 	}
  2373 	}
  2389 		rustlazyancestors_drop(self->iter);
  2387 		rustlazyancestors_drop(self->iter);
  2390 	}
  2388 	}
  2391 	PyObject_Del(self);
  2389 	PyObject_Del(self);
  2392 }
  2390 }
  2393 
  2391 
  2394 static PyObject *rustla_next(rustlazyancestorsObject *self) {
  2392 static PyObject *rustla_next(rustlazyancestorsObject *self)
       
  2393 {
  2395 	int res = rustlazyancestors_next(self->iter);
  2394 	int res = rustlazyancestors_next(self->iter);
  2396 	if (res == -1) {
  2395 	if (res == -1) {
  2397 		/* Setting an explicit exception seems unnecessary
  2396 		/* Setting an explicit exception seems unnecessary
  2398 		 * as examples from Python source code (Objects/rangeobjets.c and
  2397 		 * as examples from Python source code (Objects/rangeobjets.c
  2399 		 * Modules/_io/stringio.c) seem to demonstrate.
  2398 		 * and Modules/_io/stringio.c) seem to demonstrate.
  2400 		 */
  2399 		 */
  2401 		return NULL;
  2400 		return NULL;
  2402 	}
  2401 	}
  2403 	return PyInt_FromLong(res);
  2402 	return PyInt_FromLong(res);
  2404 }
  2403 }
  2405 
  2404 
  2406 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev) {
  2405 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev)
       
  2406 {
  2407 	if (!(PyInt_Check(rev))) {
  2407 	if (!(PyInt_Check(rev))) {
  2408 		return 0;
  2408 		return 0;
  2409 	}
  2409 	}
  2410 	return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev));
  2410 	return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev));
  2411 }
  2411 }
  2412 
  2412 
  2413 static PySequenceMethods rustla_sequence_methods = {
  2413 static PySequenceMethods rustla_sequence_methods = {
  2414 	0,                       /* sq_length */
  2414     0,                           /* sq_length */
  2415 	0,                       /* sq_concat */
  2415     0,                           /* sq_concat */
  2416 	0,                       /* sq_repeat */
  2416     0,                           /* sq_repeat */
  2417 	0,                       /* sq_item */
  2417     0,                           /* sq_item */
  2418 	0,                       /* sq_slice */
  2418     0,                           /* sq_slice */
  2419 	0,                       /* sq_ass_item */
  2419     0,                           /* sq_ass_item */
  2420 	0,                       /* sq_ass_slice */
  2420     0,                           /* sq_ass_slice */
  2421 	(objobjproc)rustla_contains, /* sq_contains */
  2421     (objobjproc)rustla_contains, /* sq_contains */
  2422 };
  2422 };
  2423 
  2423 
  2424 static PyTypeObject rustlazyancestorsType = {
  2424 static PyTypeObject rustlazyancestorsType = {
  2425 	PyVarObject_HEAD_INIT(NULL, 0) /* header */
  2425     PyVarObject_HEAD_INIT(NULL, 0)                  /* header */
  2426 	"parsers.rustlazyancestors",           /* tp_name */
  2426     "parsers.rustlazyancestors",                    /* tp_name */
  2427 	sizeof(rustlazyancestorsObject),       /* tp_basicsize */
  2427     sizeof(rustlazyancestorsObject),                /* tp_basicsize */
  2428 	0,                         /* tp_itemsize */
  2428     0,                                              /* tp_itemsize */
  2429 	(destructor)rustla_dealloc, /* tp_dealloc */
  2429     (destructor)rustla_dealloc,                     /* tp_dealloc */
  2430 	0,                         /* tp_print */
  2430     0,                                              /* tp_print */
  2431 	0,                         /* tp_getattr */
  2431     0,                                              /* tp_getattr */
  2432 	0,                         /* tp_setattr */
  2432     0,                                              /* tp_setattr */
  2433 	0,                         /* tp_compare */
  2433     0,                                              /* tp_compare */
  2434 	0,                         /* tp_repr */
  2434     0,                                              /* tp_repr */
  2435 	0,                         /* tp_as_number */
  2435     0,                                              /* tp_as_number */
  2436 	&rustla_sequence_methods,  /* tp_as_sequence */
  2436     &rustla_sequence_methods,                       /* tp_as_sequence */
  2437 	0,                         /* tp_as_mapping */
  2437     0,                                              /* tp_as_mapping */
  2438 	0,                         /* tp_hash */
  2438     0,                                              /* tp_hash */
  2439 	0,                         /* tp_call */
  2439     0,                                              /* tp_call */
  2440 	0,                         /* tp_str */
  2440     0,                                              /* tp_str */
  2441 	0,                         /* tp_getattro */
  2441     0,                                              /* tp_getattro */
  2442 	0,                         /* tp_setattro */
  2442     0,                                              /* tp_setattro */
  2443 	0,                         /* tp_as_buffer */
  2443     0,                                              /* tp_as_buffer */
  2444 	Py_TPFLAGS_DEFAULT,        /* tp_flags */
  2444     Py_TPFLAGS_DEFAULT,                             /* tp_flags */
  2445 	"Iterator over ancestors, implemented in Rust", /* tp_doc */
  2445     "Iterator over ancestors, implemented in Rust", /* tp_doc */
  2446 	0,                         /* tp_traverse */
  2446     0,                                              /* tp_traverse */
  2447 	0,                         /* tp_clear */
  2447     0,                                              /* tp_clear */
  2448 	0,                         /* tp_richcompare */
  2448     0,                                              /* tp_richcompare */
  2449 	0,                         /* tp_weaklistoffset */
  2449     0,                                              /* tp_weaklistoffset */
  2450 	0,                         /* tp_iter */
  2450     0,                                              /* tp_iter */
  2451 	(iternextfunc)rustla_next, /* tp_iternext */
  2451     (iternextfunc)rustla_next,                      /* tp_iternext */
  2452 	0,                         /* tp_methods */
  2452     0,                                              /* tp_methods */
  2453 	0,                         /* tp_members */
  2453     0,                                              /* tp_members */
  2454 	0,                         /* tp_getset */
  2454     0,                                              /* tp_getset */
  2455 	0,                         /* tp_base */
  2455     0,                                              /* tp_base */
  2456 	0,                         /* tp_dict */
  2456     0,                                              /* tp_dict */
  2457 	0,                         /* tp_descr_get */
  2457     0,                                              /* tp_descr_get */
  2458 	0,                         /* tp_descr_set */
  2458     0,                                              /* tp_descr_set */
  2459 	0,                         /* tp_dictoffset */
  2459     0,                                              /* tp_dictoffset */
  2460 	(initproc)rustla_init,     /* tp_init */
  2460     (initproc)rustla_init,                          /* tp_init */
  2461 	0,                         /* tp_alloc */
  2461     0,                                              /* tp_alloc */
  2462 };
  2462 };
  2463 #endif /* WITH_RUST */
  2463 #endif /* WITH_RUST */
  2464 
  2464 
  2465 void revlog_module_init(PyObject *mod)
  2465 void revlog_module_init(PyObject *mod)
  2466 {
  2466 {
  2475 		return;
  2475 		return;
  2476 	Py_INCREF(&nodetreeType);
  2476 	Py_INCREF(&nodetreeType);
  2477 	PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
  2477 	PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType);
  2478 
  2478 
  2479 	if (!nullentry) {
  2479 	if (!nullentry) {
  2480 		nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
  2480 		nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0,
  2481 					  -1, -1, -1, -1, nullid, 20);
  2481 		                          0, -1, -1, -1, -1, nullid, 20);
  2482 	}
  2482 	}
  2483 	if (nullentry)
  2483 	if (nullentry)
  2484 		PyObject_GC_UnTrack(nullentry);
  2484 		PyObject_GC_UnTrack(nullentry);
  2485 
  2485 
  2486 #ifdef WITH_RUST
  2486 #ifdef WITH_RUST
  2487 	rustlazyancestorsType.tp_new = PyType_GenericNew;
  2487 	rustlazyancestorsType.tp_new = PyType_GenericNew;
  2488 	if (PyType_Ready(&rustlazyancestorsType) < 0)
  2488 	if (PyType_Ready(&rustlazyancestorsType) < 0)
  2489 		return;
  2489 		return;
  2490 	Py_INCREF(&rustlazyancestorsType);
  2490 	Py_INCREF(&rustlazyancestorsType);
  2491 	PyModule_AddObject(mod, "rustlazyancestors",
  2491 	PyModule_AddObject(mod, "rustlazyancestors",
  2492 		(PyObject *)&rustlazyancestorsType);
  2492 	                   (PyObject *)&rustlazyancestorsType);
  2493 #endif
  2493 #endif
  2494 
  2494 }
  2495 }