comparison mercurial/cext/revlog.c @ 38851:781b2720d2ac

index: don't include nullid in len() I suspect the reason the nullid is in the index in the last position is that it lets index[i] for regular revision number, even when index was just a regular Python list. An alternative solution would have been to reserve revision number 0 for the null revision. I don't know why that wasn't done. Now that we have classes backing the index, we can easily make index[-1] get the nullid without having to put it last in the list and including it in the len(). This patch just hides the nullid -- it will still be accessible at index[len(index)]. I realize that this will be annoying when checking out across this commit for debugging (including bisection). Differential Revision: https://phab.mercurial-scm.org/D4022
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 20 Jul 2018 08:10:32 -0700
parents 6104b203bec8
children a3dacabd476b
comparison
equal deleted inserted replaced
38850:6104b203bec8 38851:781b2720d2ac
75 } indexObject; 75 } indexObject;
76 76
77 static Py_ssize_t index_length(const indexObject *self) 77 static Py_ssize_t index_length(const indexObject *self)
78 { 78 {
79 if (self->added == NULL) 79 if (self->added == NULL)
80 return self->length; 80 return self->length - 1;
81 return self->length + PyList_GET_SIZE(self->added); 81 return self->length + PyList_GET_SIZE(self->added) - 1;
82 } 82 }
83 83
84 static PyObject *nullentry; 84 static PyObject *nullentry;
85 static const char nullid[20]; 85 static const char nullid[20];
86 86
153 { 153 {
154 uint64_t offset_flags; 154 uint64_t offset_flags;
155 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; 155 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
156 const char *c_node_id; 156 const char *c_node_id;
157 const char *data; 157 const char *data;
158 Py_ssize_t length = index_length(self); 158 Py_ssize_t length = index_length(self) + 1;
159 PyObject *entry; 159 PyObject *entry;
160 160
161 if (pos == -1 || pos == length - 1) { 161 if (pos == -1 || pos == length - 1) {
162 Py_INCREF(nullentry); 162 Py_INCREF(nullentry);
163 return nullentry; 163 return nullentry;
223 /* 223 /*
224 * Return the 20-byte SHA of the node corresponding to the given rev. 224 * Return the 20-byte SHA of the node corresponding to the given rev.
225 */ 225 */
226 static const char *index_node(indexObject *self, Py_ssize_t pos) 226 static const char *index_node(indexObject *self, Py_ssize_t pos)
227 { 227 {
228 Py_ssize_t length = index_length(self); 228 Py_ssize_t length = index_length(self) + 1;
229 const char *data; 229 const char *data;
230 230
231 if (pos == length - 1 || pos == -1) 231 if (pos == length - 1 || pos == -1)
232 return nullid; 232 return nullid;
233 233
283 } 283 }
284 284
285 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1) 285 if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
286 return NULL; 286 return NULL;
287 287
288 len = index_length(self); 288 len = index_length(self) + 1;
289 289
290 if (self->added == NULL) { 290 if (self->added == NULL) {
291 self->added = PyList_New(0); 291 self->added = PyList_New(0);
292 if (self->added == NULL) 292 if (self->added == NULL)
293 return NULL; 293 return NULL;
433 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list, 433 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
434 Py_ssize_t marker, char *phases) 434 Py_ssize_t marker, char *phases)
435 { 435 {
436 PyObject *iter = NULL; 436 PyObject *iter = NULL;
437 PyObject *iter_item = NULL; 437 PyObject *iter_item = NULL;
438 Py_ssize_t min_idx = index_length(self) + 1; 438 Py_ssize_t min_idx = index_length(self) + 2;
439 long iter_item_long; 439 long iter_item_long;
440 440
441 if (PyList_GET_SIZE(list) != 0) { 441 if (PyList_GET_SIZE(list) != 0) {
442 iter = PyObject_GetIter(list); 442 iter = PyObject_GetIter(list);
443 if (iter == NULL) 443 if (iter == NULL)
475 PyObject *heads = NULL; 475 PyObject *heads = NULL;
476 PyObject *roots = NULL; 476 PyObject *roots = NULL;
477 PyObject *reachable = NULL; 477 PyObject *reachable = NULL;
478 478
479 PyObject *val; 479 PyObject *val;
480 Py_ssize_t len = index_length(self) - 1; 480 Py_ssize_t len = index_length(self);
481 long revnum; 481 long revnum;
482 Py_ssize_t k; 482 Py_ssize_t k;
483 Py_ssize_t i; 483 Py_ssize_t i;
484 Py_ssize_t l; 484 Py_ssize_t l;
485 int r; 485 int r;
627 PyObject *phasessize = NULL; 627 PyObject *phasessize = NULL;
628 PyObject *phaseroots = NULL; 628 PyObject *phaseroots = NULL;
629 PyObject *phaseset = NULL; 629 PyObject *phaseset = NULL;
630 PyObject *phasessetlist = NULL; 630 PyObject *phasessetlist = NULL;
631 PyObject *rev = NULL; 631 PyObject *rev = NULL;
632 Py_ssize_t len = index_length(self) - 1; 632 Py_ssize_t len = index_length(self);
633 Py_ssize_t numphase = 0; 633 Py_ssize_t numphase = 0;
634 Py_ssize_t minrevallphases = 0; 634 Py_ssize_t minrevallphases = 0;
635 Py_ssize_t minrevphase = 0; 635 Py_ssize_t minrevphase = 0;
636 Py_ssize_t i = 0; 636 Py_ssize_t i = 0;
637 char *phases = NULL; 637 char *phases = NULL;
738 "filteredrevs has no attribute __contains__"); 738 "filteredrevs has no attribute __contains__");
739 goto bail; 739 goto bail;
740 } 740 }
741 } 741 }
742 742
743 len = index_length(self) - 1; 743 len = index_length(self);
744 heads = PyList_New(0); 744 heads = PyList_New(0);
745 if (heads == NULL) 745 if (heads == NULL)
746 goto bail; 746 goto bail;
747 if (len == 0) { 747 if (len == 0) {
748 PyObject *nullid = PyInt_FromLong(-1); 748 PyObject *nullid = PyInt_FromLong(-1);
842 int rev, generaldelta; 842 int rev, generaldelta;
843 PyObject *stoparg; 843 PyObject *stoparg;
844 int stoprev, iterrev, baserev = -1; 844 int stoprev, iterrev, baserev = -1;
845 int stopped; 845 int stopped;
846 PyObject *chain = NULL, *result = NULL; 846 PyObject *chain = NULL, *result = NULL;
847 const Py_ssize_t length = index_length(self); 847 const Py_ssize_t length = index_length(self) + 1;
848 848
849 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) { 849 if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
850 return NULL; 850 return NULL;
851 } 851 }
852 852
1096 if (self->nt == NULL) { 1096 if (self->nt == NULL) {
1097 PyErr_NoMemory(); 1097 PyErr_NoMemory();
1098 return -1; 1098 return -1;
1099 } 1099 }
1100 self->ntlength = 1; 1100 self->ntlength = 1;
1101 self->ntrev = (int)index_length(self) - 1; 1101 self->ntrev = (int)index_length(self);
1102 self->ntlookups = 1; 1102 self->ntlookups = 1;
1103 self->ntmisses = 0; 1103 self->ntmisses = 0;
1104 if (nt_insert(self, nullid, -1) == -1) { 1104 if (nt_insert(self, nullid, -1) == -1) {
1105 free(self->nt); 1105 free(self->nt);
1106 self->nt = NULL; 1106 self->nt = NULL;
1391 { 1391 {
1392 char *node; 1392 char *node;
1393 1393
1394 if (PyInt_Check(value)) { 1394 if (PyInt_Check(value)) {
1395 long rev = PyInt_AS_LONG(value); 1395 long rev = PyInt_AS_LONG(value);
1396 return rev >= -1 && rev < index_length(self); 1396 return rev >= -1 && rev < index_length(self) + 1;
1397 } 1397 }
1398 1398
1399 if (node_check(value, &node) == -1) 1399 if (node_check(value, &node) == -1)
1400 return -1; 1400 return -1;
1401 1401
1671 1671
1672 argcount = PySequence_Length(args); 1672 argcount = PySequence_Length(args);
1673 revs = PyMem_Malloc(argcount * sizeof(*revs)); 1673 revs = PyMem_Malloc(argcount * sizeof(*revs));
1674 if (argcount > 0 && revs == NULL) 1674 if (argcount > 0 && revs == NULL)
1675 return PyErr_NoMemory(); 1675 return PyErr_NoMemory();
1676 len = index_length(self) - 1; 1676 len = index_length(self);
1677 1677
1678 for (i = 0; i < argcount; i++) { 1678 for (i = 0; i < argcount; i++) {
1679 static const int capacity = 24; 1679 static const int capacity = 24;
1680 PyObject *obj = PySequence_GetItem(args, i); 1680 PyObject *obj = PySequence_GetItem(args, i);
1681 bitmask x; 1681 bitmask x;
1793 * range, but exclude the sentinel nullid entry. 1793 * range, but exclude the sentinel nullid entry.
1794 */ 1794 */
1795 static int index_slice_del(indexObject *self, PyObject *item) 1795 static int index_slice_del(indexObject *self, PyObject *item)
1796 { 1796 {
1797 Py_ssize_t start, stop, step, slicelength; 1797 Py_ssize_t start, stop, step, slicelength;
1798 Py_ssize_t length = index_length(self); 1798 Py_ssize_t length = index_length(self) + 1;
1799 int ret = 0; 1799 int ret = 0;
1800 1800
1801 /* Argument changed from PySliceObject* to PyObject* in Python 3. */ 1801 /* Argument changed from PySliceObject* to PyObject* in Python 3. */
1802 #ifdef IS_PY3K 1802 #ifdef IS_PY3K
1803 if (PySlice_GetIndicesEx(item, length, 1803 if (PySlice_GetIndicesEx(item, length,