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