##// END OF EJS Templates
parsers: inline fields of dirstate values in C version...
parsers: inline fields of dirstate values in C version Previously, while unpacking the dirstate we'd create 3-4 new CPython objects for most dirstate values: - the state is a single character string, which is pooled by CPython - the mode is a new object if it isn't 0 due to being in the lookup set - the size is a new object if it is greater than 255 - the mtime is a new object if it isn't -1 due to being in the lookup set - the tuple to contain them all In some cases such as regular hg status, we actually look at all the objects. In other cases like hg add, hg status for a subdirectory, or hg status with the third-party hgwatchman enabled, we look at almost none of the objects. This patch eliminates most object creation in these cases by defining a custom C struct that is exposed to Python with an interface similar to a tuple. Only when tuple elements are actually requested are the respective objects created. The gains, where they're expected, are significant. The following tests are run against a working copy with over 270,000 files. parse_dirstate becomes significantly faster: $ hg perfdirstate before: wall 0.186437 comb 0.180000 user 0.160000 sys 0.020000 (best of 35) after: wall 0.093158 comb 0.100000 user 0.090000 sys 0.010000 (best of 95) and as a result, several commands benefit: $ time hg status # with hgwatchman enabled before: 0.42s user 0.14s system 99% cpu 0.563 total after: 0.34s user 0.12s system 99% cpu 0.471 total $ time hg add new-file before: 0.85s user 0.18s system 99% cpu 1.033 total after: 0.76s user 0.17s system 99% cpu 0.931 total There is a slight regression in regular status performance, but this is fixed in an upcoming patch.

File last commit:

