[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