[PATCH 4 of 8 filtering] clfilter: decorate several repository methods as unfiltered
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Tue Nov 20 18:11:36 CST 2012
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
# Date 1353455266 -3600
# Node ID 716cc4279f1ad69dde9a918508a11271e56b5212
# Parent 4ae17fd97c2b3e0f9972c9cc093a3bc5e77c3f67
clfilter: decorate several repository methods as unfiltered
Some core method of repo need to run on unfiltered version of repository. This
includes:
- logic writing data to the changelog,
- logic computing global cache on the whole set of revision presente in the
repo.
This changeset introduce an `unfilteredmeth` decorators to decorate
localrepomethod that MUST NOT be run on the proxy version.
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -21,10 +21,16 @@ filecache = scmutil.filecache
class storecache(filecache):
"""filecache for files in the store"""
def join(self, obj, fname):
return obj.sjoin(fname)
+def unfilteredmeth(orig):
+ """decorate method that always need to be run on unfiltered version"""
+ def wrapper(repo, *args, **kwargs):
+ return orig(repo.unfiltered(), *args, **kwargs)
+ return wrapper
+
MODERNCAPS = set(('lookup', 'branchmap', 'pushkey', 'known', 'getbundle'))
LEGACYCAPS = MODERNCAPS.union(set(['changegroupsubset']))
class localpeer(peer.peerrepository):
'''peer for a local repo; reflects only the most recent API'''
@@ -386,10 +392,11 @@ class localrepository(object):
return 'file:' + self.root
def hook(self, name, throw=False, **args):
return hook.hook(self.ui, self, name, throw, **args)
+ @unfilteredmeth
def _tag(self, names, node, message, local, user, date, extra={}):
if isinstance(names, str):
names = (names,)
branches = self.branchmap()
@@ -605,10 +612,11 @@ class localrepository(object):
self._updatebranchcache(partial, ctxgen)
self._writebranchcache(partial, self.changelog.tip(), tiprev)
return partial
+ @unfilteredmeth # Until we get a smarter cache management
def updatebranchcache(self):
tip = self.changelog.tip()
if self._branchcache is not None and self._branchcachetip == tip:
return
@@ -657,10 +665,11 @@ class localrepository(object):
bt = {}
for bn, heads in self.branchmap().iteritems():
bt[bn] = self._branchtip(heads)
return bt
+ @unfilteredmeth # Until we get a smarter cache management
def _readbranchcache(self):
partial = {}
try:
f = self.opener("cache/branchheads")
lines = f.read().split('\n')
@@ -689,10 +698,11 @@ class localrepository(object):
if self.ui.debugflag:
self.ui.warn(str(inst), '\n')
partial, last, lrev = {}, nullid, nullrev
return partial, last, lrev
+ @unfilteredmeth # Until we get a smarter cache management
def _writebranchcache(self, branches, tip, tiprev):
try:
f = self.opener("cache/branchheads", "w", atomictemp=True)
f.write("%s %s\n" % (hex(tip), tiprev))
for label, nodes in branches.iteritems():
@@ -700,10 +710,11 @@ class localrepository(object):
f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
f.close()
except (IOError, OSError):
pass
+ @unfilteredmeth # Until we get a smarter cache management
def _updatebranchcache(self, partial, ctxgen):
"""Given a branchhead cache, partial, that may have extra nodes or be
missing heads, and a generator of nodes that are at least a superset of
heads missing, this function updates partial to be correct.
"""
@@ -965,10 +976,11 @@ class localrepository(object):
self.ui.warn(_("no rollback information available\n"))
return 1
finally:
release(lock, wlock)
+ @unfilteredmeth # Until we get a smarter cache management
def _rollback(self, dryrun, force):
ui = self.ui
try:
args = self.opener.read('undo.desc').splitlines()
(oldlen, desc, detail) = (int(args[0]), args[1], None)
@@ -1043,12 +1055,12 @@ class localrepository(object):
except AttributeError:
pass
delcache('_tagscache')
- self._branchcache = None # in UTF-8
- self._branchcachetip = None
+ self.unfiltered()._branchcache = None # in UTF-8
+ self.unfiltered()._branchcachetip = None
obsolete.clearobscaches(self)
def invalidatedirstate(self):
'''Invalidates the dirstate, causing the next call to dirstate
to check if it was modified since the last time it was read,
@@ -1062,20 +1074,20 @@ class localrepository(object):
for k in self.dirstate._filecache:
try:
delattr(self.dirstate, k)
except AttributeError:
pass
- delattr(self, 'dirstate')
+ delattr(self.unfiltered(), 'dirstate')
def invalidate(self):
+ unfiltered = self.unfiltered() # all filecache are store on unfiltered
for k in self._filecache:
# dirstate is invalidated separately in invalidatedirstate()
if k == 'dirstate':
continue
-
try:
- delattr(self, k)
+ delattr(unfiltered, k)
except AttributeError:
pass
self.invalidatecaches()
def _lock(self, lockname, wait, releasefn, acquirefn, desc):
@@ -1225,10 +1237,11 @@ class localrepository(object):
if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
changelist.append(fname)
return fparent1
+ @unfilteredmeth
def commit(self, text="", user=None, date=None, match=None, force=False,
editor=False, extra={}):
"""Add a new revision to current repository.
Revision information is gathered from the working directory,
@@ -1395,10 +1408,11 @@ class localrepository(object):
def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
self.hook("commit", node=node, parent1=parent1, parent2=parent2)
self._afterlock(commithook)
return ret
+ @unfilteredmeth
def commitctx(self, ctx, error=False):
"""Add a new revision to current repository.
Revision information is passed via the context argument.
"""
@@ -1476,10 +1490,11 @@ class localrepository(object):
finally:
if tr:
tr.release()
lock.release()
+ @unfilteredmeth
def destroyed(self, newheadnodes=None):
'''Inform the repository that nodes have been destroyed.
Intended for use by strip and rollback, so there's a common
place for anything that has to be done after destroying history.
@@ -2069,10 +2084,11 @@ class localrepository(object):
if not heads:
heads = cl.heads()
return self.getlocalbundle(source,
discovery.outgoing(cl, common, heads))
+ @unfilteredmeth
def _changegroupsubset(self, commonrevs, csets, heads, source):
cl = self.changelog
mf = self.manifest
mfs = {} # needed manifests
@@ -2180,10 +2196,11 @@ class localrepository(object):
def changegroup(self, basenodes, source):
# to avoid a race we use changegroupsubset() (issue1320)
return self.changegroupsubset(basenodes, self.heads(), source)
+ @unfilteredmeth
def _changegroup(self, nodes, source):
"""Compute the changegroup of all nodes that we have that a recipient
doesn't. Return a chunkbuffer object whose read() method will return
successive changegroup chunks.
@@ -2273,10 +2290,11 @@ class localrepository(object):
if nodes:
self.hook('outgoing', node=hex(nodes[0]), source=source)
return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
+ @unfilteredmeth
def addchangegroup(self, source, srctype, url, emptyok=False):
"""Add the changegroup returned by source.read() to this repo.
srctype is a string like 'push', 'pull', or 'unbundle'. url is
the URL of the repo where this changegroup is coming from.
More information about the Mercurial-devel
mailing list