r21752:e250a482 stable
r21809:e250b830 default
Show More
revlog.py
1448 lines | 48.8 KiB | text/x-python | PythonLexer
Martin Geisler
put license and copyright info into comment blocks
r8226 # revlog.py - storage back-end for mercurial
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Martin Geisler
turn some comments back into module docstrings
r8227 """Storage back-end for Mercurial.
This provides efficient delta storage with O(1) retrieve and append
and O(changes) merge between branches.
"""
Peter Arrenbrecht
cleanup: drop unused imports
r7873 # import stuff from node for others to import from revlog
Matt Mackall
revlog: stop exporting node.short
r14393 from node import bin, hex, nullid, nullrev
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Wojciech Lopata
revlog: extract 'checkhash' method...
r19624 import ancestor, mdiff, parsers, error, util, templatefilters
Bryan O'Sullivan
util: subclass deque for Python 2.4 backwards compatibility...
r16834 import struct, zlib, errno
mpm@selenic.com
Add smart node lookup by substring or by rev number
r36
Matt Mackall
revlog: localize some fastpath functions
r5007 _pack = struct.pack
_unpack = struct.unpack
_compress = zlib.compress
_decompress = zlib.decompress
Dirkjan Ochtman
python 2.6 compatibility: compatibility wrappers for hash functions
r6470 _sha = util.sha1
Matt Mackall
revlog: localize some fastpath functions
r5007
Vishakh H
revlog: add shallow header flag...
r11746 # revlog header flags
mason@suse.com
Implement revlogng....
r2072 REVLOGV0 = 0
REVLOGNG = 1
mason@suse.com
Implement data inlined with the index file...
r2073 REVLOGNGINLINEDATA = (1 << 16)
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 REVLOGGENERALDELTA = (1 << 17)
mason@suse.com
Use revlogng and inlined data files by default...
r2222 REVLOG_DEFAULT_FLAGS = REVLOGNGINLINEDATA
REVLOG_DEFAULT_FORMAT = REVLOGNG
REVLOG_DEFAULT_VERSION = REVLOG_DEFAULT_FORMAT | REVLOG_DEFAULT_FLAGS
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 REVLOGNG_FLAGS = REVLOGNGINLINEDATA | REVLOGGENERALDELTA
Vishakh H
revlog: add shallow header flag...
r11746
# revlog index flags
Sune Foldager
revlog: remove support for punched/shallow...
r14196 REVIDX_KNOWN_FLAGS = 0
mason@suse.com
Implement data inlined with the index file...
r2073
Benoit Boissinot
add documentation for revlog._prereadsize
r10916 # max size of revlog with inline data
_maxinline = 131072
Matt Mackall
revlog: remove lazy index
r13253 _chunksize = 1048576
Greg Ward
revlog: factor out _maxinline global....
r10913
Matt Mackall
errors: move revlog errors...
r7633 RevlogError = error.RevlogError
LookupError = error.LookupError
Alexander Solovyov
LookupError should have same __str__ as RevlogError
r6703
Matt Mackall
revlog: some basic code reordering
r4987 def getoffset(q):
return int(q >> 16)
def gettype(q):
return int(q & 0xFFFF)
def offset_type(offset, type):
return long(long(offset) << 16 | type)
Nicolas Dumazet
revlog: faster hash computation when one of the parent node is null...
r7883 nullhash = _sha(nullid)
mpm@selenic.com
Move hash function back to revlog from node
r1091 def hash(text, p1, p2):
"""generate a hash from the given text and its parent hashes
This hash combines both the current file contents and its history
in a manner that makes it easy to distinguish nodes with the same
content in the revision graph.
"""
Nicolas Dumazet
revlog: faster hash computation when one of the parent node is null...
r7883 # As of now, if one of the parent node is null, p2 is null
if p2 == nullid:
# deep copy of a hash is faster than creating one
s = nullhash.copy()
s.update(p1)
else:
# none of the parent nodes are nullid
l = [p1, p2]
l.sort()
s = _sha(l[0])
s.update(l[1])
mpm@selenic.com
Move hash function back to revlog from node
r1091 s.update(text)
return s.digest()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def decompress(bin):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """ decompress the given input """
Matt Mackall
revlog: some codingstyle cleanups
r4980 if not bin:
return bin
mpm@selenic.com
Make compression more intelligent:...
r112 t = bin[0]
Matt Mackall
revlog: some codingstyle cleanups
r4980 if t == '\0':
return bin
if t == 'x':
Brad Hall
revlog: zlib.error sent to the user (issue3424)...
r16883 try:
return _decompress(bin)
except zlib.error, e:
raise RevlogError(_("revlog decompress error: %s") % str(e))
Matt Mackall
revlog: some codingstyle cleanups
r4980 if t == 'u':
return bin[1:]
Thomas Arendsen Hein
Fix some problems when working on broken repositories:...
r1853 raise RevlogError(_("unknown compression type %r") % t)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Benoit Boissinot
revlog: document v0 format
r18585 # index v0:
# 4 bytes: offset
# 4 bytes: compressed length
# 4 bytes: base rev
# 4 bytes: link rev
# 32 bytes: parent 1 nodeid
# 32 bytes: parent 2 nodeid
# 32 bytes: nodeid
Matt Mackall
revlog: some basic code reordering
r4987 indexformatv0 = ">4l20s20s20s"
v0shaoffset = 56
Matt Mackall
revlog: raise offset/type helpers to global scope
r4918
Matt Mackall
revlog: add revlogio interface...
r4972 class revlogoldio(object):
def __init__(self):
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 self.size = struct.calcsize(indexformatv0)
Matt Mackall
revlog: add revlogio interface...
r4972
Benoit Boissinot
revlog/parseindex: no need to pass the file around
r13264 def parseindex(self, data, inline):
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 s = self.size
Matt Mackall
revlog: add revlogio interface...
r4972 index = []
nodemap = {nullid: nullrev}
Matt Mackall
revlog: simplify the v0 parser
r4973 n = off = 0
l = len(data)
while off + s <= l:
cur = data[off:off + s]
off += s
Matt Mackall
revlog: localize some fastpath functions
r5007 e = _unpack(indexformatv0, cur)
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 # transform to revlogv1 format
e2 = (offset_type(e[0], 0), e[1], -1, e[2], e[3],
Matt Mackall
revlog: make revlogv0 loading more robust against corruption
r5544 nodemap.get(e[4], nullrev), nodemap.get(e[5], nullrev), e[6])
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 index.append(e2)
nodemap[e[6]] = n
Matt Mackall
revlog: simplify the v0 parser
r4973 n += 1
Matt Mackall
revlog: add revlogio interface...
r4972
Benoit Boissinot
revlog: always add the magic nullid/nullrev entry in parseindex
r13265 # add the magic null revision at -1
index.append((0, 0, 0, -1, -1, -1, -1, nullid))
Matt Mackall
revlog: pull chunkcache back into revlog
r4983 return index, nodemap, None
Matt Mackall
revlog: add revlogio interface...
r4972
Alexis S. L. Carvalho
revlog: fix revlogio.packentry corner case...
r5338 def packentry(self, entry, node, version, rev):
Benoit Boissinot
revlog: don't silently discard revlog flags on revlogv0
r10395 if gettype(entry[0]):
raise RevlogError(_("index entry flags need RevlogNG"))
Matt Mackall
revlog: abstract out index entry packing...
r4986 e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4],
node(entry[5]), node(entry[6]), entry[7])
Matt Mackall
revlog: localize some fastpath functions
r5007 return _pack(indexformatv0, *e2)
Matt Mackall
revlog: abstract out index entry packing...
r4986
Matt Mackall
revlog: some basic code reordering
r4987 # index ng:
Martin Geisler
revlog: fix inconsistent comment formatting
r11323 # 6 bytes: offset
# 2 bytes: flags
# 4 bytes: compressed length
# 4 bytes: uncompressed length
# 4 bytes: base rev
# 4 bytes: link rev
# 4 bytes: parent 1 rev
# 4 bytes: parent 2 rev
Matt Mackall
revlog: some basic code reordering
r4987 # 32 bytes: nodeid
indexformatng = ">Qiiiiii20s12x"
ngshaoffset = 32
versionformat = ">I"
Matt Mackall
revlog: add revlogio interface...
r4972 class revlogio(object):
def __init__(self):
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 self.size = struct.calcsize(indexformatng)
Matt Mackall
revlog: add revlogio interface...
r4972
Benoit Boissinot
revlog/parseindex: no need to pass the file around
r13264 def parseindex(self, data, inline):
Bernhard Leiner
use the new parseindex implementation C in parsers
r7109 # call the C implementation to parse the index data
Matt Mackall
revlog: only build the nodemap on demand
r13254 index, cache = parsers.parse_index2(data, inline)
Bryan O'Sullivan
parsers: use base-16 trie for faster node->rev mapping...
r16414 return index, getattr(index, 'nodemap', None), cache
Matt Mackall
revlog: add revlogio interface...
r4972
Alexis S. L. Carvalho
revlog: fix revlogio.packentry corner case...
r5338 def packentry(self, entry, node, version, rev):
Matt Mackall
revlog: localize some fastpath functions
r5007 p = _pack(indexformatng, *entry)
Alexis S. L. Carvalho
revlog: fix revlogio.packentry corner case...
r5338 if rev == 0:
Matt Mackall
revlog: localize some fastpath functions
r5007 p = _pack(versionformat, version) + p[4:]
Matt Mackall
revlog: abstract out index entry packing...
r4986 return p
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class revlog(object):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """
the underlying revision storage object
A revlog consists of two parts, an index and the revision data.
The index is a file with a fixed record size containing
Martin Geisler
Fixed docstring typos
r6912 information on each revision, including its nodeid (hash), the
mpm@selenic.com
Add some docstrings to revlog.py
r1083 nodeids of its parents, the position and offset of its data within
the data file, and the revision it's based on. Finally, each entry
contains a linkrev entry that can serve as a pointer to external
data.
The revision data itself is a linear collection of data chunks.
Each chunk represents a revision and is usually represented as a
delta against the previous chunk. To bound lookup time, runs of
deltas are limited to about 2 times the length of the original
version data. This makes retrieval of a version proportional to
its size, or O(1) relative to the number of revisions.
Both pieces of the revlog are written to in an append-only
fashion, which means we never need to rewrite a file to insert or
remove data, and can use some simple techniques to avoid the need
for locking while reading.
"""
Sune Foldager
revlog: remove the last bits of punched/shallow...
r14251 def __init__(self, opener, indexfile):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """
create a revlog object
opener is a function that abstracts the file opening operation
and can be used to implement COW semantics or the like.
"""
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.indexfile = indexfile
Matt Mackall
revlog: don't pass datafile as an argument
r4257 self.datafile = indexfile[:-2] + ".d"
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.opener = opener
Matt Mackall
revlog: mark cache private
r4984 self._cache = None
Wojciech Lopata
generaldelta: initialize basecache properly...
r19764 self._basecache = None
Matt Mackall
revlog: clean up the chunk caching code
r8316 self._chunkcache = (0, '')
Brodie Rao
revlog: allow tuning of the chunk cache size (via format.chunkcachesize)...
r20180 self._chunkcachesize = 65536
Matt Mackall
revlog: simplify revlog.__init__...
r4985 self.index = []
Matt Mackall
revlog: introduce a cache for partial lookups...
r13258 self._pcache = {}
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 self._nodecache = {nullid: nullrev}
self._nodepos = None
Matt Mackall
revlog: simplify revlog.__init__...
r4985
v = REVLOG_DEFAULT_VERSION
Augie Fackler
revlog: use getattr instead of hasattr
r14960 opts = getattr(opener, 'options', None)
if opts is not None:
if 'revlogv1' in opts:
if 'generaldelta' in opts:
Sune Foldager
revlog: get rid of defversion...
r14333 v |= REVLOGGENERALDELTA
else:
v = 0
Brodie Rao
revlog: allow tuning of the chunk cache size (via format.chunkcachesize)...
r20180 if 'chunkcachesize' in opts:
self._chunkcachesize = opts['chunkcachesize']
if self._chunkcachesize <= 0:
raise RevlogError(_('revlog chunk cache size %r is not greater '
'than 0') % self._chunkcachesize)
elif self._chunkcachesize & (self._chunkcachesize - 1):
raise RevlogError(_('revlog chunk cache size %r is not a power '
'of 2') % self._chunkcachesize)
Pradeepkumar Gayam
revlog: parentdelta flags for revlog index
r11928
Matt Mackall
revlog: preread revlog .i file...
r8314 i = ''
Sune Foldager
changelog: don't use generaldelta
r14334 self._initempty = True
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 try:
Benoit Boissinot
revalidate revlog data after locking the repo (issue132)
r1784 f = self.opener(self.indexfile)
Matt Mackall
revlog: remove lazy index
r13253 i = f.read()
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Matt Mackall
revlog: raise offset/type helpers to global scope
r4918 if len(i) > 0:
Matt Mackall
revlog: preread revlog .i file...
r8314 v = struct.unpack(versionformat, i[:4])[0]
Sune Foldager
changelog: don't use generaldelta
r14334 self._initempty = False
Bryan O'Sullivan
Make revlog constructor more discerning in its treatment of errors.
r1322 except IOError, inst:
if inst.errno != errno.ENOENT:
raise
Matt Mackall
revlog: simplify revlog.__init__...
r4985
self.version = v
self._inline = v & REVLOGNGINLINEDATA
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 self._generaldelta = v & REVLOGGENERALDELTA
mason@suse.com
Implement data inlined with the index file...
r2073 flags = v & ~0xFFFF
fmt = v & 0xFFFF
Matt Mackall
revlog: simplify revlog.__init__...
r4985 if fmt == REVLOGV0 and flags:
raise RevlogError(_("index %s unknown flags %#04x for format v0")
% (self.indexfile, flags >> 16))
Vishakh H
revlog: add shallow header flag...
r11746 elif fmt == REVLOGNG and flags & ~REVLOGNG_FLAGS:
Matt Mackall
revlog: simplify revlog.__init__...
r4985 raise RevlogError(_("index %s unknown flags %#04x for revlogng")
% (self.indexfile, flags >> 16))
elif fmt > REVLOGNG:
Matt Mackall
Make revlog error slightly less scary
r3743 raise RevlogError(_("index %s unknown format %d")
Thomas Arendsen Hein
Indentation cleanups for 2956948b81f3.
r3680 % (self.indexfile, fmt))
Matt Mackall
revlog: simplify revlog.__init__...
r4985
Matt Mackall
revlog: add revlogio interface...
r4972 self._io = revlogio()
Matt Mackall
revlog: regroup parsing code
r4971 if self.version == REVLOGV0:
Matt Mackall
revlog: add revlogio interface...
r4972 self._io = revlogoldio()
Benoit Boissinot
revlog: always add the magic nullid/nullrev entry in parseindex
r13265 try:
d = self._io.parseindex(i, self._inline)
except (ValueError, IndexError):
raise RevlogError(_("index %s is corrupted") % (self.indexfile))
Benoit Boissinot
revlog: explicit test and explicit variable names
r13268 self.index, nodemap, self._chunkcache = d
if nodemap is not None:
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 self.nodemap = self._nodecache = nodemap
Benoit Boissinot
revlog: always add the magic nullid/nullrev entry in parseindex
r13265 if not self._chunkcache:
self._chunkclear()
mpm@selenic.com
Only use lazy indexing for big indices and avoid the overhead of the...
r116
Matt Mackall
revlog: some codingstyle cleanups
r4980 def tip(self):
return self.node(len(self.index) - 2)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def __len__(self):
Matt Mackall
revlog: some codingstyle cleanups
r4980 return len(self.index) - 1
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def __iter__(self):
Durham Goode
commit: increase perf by avoiding unnecessary filteredrevs check...
r17951 return iter(xrange(len(self)))
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 def revs(self, start=0, stop=None):
"""iterate over all rev in this revlog (from start to stop)"""
Pierre-Yves David
revlog: allow reverse iteration with revlog.revs...
r17975 step = 1
if stop is not None:
if start > stop:
step = -1
stop += step
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 else:
Pierre-Yves David
revlog: allow reverse iteration with revlog.revs...
r17975 stop = len(self)
return xrange(start, stop, step)
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275
@util.propertycache
def nodemap(self):
Alexander Solovyov
remove unused imports and variables
r14064 self.rev(self.node(0))
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 return self._nodecache
Matt Mackall
revlog: do revlog node->rev mapping by scanning...
r13259
Matt Mackall
revlog: add hasnode helper method
r16374 def hasnode(self, node):
try:
self.rev(node)
return True
except KeyError:
return False
Bryan O'Sullivan
parsers: use base-16 trie for faster node->rev mapping...
r16414 def clearcaches(self):
try:
self._nodecache.clearcaches()
except AttributeError:
self._nodecache = {nullid: nullrev}
self._nodepos = None
Matt Mackall
revlog: do revlog node->rev mapping by scanning...
r13259 def rev(self, node):
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 try:
return self._nodecache[node]
Bryan O'Sullivan
parsers: use base-16 trie for faster node->rev mapping...
r16414 except RevlogError:
# parsers.c radix tree lookup failed
raise LookupError(node, self.indexfile, _('no node'))
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 except KeyError:
Bryan O'Sullivan
parsers: use base-16 trie for faster node->rev mapping...
r16414 # pure python cache lookup failed
Matt Mackall
revlog: incrementally build node cache with linear searches...
r13275 n = self._nodecache
i = self.index
p = self._nodepos
if p is None:
p = len(i) - 2
for r in xrange(p, -1, -1):
v = i[r][7]
n[v] = r
if v == node:
self._nodepos = r - 1
return r
raise LookupError(node, self.indexfile, _('no node'))
Matt Mackall
revlog: some codingstyle cleanups
r4980 def node(self, rev):
return self.index[rev][7]
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 def linkrev(self, rev):
return self.index[rev][4]
mpm@selenic.com
Handle nullid better for ancestor
r2 def parents(self, node):
Matt Mackall
revlog: speed up parents()
r7363 i = self.index
d = i[self.rev(node)]
return i[d[5]][7], i[d[6]][7] # map revisions to nodes inline
Alexis S. L. Carvalho
Add revlog.parentrevs function....
r2489 def parentrevs(self, rev):
Matt Mackall
revlog: add a magic null revision to our index...
r4979 return self.index[rev][5:7]
mason@suse.com
Implement revlogng....
r2072 def start(self, rev):
Matt Mackall
revlog: minor chunk speed-up
r5006 return int(self.index[rev][0] >> 16)
Matt Mackall
revlog: some codingstyle cleanups
r4980 def end(self, rev):
return self.start(rev) + self.length(rev)
def length(self, rev):
return self.index[rev][1]
Sune Foldager
revlog: calculate base revisions iteratively...
r14252 def chainbase(self, rev):
index = self.index
base = index[rev][3]
while base != rev:
rev = base
base = index[rev][3]
return base
Pradeepkumar Gayam
revlog: add a flags method that returns revision flags
r11693 def flags(self, rev):
return self.index[rev][0] & 0xFFFF
Benoit Boissinot
revlog: add rawsize(), identical to size() but not subclassed by filelog
r12024 def rawsize(self, rev):
mason@suse.com
Fill in the uncompressed size during revlog.addgroup...
r2078 """return the length of the uncompressed text for a given revision"""
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 l = self.index[rev][2]
mason@suse.com
Fill in the uncompressed size during revlog.addgroup...
r2078 if l >= 0:
return l
t = self.revision(self.node(rev))
return len(t)
Benoit Boissinot
revlog: add rawsize(), identical to size() but not subclassed by filelog
r12024 size = rawsize
mason@suse.com
Fill in the uncompressed size during revlog.addgroup...
r2078
Siddharth Agarwal
revlog.ancestors: add support for including revs...
r18081 def ancestors(self, revs, stoprev=0, inclusive=False):
Greg Ward
revlog: rewrite several method docstrings...
r10047 """Generate the ancestors of 'revs' in reverse topological order.
Joshua Redstone
revlog: add optional stoprev arg to revlog.ancestors()...
r16868 Does not generate revs lower than stoprev.
Greg Ward
revlog: rewrite several method docstrings...
r10047
Siddharth Agarwal
revlog: move ancestor generation out to a new class...
r18090 See the documentation for ancestor.lazyancestors for more details."""
Siddharth Agarwal
revlog.ancestors: add support for including revs...
r18081
Siddharth Agarwal
revlog: move ancestor generation out to a new class...
r18090 return ancestor.lazyancestors(self, revs, stoprev=stoprev,
inclusive=inclusive)
Stefano Tortarolo
Add ancestors and descendants to revlog...
r6872
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 def descendants(self, revs):
Greg Ward
revlog: rewrite several method docstrings...
r10047 """Generate the descendants of 'revs' in revision order.
Yield a sequence of revision numbers starting with a child of
some rev in revs, i.e., each revision is *not* considered a
descendant of itself. Results are ordered by revision number (a
topological sort)."""
Nicolas Dumazet
revlog: fix descendants() if nullrev is in revs...
r12950 first = min(revs)
if first == nullrev:
for i in self:
yield i
return
Martin Geisler
util: use built-in set and frozenset...
r8150 seen = set(revs)
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 for i in self.revs(start=first + 1):
Stefano Tortarolo
Add ancestors and descendants to revlog...
r6872 for x in self.parentrevs(i):
if x != nullrev and x in seen:
seen.add(i)
yield i
break
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741 def findcommonmissing(self, common=None, heads=None):
"""Return a tuple of the ancestors of common and the ancestors of heads
Pierre-Yves David
revlog: improve docstring for findcommonmissing
r15835 that are not ancestors of common. In revset terminology, we return the
tuple:
Greg Ward
revlog: rewrite several method docstrings...
r10047
Pierre-Yves David
revlog: improve docstring for findcommonmissing
r15835 ::common, (::heads) - (::common)
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233
Greg Ward
revlog: rewrite several method docstrings...
r10047 The list is sorted by revision number, meaning it is
topologically sorted.
'heads' and 'common' are both lists of node IDs. If heads is
not supplied, uses all of the revlog's heads. If common is not
supplied, uses nullid."""
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 if common is None:
common = [nullid]
if heads is None:
heads = self.heads()
common = [self.rev(n) for n in common]
heads = [self.rev(n) for n in heads]
# we want the ancestors, but inclusive
Durham Goode
revlog: return lazy set from findcommonmissing...
r20073 class lazyset(object):
def __init__(self, lazyvalues):
self.addedvalues = set()
self.lazyvalues = lazyvalues
def __contains__(self, value):
return value in self.addedvalues or value in self.lazyvalues
def __iter__(self):
added = self.addedvalues
for r in added:
yield r
for r in self.lazyvalues:
if not r in added:
yield r
def add(self, value):
self.addedvalues.add(value)
def update(self, values):
self.addedvalues.update(values)
has = lazyset(self.ancestors(common))
Martin Geisler
replace set-like dictionaries with real sets...
r8152 has.add(nullrev)
has.update(common)
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233
# take all ancestors from heads that aren't in has
Benoit Boissinot
revlog.missing(): use sets instead of a dict
r8453 missing = set()
Bryan O'Sullivan
util: subclass deque for Python 2.4 backwards compatibility...
r16834 visit = util.deque(r for r in heads if r not in has)
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 while visit:
Bryan O'Sullivan
cleanup: use the deque type where appropriate...
r16803 r = visit.popleft()
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 if r in missing:
continue
else:
Benoit Boissinot
revlog.missing(): use sets instead of a dict
r8453 missing.add(r)
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 for p in self.parentrevs(r):
if p not in has:
visit.append(p)
Benoit Boissinot
revlog.missing(): use sets instead of a dict
r8453 missing = list(missing)
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 missing.sort()
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741 return has, [self.node(r) for r in missing]
Siddharth Agarwal
revlog: add rev-specific variant of findmissing...
r17972 def findmissingrevs(self, common=None, heads=None):
"""Return the revision numbers of the ancestors of heads that
are not ancestors of common.
More specifically, return a list of revision numbers corresponding to
nodes N such that every N satisfies the following constraints:
1. N is an ancestor of some node in 'heads'
2. N is not an ancestor of any node in 'common'
The list is sorted by revision number, meaning it is
topologically sorted.
'heads' and 'common' are both lists of revision numbers. If heads is
not supplied, uses all of the revlog's heads. If common is not
supplied, uses nullid."""
if common is None:
common = [nullrev]
if heads is None:
heads = self.headrevs()
return ancestor.missingancestors(heads, common, self.parentrevs)
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741 def findmissing(self, common=None, heads=None):
"""Return the ancestors of heads that are not ancestors of common.
More specifically, return a list of nodes N such that every N
satisfies the following constraints:
1. N is an ancestor of some node in 'heads'
2. N is not an ancestor of any node in 'common'
The list is sorted by revision number, meaning it is
topologically sorted.
'heads' and 'common' are both lists of node IDs. If heads is
not supplied, uses all of the revlog's heads. If common is not
supplied, uses nullid."""
Siddharth Agarwal
revlog: switch findmissing to use ancestor.missingancestors...
r17971 if common is None:
common = [nullid]
if heads is None:
heads = self.heads()
common = [self.rev(n) for n in common]
heads = [self.rev(n) for n in heads]
return [self.node(r) for r in
ancestor.missingancestors(heads, common, self.parentrevs)]
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 def nodesbetween(self, roots=None, heads=None):
Greg Ward
revlog: rewrite several method docstrings...
r10047 """Return a topological path from 'roots' to 'heads'.
Return a tuple (nodes, outroots, outheads) where 'nodes' is a
topologically sorted list of all nodes N that satisfy both of
these constraints:
1. N is a descendant of some node in 'roots'
2. N is an ancestor of some node in 'heads'
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457
Greg Ward
revlog: rewrite several method docstrings...
r10047 Every node is considered to be both a descendant and an ancestor
of itself, so every reachable node in 'roots' and 'heads' will be
included in 'nodes'.
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457
Greg Ward
revlog: rewrite several method docstrings...
r10047 'outroots' is the list of reachable nodes in 'roots', i.e., the
subset of 'roots' that is returned in 'nodes'. Likewise,
'outheads' is the subset of 'heads' that is also in 'nodes'.
'roots' and 'heads' are both lists of node IDs. If 'roots' is
unspecified, uses nullid as the only root. If 'heads' is
unspecified, uses list of all of the revlog's heads."""
Eric Hopper
Fix to handle case of empty list for roots or heads in nodesbetween.
r1463 nonodes = ([], [], [])
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 if roots is not None:
roots = list(roots)
Eric Hopper
Fix to handle case of empty list for roots or heads in nodesbetween.
r1463 if not roots:
return nonodes
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 lowestrev = min([self.rev(n) for n in roots])
else:
Matt Mackall
check-code: catch misspellings of descendant...
r14549 roots = [nullid] # Everybody's a descendant of nullid
Thomas Arendsen Hein
Define and use nullrev (revision of nullid) instead of -1.
r3578 lowestrev = nullrev
if (lowestrev == nullrev) and (heads is None):
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # We want _all_ the nodes!
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 return ([self.node(r) for r in self], [nullid], list(self.heads()))
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 if heads is None:
# All nodes are ancestors, so the latest ancestor is the last
# node.
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 highestrev = len(self) - 1
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Set ancestors to None to signal that every node is an ancestor.
ancestors = None
# Set heads to an empty dictionary for later discovery of heads
heads = {}
else:
Eric Hopper
Fix to handle case of empty list for roots or heads in nodesbetween.
r1463 heads = list(heads)
if not heads:
return nonodes
Benoit Boissinot
revlog: use set instead of dict
r8464 ancestors = set()
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Turn heads into a dictionary so we can remove 'fake' heads.
# Also, later we will be using it to filter out the heads we can't
# find from roots.
Martin Geisler
revlog: use real Booleans instead of 0/1 in nodesbetween
r14219 heads = dict.fromkeys(heads, False)
Benoit Boissinot
nodesbetween: fix a bug with duplicate heads
r3360 # Start at the top and keep marking parents until we're done.
Martin Geisler
rebase, revlog: use set(x) instead of set(x.keys())...
r8163 nodestotag = set(heads)
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Remember where the top was so we can use it as a limit later.
highestrev = max([self.rev(n) for n in nodestotag])
while nodestotag:
# grab a node to tag
n = nodestotag.pop()
# Never tag nullid
if n == nullid:
continue
# A node's revision number represents its place in a
# topologically sorted list of nodes.
r = self.rev(n)
if r >= lowestrev:
if n not in ancestors:
Matt Mackall
check-code: catch misspellings of descendant...
r14549 # If we are possibly a descendant of one of the roots
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # and we haven't already been marked as an ancestor
Benoit Boissinot
revlog: use set instead of dict
r8464 ancestors.add(n) # Mark as ancestor
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Add non-nullid parents to list of nodes to tag.
Martin Geisler
revlog: let nodestotag be a set instead of a list
r8153 nodestotag.update([p for p in self.parents(n) if
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 p != nullid])
elif n in heads: # We've seen it before, is it a fake head?
# So it is, real heads should not be the ancestors of
# any other heads.
heads.pop(n)
Eric Hopper
Fix small bug in nodesbetween if heads is [nullid].
r1459 if not ancestors:
Eric Hopper
Fix to handle case of empty list for roots or heads in nodesbetween.
r1463 return nonodes
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Now that we have our set of ancestors, we want to remove any
# roots that are not ancestors.
# If one of the roots was nullid, everything is included anyway.
Thomas Arendsen Hein
Define and use nullrev (revision of nullid) instead of -1.
r3578 if lowestrev > nullrev:
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # But, since we weren't, let's recompute the lowest rev to not
# include roots that aren't ancestors.
# Filter out roots that aren't ancestors of heads
roots = [n for n in roots if n in ancestors]
# Recompute the lowest revision
if roots:
lowestrev = min([self.rev(n) for n in roots])
else:
# No more roots? Return empty list
Eric Hopper
Fix to handle case of empty list for roots or heads in nodesbetween.
r1463 return nonodes
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 else:
# We are descending from nullid, and don't need to care about
# any other roots.
Thomas Arendsen Hein
Define and use nullrev (revision of nullid) instead of -1.
r3578 lowestrev = nullrev
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 roots = [nullid]
Martin Geisler
replace set-like dictionaries with real sets...
r8152 # Transform our roots list into a set.
Matt Mackall
check-code: catch misspellings of descendant...
r14549 descendants = set(roots)
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Also, keep the original roots so we can filter out roots that aren't
# 'real' roots (i.e. are descended from other roots).
Matt Mackall
check-code: catch misspellings of descendant...
r14549 roots = descendants.copy()
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # Our topologically sorted list of output nodes.
orderedout = []
# Don't start at nullid since we don't want nullid in our output list,
timeless@mozdev.org
spelling: descendants
r17483 # and if nullid shows up in descendants, empty parents will look like
Matt Mackall
check-code: catch misspellings of descendant...
r14549 # they're descendants.
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 for r in self.revs(start=max(lowestrev, 0), stop=highestrev + 1):
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 n = self.node(r)
Matt Mackall
check-code: catch misspellings of descendant...
r14549 isdescendant = False
if lowestrev == nullrev: # Everybody is a descendant of nullid
isdescendant = True
elif n in descendants:
# n is already a descendant
isdescendant = True
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # This check only needs to be done here because all the roots
Matt Mackall
check-code: catch misspellings of descendant...
r14549 # will start being marked is descendants before the loop.
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 if n in roots:
# If n was a root, check if it's a 'real' root.
p = tuple(self.parents(n))
Matt Mackall
check-code: catch misspellings of descendant...
r14549 # If any of its parents are descendants, it's not a root.
if (p[0] in descendants) or (p[1] in descendants):
Martin Geisler
replace set-like dictionaries with real sets...
r8152 roots.remove(n)
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 else:
p = tuple(self.parents(n))
Matt Mackall
check-code: catch misspellings of descendant...
r14549 # A node is a descendant if either of its parents are
# descendants. (We seeded the dependents list with the roots
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # up there, remember?)
Matt Mackall
check-code: catch misspellings of descendant...
r14549 if (p[0] in descendants) or (p[1] in descendants):
descendants.add(n)
isdescendant = True
if isdescendant and ((ancestors is None) or (n in ancestors)):
# Only include nodes that are both descendants and ancestors.
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 orderedout.append(n)
if (ancestors is not None) and (n in heads):
# We're trying to figure out which heads are reachable
# from roots.
# Mark this head as having been reached
Martin Geisler
revlog: use real Booleans instead of 0/1 in nodesbetween
r14219 heads[n] = True
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 elif ancestors is None:
# Otherwise, we're trying to discover the heads.
# Assume this is a head because if it isn't, the next step
# will eventually remove it.
Martin Geisler
revlog: use real Booleans instead of 0/1 in nodesbetween
r14219 heads[n] = True
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 # But, obviously its parents aren't.
for p in self.parents(n):
heads.pop(p, None)
Martin Geisler
revlog: use real Booleans instead of 0/1 in nodesbetween
r14219 heads = [n for n, flag in heads.iteritems() if flag]
Martin Geisler
replace set-like dictionaries with real sets...
r8152 roots = list(roots)
Eric Hopper
This implements the nodesbetween method, and it removes the newer method...
r1457 assert orderedout
assert roots
assert heads
return (orderedout, roots, heads)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 def headrevs(self):
Bryan O'Sullivan
revlog: switch to a C version of headrevs...
r16786 try:
return self.index.headrevs()
except AttributeError:
Pierre-Yves David
clfilter: split `revlog.headrevs` C call from python code...
r17674 return self._headrevs()
def _headrevs(self):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 count = len(self)
if not count:
return [nullrev]
Pierre-Yves David
clfilter: handle non contiguous iteration in `revlov.headrevs`...
r17673 # we won't iter over filtered rev so nobody is a head at start
ishead = [0] * (count + 1)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 index = self.index
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 for r in self:
Pierre-Yves David
clfilter: handle non contiguous iteration in `revlov.headrevs`...
r17673 ishead[r] = 1 # I may be an head
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 e = index[r]
Pierre-Yves David
clfilter: handle non contiguous iteration in `revlov.headrevs`...
r17673 ishead[e[5]] = ishead[e[6]] = 0 # my parent are not
return [r for r, val in enumerate(ishead) if val]
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923 def heads(self, start=None, stop=None):
Benoit Boissinot
add a -r/--rev option to heads to show only heads descendant from rev
r1550 """return the list of all nodes that have no children
Thomas Arendsen Hein
Fixes to "hg heads -r FOO":...
r1551
if start is specified, only heads that are descendants of
start will be returned
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923 if stop is specified, it will consider all the revs from stop
as if they had no children
Thomas Arendsen Hein
Fixes to "hg heads -r FOO":...
r1551 """
Matt Mackall
revlog: implement a fast path for heads
r4991 if start is None and stop is None:
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if not len(self):
Matt Mackall
revlog: implement a fast path for heads
r4991 return [nullid]
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 return [self.node(r) for r in self.headrevs()]
Matt Mackall
revlog: implement a fast path for heads
r4991
Thomas Arendsen Hein
Fixes to "hg heads -r FOO":...
r1551 if start is None:
start = nullid
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923 if stop is None:
stop = []
Martin Geisler
replace set-like dictionaries with real sets...
r8152 stoprevs = set([self.rev(n) for n in stop])
Benoit Boissinot
add a -r/--rev option to heads to show only heads descendant from rev
r1550 startrev = self.rev(start)
Benoit Boissinot
revlog: use set instead of dict
r8464 reachable = set((startrev,))
heads = set((startrev,))
mpm@selenic.com
Add some docstrings to revlog.py
r1083
Alexis S. L. Carvalho
Change revlog.heads to walk the revision graph using revision numbers...
r2490 parentrevs = self.parentrevs
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 for r in self.revs(start=startrev + 1):
Alexis S. L. Carvalho
Change revlog.heads to walk the revision graph using revision numbers...
r2490 for p in parentrevs(r):
if p in reachable:
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923 if r not in stoprevs:
Benoit Boissinot
revlog: use set instead of dict
r8464 reachable.add(r)
heads.add(r)
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923 if p in heads and p not in stoprevs:
Benoit Boissinot
revlog: use set instead of dict
r8464 heads.remove(p)
Benoit Boissinot
fix calculation of new heads added during push with -r...
r3923
Alexis S. L. Carvalho
Change revlog.heads to walk the revision graph using revision numbers...
r2490 return [self.node(r) for r in heads]
mpm@selenic.com
revlog: add a children function...
r370
def children(self, node):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """find the children of a given node"""
mpm@selenic.com
revlog: add a children function...
r370 c = []
p = self.rev(node)
Pierre-Yves David
clfilter: make the revlog class responsible of all its iteration...
r17672 for r in self.revs(start=p + 1):
Thomas Arendsen Hein
Fix revlog.children so the real children of the null revision can be calculated.
r4746 prevs = [pr for pr in self.parentrevs(r) if pr != nullrev]
if prevs:
for pr in prevs:
if pr == p:
c.append(self.node(r))
elif p == nullrev:
c.append(self.node(r))
mpm@selenic.com
revlog: add a children function...
r370 return c
mpm@selenic.com
Whitespace cleanups...
r515
Benoit Boissinot
revlog: put graph related functions together
r10897 def descendant(self, start, end):
Nicolas Dumazet
revlog: if start is nullrev, end is always a descendant
r12949 if start == nullrev:
return True
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 for i in self.descendants([start]):
Benoit Boissinot
revlog: put graph related functions together
r10897 if i == end:
return True
elif i > end:
break
return False
Mads Kiilerich
revlog: introduce commonancestorsheads method...
r21104 def commonancestorsheads(self, a, b):
"""calculate all the heads of the common ancestors of nodes a and b"""
a, b = self.rev(a), self.rev(b)
try:
ancs = self.index.commonancestorsheads(a, b)
except (AttributeError, OverflowError): # C implementation failed
ancs = ancestor.commonancestorsheads(self.parentrevs, a, b)
return map(self.node, ancs)
Mads Kiilerich
revlog: backout 514d32de6646 - commonancestors
r21107 def ancestor(self, a, b):
"""calculate the least common ancestor of nodes a and b"""
Benoit Boissinot
revlog: put graph related functions together
r10897 a, b = self.rev(a), self.rev(b)
Bryan O'Sullivan
parsers: a C implementation of the new ancestors algorithm...
r18988 try:
ancs = self.index.ancestors(a, b)
Mads Kiilerich
revlog: backout 514d32de6646 - commonancestors
r21107 except (AttributeError, OverflowError):
Bryan O'Sullivan
parsers: a C implementation of the new ancestors algorithm...
r18988 ancs = ancestor.ancestors(self.parentrevs, a, b)
Bryan O'Sullivan
revlog: choose a consistent ancestor when there's a tie...
r18987 if ancs:
# choose a consistent winner when there's a tie
Mads Kiilerich
revlog: backout 514d32de6646 - commonancestors
r21107 return min(map(self.node, ancs))
Bryan O'Sullivan
revlog: choose a consistent ancestor when there's a tie...
r18987 return nullid
Benoit Boissinot
revlog: put graph related functions together
r10897
Matt Mackall
Only look up tags and branches as a last resort
r3453 def _match(self, id):
Matt Mackall
revlog: don't handle long for revision matching...
r16762 if isinstance(id, int):
Benoit Boissinot
cleanups in revlog.lookup...
r3156 # rev
Benoit Boissinot
lookup should allow -1 to represent nullid (if passed an int as arg)
r2641 return self.node(id)
Matt Mackall
revlog.lookup tweaks...
r3438 if len(id) == 20:
# possibly a binary node
# odds of a binary node being all hex in ASCII are 1 in 10**25
try:
node = id
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 self.rev(node) # quick search the index
Matt Mackall
revlog.lookup tweaks...
r3438 return node
Brendan Cully
Add revlog.LookupError exception, and use it instead of RevlogError....
r3930 except LookupError:
Matt Mackall
revlog.lookup tweaks...
r3438 pass # may be partial hex id
mpm@selenic.com
Add smart node lookup by substring or by rev number
r36 try:
Benoit Boissinot
cleanups in revlog.lookup...
r3156 # str(rev)
mpm@selenic.com
Add smart node lookup by substring or by rev number
r36 rev = int(id)
Matt Mackall
revlog: some codingstyle cleanups
r4980 if str(rev) != id:
raise ValueError
if rev < 0:
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 rev = len(self) + rev
if rev < 0 or rev >= len(self):
Matt Mackall
revlog: some codingstyle cleanups
r4980 raise ValueError
mpm@selenic.com
Add smart node lookup by substring or by rev number
r36 return self.node(rev)
mpm@selenic.com
Various node id lookup tweaks...
r469 except (ValueError, OverflowError):
Benoit Boissinot
cleanups in revlog.lookup...
r3156 pass
Matt Mackall
Only look up tags and branches as a last resort
r3453 if len(id) == 40:
try:
Matt Mackall
revlog.lookup tweaks...
r3438 # a full hex nodeid?
node = bin(id)
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 self.rev(node)
Benoit Boissinot
optimize revlog.lookup when passed hex(node)[:...]...
r3157 return node
Sune Foldager
provide nicer feedback when an unknown node id is passed to a command...
r7062 except (TypeError, LookupError):
Matt Mackall
Only look up tags and branches as a last resort
r3453 pass
def _partialmatch(self, id):
Bryan O'Sullivan
revlog: speed up prefix matching against nodes...
r16665 try:
Matt Mackall
revlog: handle hidden revs in _partialmatch (issue3979)...
r19471 n = self.index.partialmatch(id)
if n and self.hasnode(n):
return n
return None
Bryan O'Sullivan
revlog: speed up prefix matching against nodes...
r16665 except RevlogError:
# parsers.c radix tree lookup gave multiple matches
Matt Mackall
revlog: handle hidden revs in _partialmatch (issue3979)...
r19471 # fall through to slow path that filters hidden revisions
pass
Bryan O'Sullivan
revlog: speed up prefix matching against nodes...
r16665 except (AttributeError, ValueError):
# we are pure python, or key was too short to search radix tree
pass
Matt Mackall
revlog: introduce a cache for partial lookups...
r13258 if id in self._pcache:
return self._pcache[id]
Matt Mackall
Only look up tags and branches as a last resort
r3453 if len(id) < 40:
try:
Matt Mackall
revlog.lookup tweaks...
r3438 # hex(node)[:...]
Alejandro Santos
compat: use // for integer division
r9029 l = len(id) // 2 # grab an even number of digits
Matt Mackall
revlog: do revlog node->rev mapping by scanning...
r13259 prefix = bin(id[:l * 2])
nl = [e[7] for e in self.index if e[7].startswith(prefix)]
Matt Mackall
revlog: handle hidden revs in _partialmatch (issue3979)...
r19471 nl = [n for n in nl if hex(n).startswith(id) and
self.hasnode(n)]
Matt Mackall
lookup: speed up partial lookup
r7365 if len(nl) > 0:
if len(nl) == 1:
Matt Mackall
revlog: introduce a cache for partial lookups...
r13258 self._pcache[id] = nl[0]
Matt Mackall
lookup: speed up partial lookup
r7365 return nl[0]
raise LookupError(id, self.indexfile,
_('ambiguous identifier'))
return None
Matt Mackall
Only look up tags and branches as a last resort
r3453 except TypeError:
pass
def lookup(self, id):
"""locate a node based on:
- revision number or str(revision number)
- nodeid or subset of hex nodeid
"""
n = self._match(id)
if n is not None:
return n
n = self._partialmatch(id)
if n:
return n
mpm@selenic.com
Whitespace cleanups...
r515
Matt Mackall
revlog: report node and file when lookup fails
r6228 raise LookupError(id, self.indexfile, _('no match found'))
mpm@selenic.com
Add smart node lookup by substring or by rev number
r36
Matt Mackall
Move cmp bits from filelog to revlog
r2890 def cmp(self, node, text):
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539 """compare text with a given file revision
returns True if text is different than what is stored.
"""
Matt Mackall
Move cmp bits from filelog to revlog
r2890 p1, p2 = self.parents(node)
return hash(text, p1, p2) != node
Matt Mackall
revlog: clean up the chunk caching code
r8316 def _addchunk(self, offset, data):
o, d = self._chunkcache
# try to add to existing cache
Matt Mackall
revlog: remove lazy index
r13253 if o + len(d) == offset and len(d) + len(data) < _chunksize:
Matt Mackall
revlog: clean up the chunk caching code
r8316 self._chunkcache = o, d + data
else:
self._chunkcache = offset, data
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 def _loadchunk(self, offset, length):
if self._inline:
df = self.opener(self.indexfile)
else:
df = self.opener(self.datafile)
Matt Mackall
revlog: clean up the chunk caching code
r8316
Brodie Rao
revlog: read/cache chunks in fixed windows of 64 KB...
r20179 # Cache data both forward and backward around the requested
# data, in a fixed size window. This helps speed up operations
# involving reading the revlog backwards.
Brodie Rao
revlog: allow tuning of the chunk cache size (via format.chunkcachesize)...
r20180 cachesize = self._chunkcachesize
realoffset = offset & ~(cachesize - 1)
reallength = (((offset + length + cachesize) & ~(cachesize - 1))
- realoffset)
Brodie Rao
revlog: read/cache chunks in fixed windows of 64 KB...
r20179 df.seek(realoffset)
d = df.read(reallength)
Matt Mackall
misc: adding missing file close() calls...
r15407 df.close()
Brodie Rao
revlog: read/cache chunks in fixed windows of 64 KB...
r20179 self._addchunk(realoffset, d)
if offset != realoffset or reallength != length:
return util.buffer(d, offset - realoffset, length)
Matt Mackall
revlog: clean up the chunk caching code
r8316 return d
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 def _getchunk(self, offset, length):
Matt Mackall
revlog: clean up the chunk caching code
r8316 o, d = self._chunkcache
l = len(d)
# is it in the cache?
cachestart = offset - o
cacheend = cachestart + length
if cachestart >= 0 and cacheend <= l:
if cachestart == 0 and cacheend == l:
return d # avoid a copy
Bryan O'Sullivan
revlog: avoid an expensive string copy...
r16423 return util.buffer(d, cachestart, cacheend - cachestart)
Matt Mackall
revlog: clean up the chunk caching code
r8316
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 return self._loadchunk(offset, length)
Matt Mackall
revlog: clean up the chunk caching code
r8316
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 def _chunkraw(self, startrev, endrev):
Matt Mackall
revlog: add cache priming for reconstructing delta chains
r8318 start = self.start(startrev)
Siddharth Agarwal
revlog.revision: fix cache preload for inline revlogs...
r19714 end = self.end(endrev)
Matt Mackall
revlog: add cache priming for reconstructing delta chains
r8318 if self._inline:
start += (startrev + 1) * self._io.size
Siddharth Agarwal
revlog.revision: fix cache preload for inline revlogs...
r19714 end += (endrev + 1) * self._io.size
length = end - start
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 return self._getchunk(start, length)
Matt Mackall
revlog: add cache priming for reconstructing delta chains
r8318
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 def _chunk(self, rev):
return decompress(self._chunkraw(rev, rev))
Siddharth Agarwal
revlog: add a fast method for getting a list of chunks...
r19713 def _chunks(self, revs):
'''faster version of [self._chunk(rev) for rev in revs]
Assumes that revs is in ascending order.'''
Siddharth Agarwal
revlog: move chunk cache preload from revision to _chunks...
r19716 if not revs:
return []
Siddharth Agarwal
revlog: add a fast method for getting a list of chunks...
r19713 start = self.start
length = self.length
inline = self._inline
iosize = self._io.size
Siddharth Agarwal
revlog._chunks: inline getchunk...
r19715 buffer = util.buffer
Siddharth Agarwal
revlog: add a fast method for getting a list of chunks...
r19713
l = []
ladd = l.append
Siddharth Agarwal
revlog: move chunk cache preload from revision to _chunks...
r19716 # preload the cache
Matt Mackall
revlog: deal with chunk ranges over 2G on Windows (issue4215)...
r20957 try:
Matt Mackall
revlog: fix check-code error
r21752 while True:
Matt Mackall
revlog: make _chunkcache access atomic...
r21749 # ensure that the cache doesn't change out from under us
_cache = self._chunkcache
self._chunkraw(revs[0], revs[-1])
if _cache == self._chunkcache:
break
offset, data = _cache
Matt Mackall
revlog: deal with chunk ranges over 2G on Windows (issue4215)...
r20957 except OverflowError:
# issue4215 - we can't cache a run of chunks greater than
# 2G on Windows
return [self._chunk(rev) for rev in revs]
Siddharth Agarwal
revlog._chunks: inline getchunk...
r19715
Siddharth Agarwal
revlog: add a fast method for getting a list of chunks...
r19713 for rev in revs:
chunkstart = start(rev)
if inline:
chunkstart += (rev + 1) * iosize
chunklength = length(rev)
Siddharth Agarwal
revlog._chunks: inline getchunk...
r19715 ladd(decompress(buffer(data, chunkstart - offset, chunklength)))
Siddharth Agarwal
revlog: add a fast method for getting a list of chunks...
r19713
return l
Sune Foldager
revlog: introduce _chunkbase to allow filelog to override...
r14075
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 def _chunkclear(self):
self._chunkcache = (0, '')
Benoit Boissinot
cleanup of revlog.group when repository is local...
r1598
Pradeepkumar Gayam
revlog: deltachain() returns chain of revs need to construct a revision
r11929 def deltaparent(self, rev):
Sune Foldager
revlog: remove support for parentdelta...
r14195 """return deltaparent of the given revision"""
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 base = self.index[rev][3]
if base == rev:
Sune Foldager
revlog: compute correct deltaparent in the deltaparent function...
r14208 return nullrev
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 elif self._generaldelta:
return base
Sune Foldager
revlog: compute correct deltaparent in the deltaparent function...
r14208 else:
return rev - 1
Pradeepkumar Gayam
revlog: deltachain() returns chain of revs need to construct a revision
r11929
Benoit Boissinot
revlog.py: factorization and fixes for rev < 0 (nullid)
r1941 def revdiff(self, rev1, rev2):
"""return or calculate a delta between two revisions"""
Sune Foldager
revlog: compute correct deltaparent in the deltaparent function...
r14208 if rev1 != nullrev and self.deltaparent(rev2) == rev1:
Bryan O'Sullivan
revlog: avoid an expensive string copy...
r16423 return str(self._chunk(rev2))
Matt Mackall
revlog: minor revdiff reorganization
r5005
Matt Mackall
revlog: drop some unneeded rev.node calls in revdiff
r16424 return mdiff.textdiff(self.revision(rev1),
self.revision(rev2))
mpm@selenic.com
Add code to retrieve or construct a revlog delta
r119
Matt Mackall
revlog: allow retrieving contents by revision number
r16375 def revision(self, nodeorrev):
Patrick Mezard
revlog: fix partial revision() docstring (from d7d64b89a65c)
r16435 """return an uncompressed revision of a given node or revision
number.
"""
Matt Mackall
revlog: allow retrieving contents by revision number
r16375 if isinstance(nodeorrev, int):
rev = nodeorrev
node = self.node(rev)
else:
node = nodeorrev
rev = None
Matt Mackall
revlog: hold a private reference to self._cache...
r21750 _cache = self._cache # grab local copy of cache to avoid thread race
Benoit Boissinot
revlog.revision(): don't use nullrev as the default value for the cache...
r11996 cachedrev = None
Matt Mackall
revlog: some codingstyle cleanups
r4980 if node == nullid:
return ""
Matt Mackall
revlog: hold a private reference to self._cache...
r21750 if _cache:
if _cache[0] == node:
return _cache[2]
cachedrev = _cache[1]
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
Add some docstrings to revlog.py
r1083 # look up what we need to read
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 text = None
Matt Mackall
revlog: allow retrieving contents by revision number
r16375 if rev is None:
rev = self.rev(node)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Matt Mackall
revlog: move flag checking out of the offset fastpath
r5004 # check rev flags
Vishakh H
revlog: add punched revision flag...
r11745 if self.flags(rev) & ~REVIDX_KNOWN_FLAGS:
Matt Mackall
revlog: more robust for damaged indexes...
r5312 raise RevlogError(_('incompatible revision flag %x') %
Vishakh H
revlog: add punched revision flag...
r11745 (self.flags(rev) & ~REVIDX_KNOWN_FLAGS))
Matt Mackall
revlog: move flag checking out of the offset fastpath
r5004
Benoit Boissinot
revlog.revision(): minor cleanup...
r11995 # build delta chain
Benoit Boissinot
revlog.revision(): inline deltachain computation
r11998 chain = []
Sune Foldager
revlog: calculate base revisions iteratively...
r14252 index = self.index # for performance
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 generaldelta = self._generaldelta
Benoit Boissinot
revlog.revision(): inline deltachain computation
r11998 iterrev = rev
Sune Foldager
revlog: calculate base revisions iteratively...
r14252 e = index[iterrev]
while iterrev != e[3] and iterrev != cachedrev:
Benoit Boissinot
revlog.revision(): inline deltachain computation
r11998 chain.append(iterrev)
Sune Foldager
revlog: support reading generaldelta revlogs...
r14253 if generaldelta:
iterrev = e[3]
else:
iterrev -= 1
Sune Foldager
revlog: calculate base revisions iteratively...
r14252 e = index[iterrev]
Benoit Boissinot
revlog.revision(): minor cleanup...
r11995
Benoit Boissinot
revlog.revision(): inline deltachain computation
r11998 if iterrev == cachedrev:
# cache hit
Matt Mackall
revlog: hold a private reference to self._cache...
r21750 text = _cache[2]
Siddharth Agarwal
revlog: move chunk cache preload from revision to _chunks...
r19716 else:
chain.append(iterrev)
chain.reverse()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Matt Mackall
revlog: drop cache after use to save memory footprint...
r11754 # drop cache to save memory
self._cache = None
Siddharth Agarwal
revlog: move chunk cache preload from revision to _chunks...
r19716 bins = self._chunks(chain)
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 if text is None:
Siddharth Agarwal
revlog: move chunk cache preload from revision to _chunks...
r19716 text = str(bins[0])
bins = bins[1:]
Matt Mackall
revlog: refactor chunk cache interface again...
r8650
Matt Mackall
revlog: eliminate diff and patches functions...
r4989 text = mdiff.patches(text, bins)
Matt Mackall
revlog: break hash checking into subfunction
r13239
Matt Mackall
revlog: pass rev to _checkhash
r13276 text = self._checkhash(text, node, rev)
Matt Mackall
revlog: break hash checking into subfunction
r13239
self._cache = (node, rev, text)
return text
Matt Mackall
revlog: pass rev to _checkhash
r13276 def _checkhash(self, text, node, rev):
Benoit Boissinot
cleanup of revlog.group when repository is local...
r1598 p1, p2 = self.parents(node)
Wojciech Lopata
revlog: extract 'checkhash' method...
r19624 self.checkhash(text, p1, p2, node, rev)
return text
def checkhash(self, text, p1, p2, node, rev=None):
Sune Foldager
revlog: remove support for punched/shallow...
r14196 if node != hash(text, p1, p2):
Wojciech Lopata
revlog: extract 'checkhash' method...
r19624 revornode = rev
if revornode is None:
revornode = templatefilters.short(hex(node))
raise RevlogError(_("integrity check failed on %s:%s")
% (self.indexfile, revornode))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mason@suse.com
Make the appendfile class inline-data index friendly...
r2075 def checkinlinesize(self, tr, fp=None):
Greg Ward
revlog: factor out _maxinline global....
r10913 if not self._inline or (self.start(-2) + self.length(-2)) < _maxinline:
mason@suse.com
Implement data inlined with the index file...
r2073 return
Matt Mackall
revlog: use index to find index size
r8315
Chris Mason
...
r2084 trinfo = tr.find(self.indexfile)
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if trinfo is None:
Thomas Arendsen Hein
Indentation cleanups for 2956948b81f3.
r3680 raise RevlogError(_("%s not found in the transaction")
% self.indexfile)
Chris Mason
...
r2084
trindex = trinfo[2]
dataoff = self.start(trindex)
tr.add(self.datafile, dataoff)
Matt Mackall
revlog: use index to find index size
r8315
Matt Mackall
revlog: use chunk cache to avoid rereading when splitting inline files
r8317 if fp:
fp.flush()
fp.close()
Matt Mackall
revlog: use index to find index size
r8315
mason@suse.com
Implement data inlined with the index file...
r2073 df = self.opener(self.datafile, 'w')
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 try:
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for r in self:
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 df.write(self._chunkraw(r, r))
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 finally:
df.close()
mason@suse.com
Create an atomic opener that does not automatically rename on close...
r2076 fp = self.opener(self.indexfile, 'w', atomictemp=True)
mason@suse.com
Implement data inlined with the index file...
r2073 self.version &= ~(REVLOGNGINLINEDATA)
Matt Mackall
revlog: change _inline from a function to a variable
r4982 self._inline = False
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for i in self:
Alexis S. L. Carvalho
revlog: fix revlogio.packentry corner case...
r5338 e = self._io.packentry(self.index[i], self.node, self.version, i)
mason@suse.com
Implement data inlined with the index file...
r2073 fp.write(e)
Greg Ward
atomictempfile: make close() consistent with other file-like objects....
r15057 # if we don't call close, the temp file will never replace the
mason@suse.com
Create an atomic opener that does not automatically rename on close...
r2076 # real index
Greg Ward
atomictempfile: make close() consistent with other file-like objects....
r15057 fp.close()
Chris Mason
...
r2084
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 tr.replace(self.indexfile, trindex * self._io.size)
self._chunkclear()
mason@suse.com
Implement data inlined with the index file...
r2073
Wojciech Lopata
revlog: pass node as an argument of addrevision...
r19625 def addrevision(self, text, transaction, link, p1, p2, cachedelta=None,
node=None):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """add a revision to the log
text - the revision data to add
transaction - the transaction object used for rollback
link - the linkrev data to add
p1, p2 - the parent nodeids of the revision
Benoit Boissinot
revlog: fix docstring
r12012 cachedelta - an optional precomputed delta
Wojciech Lopata
revlog: pass node as an argument of addrevision...
r19625 node - nodeid of revision; typically node is not specified, and it is
computed by default as hash(text, p1, p2), however subclasses might
use different hashing method (and override checkhash() in such case)
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """
Durham Goode
revlog: add exception when linkrev == nullrev...
r19326 if link == nullrev:
raise RevlogError(_("attempted to add linkrev -1 to %s")
% self.indexfile)
Wojciech Lopata
revlog: pass node as an argument of addrevision...
r19625 node = node or hash(text, p1, p2)
Sune Foldager
revlog: remove support for punched/shallow...
r14196 if node in self.nodemap:
Benoit Boissinot
revlog.addrevision(): move computation of nodeid in addrevision()...
r12023 return node
Matt Mackall
revlog: simplify addrevision...
r4981 dfh = None
Matt Mackall
revlog: change _inline from a function to a variable
r4982 if not self._inline:
Alexis S. L. Carvalho
make revlog.addgroup pass its file handles to addrevision...
r3390 dfh = self.opener(self.datafile, "a")
ifh = self.opener(self.indexfile, "a+")
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 try:
Benoit Boissinot
revlog.addrevision(): move computation of nodeid in addrevision()...
r12023 return self._addrevision(node, text, transaction, link, p1, p2,
Benoit Boissinot
revlog._addrevision(): make the parent of the cached delta explicit
r11962 cachedelta, ifh, dfh)
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 finally:
if dfh:
dfh.close()
ifh.close()
Alexis S. L. Carvalho
make revlog.addgroup pass its file handles to addrevision...
r3390
Bryan O'Sullivan
revlog: make compress a method...
r17128 def compress(self, text):
""" generate a possibly-compressed representation of text """
if not text:
return ("", text)
l = len(text)
bin = None
if l < 44:
pass
elif l > 1000000:
# zlib makes an internal copy, thus doubling memory usage for
# large files, so lets do this in pieces
z = zlib.compressobj()
p = []
pos = 0
while pos < l:
pos2 = pos + 2**20
p.append(z.compress(text[pos:pos2]))
pos = pos2
p.append(z.flush())
if sum(map(len, p)) < l:
bin = "".join(p)
else:
bin = _compress(text)
if bin is None or len(bin) > l:
if text[0] == '\0':
return ("", text)
return ('u', text)
return ("", bin)
Benoit Boissinot
revlog.addrevision(): move computation of nodeid in addrevision()...
r12023 def _addrevision(self, node, text, transaction, link, p1, p2,
Benoit Boissinot
revlog._addrevision(): make the parent of the cached delta explicit
r11962 cachedelta, ifh, dfh):
Sune Foldager
revlog: add docstring to _addrevision
r14292 """internal function to add revisions to the log
Benoit Boissinot
revlog._addrevision(): allow text argument to be None, build it lazily
r12623
Sune Foldager
revlog: add docstring to _addrevision
r14292 see addrevision for argument descriptions.
invariants:
- text is optional (can be None); if not set, cachedelta must be set.
Mads Kiilerich
fix trivial spelling errors
r17424 if both are set, they must correspond to each other.
Sune Foldager
revlog: add docstring to _addrevision
r14292 """
Matt Mackall
revlog: fix buildtext local scope...
r12886 btext = [text]
def buildtext():
if btext[0] is not None:
return btext[0]
Benoit Boissinot
revlog._addrevision(): allow text argument to be None, build it lazily
r12623 # flush any pending writes here so we can read it in revision
if dfh:
dfh.flush()
ifh.flush()
basetext = self.revision(self.node(cachedelta[0]))
Matt Mackall
revlog: fix buildtext local scope...
r12886 btext[0] = mdiff.patch(basetext, cachedelta[1])
Wojciech Lopata
revlog: extract 'checkhash' method...
r19624 self.checkhash(btext[0], p1, p2, node)
Matt Mackall
revlog: fix buildtext local scope...
r12886 return btext[0]
Benoit Boissinot
revlog._addrevision(): allow text argument to be None, build it lazily
r12623
Matt Mackall
revlog: extract delta building to a subfunction
r12888 def builddelta(rev):
# can we use the cached delta?
if cachedelta and cachedelta[0] == rev:
delta = cachedelta[1]
else:
t = buildtext()
ptext = self.revision(self.node(rev))
delta = mdiff.textdiff(ptext, t)
Bryan O'Sullivan
revlog: make compress a method...
r17128 data = self.compress(delta)
Matt Mackall
revlog: extract delta building to a subfunction
r12888 l = len(data[1]) + len(data[0])
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 if basecache[0] == rev:
Sune Foldager
revlog: support writing generaldelta revlogs...
r14270 chainbase = basecache[1]
Sune Foldager
revlog: calculate base revisions iteratively...
r14252 else:
Sune Foldager
revlog: support writing generaldelta revlogs...
r14270 chainbase = self.chainbase(rev)
Matt Mackall
backout e7167007c083...
r17150 dist = l + offset - self.start(chainbase)
Sune Foldager
revlog: support writing generaldelta revlogs...
r14270 if self._generaldelta:
base = rev
else:
base = chainbase
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 return dist, l, data, base, chainbase
Matt Mackall
revlog: extract delta building to a subfunction
r12888
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 curr = len(self)
Matt Mackall
revlog: simplify addrevision...
r4981 prev = curr - 1
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 base = chainbase = curr
Matt Mackall
revlog: simplify addrevision...
r4981 offset = self.end(prev)
Pradeepkumar Gayam
revlog: append delta against p1
r11931 flags = 0
Benoit Boissinot
revlog._addrevision(): make the parent of the cached delta explicit
r11962 d = None
Wojciech Lopata
generaldelta: initialize basecache properly...
r19764 if self._basecache is None:
self._basecache = (prev, self.chainbase(prev))
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 basecache = self._basecache
Matt Mackall
revlog: precalculate p1 and p2 revisions
r12889 p1r, p2r = self.rev(p1), self.rev(p2)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Benoit Boissinot
parendelta: fix computation of base rev (fixes issue2337)...
r11963 # should we try to build a delta?
Matt Mackall
revlog: choose best delta for parentdelta (issue2466)...
r12890 if prev != nullrev:
Sune Foldager
revlog: support writing generaldelta revlogs...
r14270 if self._generaldelta:
Sune Foldager
revlog: improve delta generation heuristics for generaldelta...
r14301 if p1r >= basecache[1]:
d = builddelta(p1r)
elif p2r >= basecache[1]:
d = builddelta(p2r)
else:
d = builddelta(prev)
Sune Foldager
revlog: support writing generaldelta revlogs...
r14270 else:
d = builddelta(prev)
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 dist, l, data, base, chainbase = d
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
# full versions are inserted when the needed deltas
# become comparable to the uncompressed text
Benoit Boissinot
revlog._addrevision(): allow text argument to be None, build it lazily
r12623 if text is None:
textlen = mdiff.patchedsize(self.rawsize(cachedelta[0]),
cachedelta[1])
else:
textlen = len(text)
Sune Foldager
revlog: remove support for punched/shallow...
r14196 if d is None or dist > textlen * 2:
Matt Mackall
revlog: fix buildtext local scope...
r12886 text = buildtext()
Bryan O'Sullivan
revlog: make compress a method...
r17128 data = self.compress(text)
mason@suse.com
Reduce string duplication in compression code...
r1533 l = len(data[1]) + len(data[0])
Sune Foldager
revlog: fix bug in chainbase cache...
r14296 base = chainbase = curr
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Benoit Boissinot
revlog._addrevision(): allow text argument to be None, build it lazily
r12623 e = (offset_type(offset, flags), l, textlen,
Matt Mackall
revlog: precalculate p1 and p2 revisions
r12889 base, link, p1r, p2r, node)
Matt Mackall
revlog: add a magic null revision to our index...
r4979 self.index.insert(-1, e)
Matt Mackall
revlog: simplify addrevision...
r4981 self.nodemap[node] = curr
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977
Alexis S. L. Carvalho
revlog: fix revlogio.packentry corner case...
r5338 entry = self._io.packentry(e, self.node, self.version, curr)
Durham Goode
revlog: move file writing to a separate function...
r20217 self._writeentry(transaction, ifh, dfh, entry, data, link, offset)
if type(text) == str: # only accept immutable objects
self._cache = (node, curr, text)
self._basecache = (curr, chainbase)
return node
def _writeentry(self, transaction, ifh, dfh, entry, data, link, offset):
curr = len(self) - 1
Matt Mackall
revlog: change _inline from a function to a variable
r4982 if not self._inline:
mason@suse.com
Implement data inlined with the index file...
r2073 transaction.add(self.datafile, offset)
Matt Mackall
revlog: simplify addrevision...
r4981 transaction.add(self.indexfile, curr * len(entry))
mason@suse.com
Implement data inlined with the index file...
r2073 if data[0]:
Alexis S. L. Carvalho
make revlog.addgroup pass its file handles to addrevision...
r3390 dfh.write(data[0])
dfh.write(data[1])
dfh.flush()
Matt Mackall
revlog: simplify addrevision...
r4981 ifh.write(entry)
mason@suse.com
Implement data inlined with the index file...
r2073 else:
Matt Mackall
revlog: avoid some unnecessary seek/tell syscalls
r4996 offset += curr * self._io.size
Patrick Mezard
revlog: fix inlined revision transaction extra data (issue 749)
r5324 transaction.add(self.indexfile, offset, curr)
Matt Mackall
revlog: simplify addrevision...
r4981 ifh.write(entry)
Alexis S. L. Carvalho
make revlog.addgroup pass its file handles to addrevision...
r3390 ifh.write(data[0])
ifh.write(data[1])
self.checkinlinesize(transaction, ifh)
mason@suse.com
Implement data inlined with the index file...
r2073
Matt Mackall
bundle: get rid of chunkiter
r12335 def addgroup(self, bundle, linkmapper, transaction):
mpm@selenic.com
Add some docstrings to revlog.py
r1083 """
add a delta group
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
Add some docstrings to revlog.py
r1083 given a set of deltas, add them to the revision log. the
first delta is against its parent, which should be in our
log, the rest are against the previous delta.
"""
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 # track the base of the current delta log
Pierre-Yves David
revlog: make addgroup returns a list of node contained in the added source...
r15890 content = []
Thomas Arendsen Hein
Calling revlog.addgroup with an empty changegroup now raises RevlogError....
r2002 node = None
mpm@selenic.com
Whitespace cleanups...
r515
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 r = len(self)
end = 0
mpm@selenic.com
Add changegroup support
r46 if r:
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 end = self.end(r - 1)
mason@suse.com
Implement revlogng....
r2072 ifh = self.opener(self.indexfile, "a+")
Matt Mackall
revlog: avoid some unnecessary seek/tell syscalls
r4996 isize = r * self._io.size
Matt Mackall
revlog: change _inline from a function to a variable
r4982 if self._inline:
Matt Mackall
revlog: avoid some unnecessary seek/tell syscalls
r4996 transaction.add(self.indexfile, end + isize, r)
mason@suse.com
Implement data inlined with the index file...
r2073 dfh = None
else:
Matt Mackall
revlog: avoid some unnecessary seek/tell syscalls
r4996 transaction.add(self.indexfile, isize, r)
mason@suse.com
Implement data inlined with the index file...
r2073 transaction.add(self.datafile, end)
dfh = self.opener(self.datafile, "a")
mpm@selenic.com
Add changegroup support
r46
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 try:
# loop through our set of deltas
chain = None
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 while True:
Benoit Boissinot
unbundler: separate delta and header parsing...
r14144 chunkdata = bundle.deltachunk(chain)
Matt Mackall
bundle: move chunk parsing into unbundle class
r12336 if not chunkdata:
Matt Mackall
bundle: get rid of chunkiter
r12335 break
Matt Mackall
bundle: move chunk parsing into unbundle class
r12336 node = chunkdata['node']
p1 = chunkdata['p1']
p2 = chunkdata['p2']
cs = chunkdata['cs']
Benoit Boissinot
bundler: make parsechunk return the base revision of the delta
r14141 deltabase = chunkdata['deltabase']
delta = chunkdata['delta']
Matt Mackall
bundle: move chunk parsing into unbundle class
r12336
Pierre-Yves David
revlog: make addgroup returns a list of node contained in the added source...
r15890 content.append(node)
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 link = linkmapper(cs)
Sune Foldager
revlog: remove support for punched/shallow...
r14196 if node in self.nodemap:
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 # this can happen if two branches make the same change
chain = node
continue
mpm@selenic.com
Changes to network protocol...
r192
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 for p in (p1, p2):
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 if p not in self.nodemap:
Sune Foldager
revlog: remove support for punched/shallow...
r14196 raise LookupError(p, self.indexfile,
_('unknown parent'))
mpm@selenic.com
Add changegroup support
r46
Benoit Boissinot
bundler: make parsechunk return the base revision of the delta
r14141 if deltabase not in self.nodemap:
raise LookupError(deltabase, self.indexfile,
_('unknown delta base'))
mpm@selenic.com
Add changegroup support
r46
Benoit Boissinot
bundler: make parsechunk return the base revision of the delta
r14141 baserev = self.rev(deltabase)
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 chain = self._addrevision(node, None, transaction, link,
Benoit Boissinot
bundler: make parsechunk return the base revision of the delta
r14141 p1, p2, (baserev, delta), ifh, dfh)
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 if not dfh and not self._inline:
# addrevision switched from inline to conventional
# reopen the index
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 ifh.close()
Benoit Boissinot
revlog.addgroup(): always use _addrevision() to add new revlog entries...
r12624 dfh = self.opener(self.datafile, "a")
ifh = self.opener(self.indexfile, "a")
Benoit Boissinot
revlog: make sure the files are closed after an exception happens...
r6261 finally:
if dfh:
dfh.close()
ifh.close()
mpm@selenic.com
Add changegroup support
r46
Pierre-Yves David
revlog: make addgroup returns a list of node contained in the added source...
r15890 return content
Matt Mackall
verify: add check for mismatch of index and data length
r1493
Durham Goode
strip: add faster revlog strip computation...
r20074 def getstrippoint(self, minlink):
"""find the minimum rev that must be stripped to strip the linkrev
Returns a tuple containing the minimum rev and a set of all revs that
have linkrevs that will be broken by this strip.
"""
brokenrevs = set()
strippoint = len(self)
heads = {}
futurelargelinkrevs = set()
for head in self.headrevs():
headlinkrev = self.linkrev(head)
heads[head] = headlinkrev
if headlinkrev >= minlink:
futurelargelinkrevs.add(headlinkrev)
# This algorithm involves walking down the rev graph, starting at the
# heads. Since the revs are topologically sorted according to linkrev,
# once all head linkrevs are below the minlink, we know there are
# no more revs that could have a linkrev greater than minlink.
# So we can stop walking.
while futurelargelinkrevs:
strippoint -= 1
linkrev = heads.pop(strippoint)
if linkrev < minlink:
brokenrevs.add(strippoint)
else:
futurelargelinkrevs.remove(linkrev)
for p in self.parentrevs(strippoint):
if p != nullrev:
plinkrev = self.linkrev(p)
heads[p] = plinkrev
if plinkrev >= minlink:
futurelargelinkrevs.add(plinkrev)
return strippoint, brokenrevs
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 def strip(self, minlink, transaction):
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 """truncate the revlog on the first revision with a linkrev >= minlink
This function is called when we're stripping revision minlink and
its descendants from the repository.
We have to remove all revisions with linkrev >= minlink, because
the equivalent changelog revisions will be renumbered after the
strip.
So we truncate the revlog on the first of these revisions, and
trust that the caller has saved the revisions that shouldn't be
Steven Brown
revlog: clarify strip docstring "readd" -> "re-add"...
r15827 removed and that it'll re-add them after this truncation.
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 """
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if len(self) == 0:
mason@suse.com
Add revlog.strip to truncate away revisions....
r1535 return
Durham Goode
strip: add faster revlog strip computation...
r20074 rev, _ = self.getstrippoint(minlink)
if rev == len(self):
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 return
mason@suse.com
Add revlog.strip to truncate away revisions....
r1535
# first truncate the files on disk
end = self.start(rev)
Matt Mackall
revlog: change _inline from a function to a variable
r4982 if not self._inline:
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 transaction.add(self.datafile, end)
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 end = rev * self._io.size
mason@suse.com
Implement data inlined with the index file...
r2073 else:
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 end += rev * self._io.size
mason@suse.com
Implement revlogng....
r2072
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 transaction.add(self.indexfile, end)
mason@suse.com
Add revlog.strip to truncate away revisions....
r1535
# then reset internal state in memory to forget those revisions
Matt Mackall
revlog: mark cache private
r4984 self._cache = None
Matt Mackall
revlog: refactor chunk cache interface again...
r8650 self._chunkclear()
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for x in xrange(rev, len(self)):
mason@suse.com
Implement revlogng....
r2072 del self.nodemap[self.node(x)]
mason@suse.com
Add revlog.strip to truncate away revisions....
r1535
Matt Mackall
revlog: add a magic null revision to our index...
r4979 del self.index[rev:-1]
mason@suse.com
Add revlog.strip to truncate away revisions....
r1535
Matt Mackall
verify: add check for mismatch of index and data length
r1493 def checksize(self):
expected = 0
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if len(self):
expected = max(0, self.end(len(self) - 1))
Matt Mackall
verify: notice extra data in indices
r1667
Matt Mackall
Handle empty logs in repo.checksize
r1494 try:
f = self.opener(self.datafile)
f.seek(0, 2)
actual = f.tell()
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Matt Mackall
verify: notice extra data in indices
r1667 dd = actual - expected
Matt Mackall
Handle empty logs in repo.checksize
r1494 except IOError, inst:
Matt Mackall
verify: notice extra data in indices
r1667 if inst.errno != errno.ENOENT:
raise
dd = 0
try:
f = self.opener(self.indexfile)
f.seek(0, 2)
actual = f.tell()
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Matt Mackall
revlog: parse revlogv0 indexes into v1 internally...
r4977 s = self._io.size
Alejandro Santos
compat: use // for integer division
r9029 i = max(0, actual // s)
Matt Mackall
verify: notice extra data in indices
r1667 di = actual - (i * s)
Matt Mackall
revlog: change _inline from a function to a variable
r4982 if self._inline:
mason@suse.com
Implement data inlined with the index file...
r2073 databytes = 0
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for r in self:
Matt Mackall
revlog: more robust for damaged indexes...
r5312 databytes += max(0, self.length(r))
mason@suse.com
Implement data inlined with the index file...
r2073 dd = 0
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 di = actual - len(self) * s - databytes
Matt Mackall
verify: notice extra data in indices
r1667 except IOError, inst:
if inst.errno != errno.ENOENT:
raise
di = 0
return (dd, di)
Adrian Buehlmann
revlog: add files method
r6891
def files(self):
Matt Mackall
many, many trivial check-code fixups
r10282 res = [self.indexfile]
Adrian Buehlmann
revlog: add files method
r6891 if not self._inline:
res.append(self.datafile)
return res