# HG changeset patch # User Gregory Szorc # Date 1499368853 25200 # Node ID 36a415b5a4b2c012d61b171cb3bf91c9cd8fdd29 # Parent ca4b78eb11e7a67600e85784df4da2655351b6d2 localrepo: add sparse caches The sparse extension maintains caches for the sparse files to a signature and a signature to a matcher. This allows the sparse matchers to be resolved quickly, which is apparently something that can occur in loops. This patch ports the sparse caches to the localrepo class pretty much as-is. There is potentially room to improve the caching mechanism. But that can be done as a follow-up. The default invalidatecaches() now clears the relevant sparse cache. invalidatesignaturecache() has been moved to sparse.py. diff -r ca4b78eb11e7 -r 36a415b5a4b2 hgext/sparse.py --- a/hgext/sparse.py Thu Jul 06 12:26:04 2017 -0700 +++ b/hgext/sparse.py Thu Jul 06 12:20:53 2017 -0700 @@ -421,7 +421,7 @@ """Returns the signature string representing the contents of the current project sparse configuration. This can be used to cache the sparse matcher for a given set of revs.""" - signaturecache = self.signaturecache + signaturecache = self._sparsesignaturecache signature = signaturecache.get('signature') if includetemp: tempsignature = signaturecache.get('tempsignature') @@ -445,13 +445,6 @@ signaturecache['tempsignature'] = tempsignature return '%s %s' % (str(signature), str(tempsignature)) - def invalidatecaches(self): - self.invalidatesignaturecache() - return super(SparseRepo, self).invalidatecaches() - - def invalidatesignaturecache(self): - self.signaturecache.clear() - def sparsematch(self, *revs, **kwargs): """Returns the sparse match function for the given revs. @@ -470,7 +463,7 @@ key = '%s %s' % (str(signature), ' '.join([str(r) for r in revs])) - result = self.sparsecache.get(key, None) + result = self._sparsematchercache.get(key, None) if result: return result @@ -513,7 +506,7 @@ tempincludes = self.gettemporaryincludes() result = forceincludematcher(result, tempincludes) - self.sparsecache[key] = result + self._sparsematchercache[key] = result return result @@ -523,7 +516,7 @@ '\n'.join(sorted(include)), '\n'.join(sorted(exclude))) self.vfs.write("sparse", raw) - self.invalidatesignaturecache() + sparse.invalidatesignaturecache(self) def addtemporaryincludes(self, files): includes = self.gettemporaryincludes() @@ -541,7 +534,7 @@ def _writetemporaryincludes(self, includes): raw = '\n'.join(sorted(includes)) self.vfs.write('tempsparse', raw) - self.invalidatesignaturecache() + sparse.invalidatesignaturecache(self) def prunetemporaryincludes(self): if repo.vfs.exists('tempsparse'): @@ -572,15 +565,14 @@ dirstate.drop(file) self.vfs.unlink('tempsparse') - self.invalidatesignaturecache() + sparse.invalidatesignaturecache(self) msg = _("cleaned up %d temporarily added file(s) from the " "sparse checkout\n") ui.status(msg % len(tempincludes)) if 'dirstate' in repo._filecache: repo.dirstate.repo = repo - repo.sparsecache = {} - repo.signaturecache = {} + repo.__class__ = SparseRepo @command('^debugsparse', [ diff -r ca4b78eb11e7 -r 36a415b5a4b2 mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Jul 06 12:26:04 2017 -0700 +++ b/mercurial/localrepo.py Thu Jul 06 12:20:53 2017 -0700 @@ -422,6 +422,11 @@ # generic mapping between names and nodes self.names = namespaces.namespaces() + # Key to signature value. + self._sparsesignaturecache = {} + # Signature to cached matcher instance. + self._sparsematchercache = {} + def close(self): self._writecaches() @@ -1300,6 +1305,7 @@ self.unfiltered()._branchcaches.clear() self.invalidatevolatilesets() + self._sparsesignaturecache.clear() def invalidatevolatilesets(self): self.filteredrevcache.clear() diff -r ca4b78eb11e7 -r 36a415b5a4b2 mercurial/sparse.py --- a/mercurial/sparse.py Thu Jul 06 12:26:04 2017 -0700 +++ b/mercurial/sparse.py Thu Jul 06 12:20:53 2017 -0700 @@ -126,3 +126,6 @@ profiles.update(patternsforrev(repo, rev)[2]) return profiles + +def invalidatesignaturecache(repo): + repo._sparsesignaturecache.clear()