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
--- a/mercurial/cext/parsers.c Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/cext/parsers.c Fri Jul 20 08:10:32 2018 -0700
@@ -713,7 +713,7 @@
void manifest_module_init(PyObject *mod);
void revlog_module_init(PyObject *mod);
-static const int version = 6;
+static const int version = 7;
static void module_init(PyObject *mod)
{
--- a/mercurial/cext/revlog.c Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/cext/revlog.c Fri Jul 20 08:10:32 2018 -0700
@@ -77,8 +77,8 @@
static Py_ssize_t index_length(const indexObject *self)
{
if (self->added == NULL)
- return self->length;
- return self->length + PyList_GET_SIZE(self->added);
+ return self->length - 1;
+ return self->length + PyList_GET_SIZE(self->added) - 1;
}
static PyObject *nullentry;
@@ -155,7 +155,7 @@
int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
const char *c_node_id;
const char *data;
- Py_ssize_t length = index_length(self);
+ Py_ssize_t length = index_length(self) + 1;
PyObject *entry;
if (pos == -1 || pos == length - 1) {
@@ -225,7 +225,7 @@
*/
static const char *index_node(indexObject *self, Py_ssize_t pos)
{
- Py_ssize_t length = index_length(self);
+ Py_ssize_t length = index_length(self) + 1;
const char *data;
if (pos == length - 1 || pos == -1)
@@ -285,7 +285,7 @@
if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1)
return NULL;
- len = index_length(self);
+ len = index_length(self) + 1;
if (self->added == NULL) {
self->added = PyList_New(0);
@@ -435,7 +435,7 @@
{
PyObject *iter = NULL;
PyObject *iter_item = NULL;
- Py_ssize_t min_idx = index_length(self) + 1;
+ Py_ssize_t min_idx = index_length(self) + 2;
long iter_item_long;
if (PyList_GET_SIZE(list) != 0) {
@@ -477,7 +477,7 @@
PyObject *reachable = NULL;
PyObject *val;
- Py_ssize_t len = index_length(self) - 1;
+ Py_ssize_t len = index_length(self);
long revnum;
Py_ssize_t k;
Py_ssize_t i;
@@ -629,7 +629,7 @@
PyObject *phaseset = NULL;
PyObject *phasessetlist = NULL;
PyObject *rev = NULL;
- Py_ssize_t len = index_length(self) - 1;
+ Py_ssize_t len = index_length(self);
Py_ssize_t numphase = 0;
Py_ssize_t minrevallphases = 0;
Py_ssize_t minrevphase = 0;
@@ -740,7 +740,7 @@
}
}
- len = index_length(self) - 1;
+ len = index_length(self);
heads = PyList_New(0);
if (heads == NULL)
goto bail;
@@ -844,7 +844,7 @@
int stoprev, iterrev, baserev = -1;
int stopped;
PyObject *chain = NULL, *result = NULL;
- const Py_ssize_t length = index_length(self);
+ const Py_ssize_t length = index_length(self) + 1;
if (!PyArg_ParseTuple(args, "iOi", &rev, &stoparg, &generaldelta)) {
return NULL;
@@ -1098,7 +1098,7 @@
return -1;
}
self->ntlength = 1;
- self->ntrev = (int)index_length(self) - 1;
+ self->ntrev = (int)index_length(self);
self->ntlookups = 1;
self->ntmisses = 0;
if (nt_insert(self, nullid, -1) == -1) {
@@ -1393,7 +1393,7 @@
if (PyInt_Check(value)) {
long rev = PyInt_AS_LONG(value);
- return rev >= -1 && rev < index_length(self);
+ return rev >= -1 && rev < index_length(self) + 1;
}
if (node_check(value, &node) == -1)
@@ -1673,7 +1673,7 @@
revs = PyMem_Malloc(argcount * sizeof(*revs));
if (argcount > 0 && revs == NULL)
return PyErr_NoMemory();
- len = index_length(self) - 1;
+ len = index_length(self);
for (i = 0; i < argcount; i++) {
static const int capacity = 24;
@@ -1795,7 +1795,7 @@
static int index_slice_del(indexObject *self, PyObject *item)
{
Py_ssize_t start, stop, step, slicelength;
- Py_ssize_t length = index_length(self);
+ Py_ssize_t length = index_length(self) + 1;
int ret = 0;
/* Argument changed from PySliceObject* to PyObject* in Python 3. */
--- a/mercurial/policy.py Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/policy.py Fri Jul 20 08:10:32 2018 -0700
@@ -69,7 +69,7 @@
(r'cext', r'bdiff'): 3,
(r'cext', r'mpatch'): 1,
(r'cext', r'osutil'): 4,
- (r'cext', r'parsers'): 6,
+ (r'cext', r'parsers'): 7,
}
# map import request to other package or module
--- a/mercurial/pure/parsers.py Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/pure/parsers.py Fri Jul 20 08:10:32 2018 -0700
@@ -39,7 +39,7 @@
class BaseIndexObject(object):
def __len__(self):
- return self._lgt + len(self._extra) + 1
+ return self._lgt + len(self._extra)
def append(self, tup):
self._extra.append(tup)
@@ -47,12 +47,12 @@
def _fix_index(self, i):
if not isinstance(i, int):
raise TypeError("expecting int indexes")
- if i < 0 or i >= len(self):
+ if i < 0 or i >= len(self) + 1:
raise IndexError
return i
def __getitem__(self, i):
- if i == -1 or i == len(self) - 1:
+ if i == -1 or i == len(self):
return (0, 0, 0, -1, -1, -1, -1, nullid)
i = self._fix_index(i)
if i >= self._lgt:
--- a/mercurial/repoview.py Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/repoview.py Fri Jul 20 08:10:32 2018 -0700
@@ -210,7 +210,7 @@
unfichangelog = unfi.changelog
# bypass call to changelog.method
unfiindex = unfichangelog.index
- unfilen = len(unfiindex) - 1
+ unfilen = len(unfiindex)
unfinode = unfiindex[unfilen - 1][7]
revs = filterrevs(unfi, self.filtername, self._visibilityexceptions)
--- a/mercurial/revlog.py Wed Aug 01 10:57:14 2018 -0700
+++ b/mercurial/revlog.py Fri Jul 20 08:10:32 2018 -0700
@@ -791,10 +791,8 @@
indexformatv0_unpack = indexformatv0.unpack
class revlogoldindex(list):
- def __len__(self):
- return list.__len__(self) + 1
def __getitem__(self, i):
- if i == -1 or i == len(self) - 1:
+ if i == -1 or i == len(self):
return (0, 0, 0, -1, -1, -1, -1, nullid)
return list.__getitem__(self, i)
@@ -1066,11 +1064,11 @@
yield fp
def tip(self):
- return self.node(len(self.index) - 2)
+ return self.node(len(self.index) - 1)
def __contains__(self, rev):
return 0 <= rev < len(self)
def __len__(self):
- return len(self.index) - 1
+ return len(self.index)
def __iter__(self):
return iter(pycompat.xrange(len(self)))
def revs(self, start=0, stop=None):
@@ -1139,7 +1137,7 @@
i = self.index
p = self._nodepos
if p is None:
- p = len(i) - 2
+ p = len(i) - 1
else:
assert p < len(i)
for r in pycompat.xrange(p, -1, -1):