revlog: add a magic null revision to our index
We expand our index by one entry so that index[nullrev] points to a
unique entry, the null revision. This naturally eliminates numerous
extra tests in the performance-sensitive index access functions, most
of which are now trivial again.
Adding new entries is now done with insert(-1, e) rather than
append(e).
--- a/mercurial/bundlerepo.py Mon Jul 23 20:44:08 2007 -0500
+++ b/mercurial/bundlerepo.py Mon Jul 23 20:44:08 2007 -0500
@@ -58,13 +58,10 @@
if not prev:
prev = p1
# start, size, base is not used, link, p1, p2, delta ref
- if self.version == revlog.REVLOGV0:
- e = (start, size, None, link, p1, p2, node)
- else:
- e = (revlog.offset_type(start, 0), size, -1, None, link,
- self.rev(p1), self.rev(p2), node)
+ e = (revlog.offset_type(start, 0), size, -1, None, link,
+ self.rev(p1), self.rev(p2), node)
self.basemap[n] = prev
- self.index.append(e)
+ self.index.insert(-1, e)
self.nodemap[node] = n
prev = node
n += 1
--- a/mercurial/revlog.py Mon Jul 23 20:44:08 2007 -0500
+++ b/mercurial/revlog.py Mon Jul 23 20:44:08 2007 -0500
@@ -235,6 +235,8 @@
self.p.index[pos] = item
def __delitem__(self, pos):
del self.p.index[pos]
+ def insert(self, pos, e):
+ self.p.index.insert(pos, e)
def append(self, e):
self.p.index.append(e)
@@ -451,6 +453,8 @@
self._io = revlogoldio()
if i:
self.index, self.nodemap = self._io.parseindex(f, st, self._inline())
+ # add the magic null revision at -1
+ self.index.append((0, 0, 0, -1, -1, -1, -1, nullid))
def _loadindex(self, start, end):
"""load a block of indexes all at once from the lazy parser"""
@@ -472,38 +476,28 @@
def _inline(self): return self.version & REVLOGNGINLINEDATA
- def tip(self): return self.node(len(self.index) - 1)
- def count(self): return len(self.index)
+ def tip(self): return self.node(len(self.index) - 2)
+ def count(self): return len(self.index) - 1
def node(self, rev):
- return rev == nullrev and nullid or self.index[rev][7]
+ return self.index[rev][7]
def rev(self, node):
try:
return self.nodemap[node]
except KeyError:
raise LookupError(_('%s: no node %s') % (self.indexfile, hex(node)))
def linkrev(self, node):
- return (node == nullid) and nullrev or self.index[self.rev(node)][4]
+ return self.index[self.rev(node)][4]
def parents(self, node):
- if node == nullid: return (nullid, nullid)
- r = self.rev(node)
- d = self.index[r][5:7]
+ d = self.index[self.rev(node)][5:7]
return (self.node(d[0]), self.node(d[1]))
def parentrevs(self, rev):
- if rev == nullrev:
- return (nullrev, nullrev)
- d = self.index[rev][5:7]
- return d
+ return self.index[rev][5:7]
def start(self, rev):
- if rev == nullrev:
- return 0
return getoffset(self.index[rev][0])
-
def end(self, rev): return self.start(rev) + self.length(rev)
def size(self, rev):
"""return the length of the uncompressed text for a given revision"""
- if rev == nullrev:
- return 0
l = self.index[rev][2]
if l >= 0:
return l
@@ -532,15 +526,9 @@
"""
def length(self, rev):
- if rev == nullrev:
- return 0
- else:
- return self.index[rev][1]
+ return self.index[rev][1]
def base(self, rev):
- if (rev == nullrev):
- return nullrev
- else:
- return self.index[rev][3]
+ return self.index[rev][3]
def reachable(self, node, stop=None):
"""return a hash of all nodes ancestral to a given node, including
@@ -1029,7 +1017,7 @@
e = (offset_type(offset, 0), l, len(text),
base, link, self.rev(p1), self.rev(p2), node)
- self.index.append(e)
+ self.index.insert(-1, e)
self.nodemap[node] = n
if self.version == REVLOGV0:
@@ -1049,7 +1037,7 @@
ifh.seek(0, 2)
transaction.add(self.indexfile, ifh.tell(), self.count() - 1)
- if len(self.index) == 1 and self.version != REVLOGV0:
+ if self.count() == 1 and self.version != REVLOGV0:
l = struct.pack(versionformat, self.version)
ifh.write(l)
entry = entry[4:]
@@ -1193,7 +1181,7 @@
else:
e = (offset_type(end, 0), len(cdelta), textlen, base,
link, self.rev(p1), self.rev(p2), node)
- self.index.append(e)
+ self.index.insert(-1, e)
self.nodemap[node] = r
if self._inline():
ifh.write(struct.pack(indexformatng, *e))
@@ -1252,7 +1240,7 @@
for x in xrange(rev, self.count()):
del self.nodemap[self.node(x)]
- del self.index[rev:]
+ del self.index[rev:-1]
def checksize(self):
expected = 0