From patchwork Mon Mar 30 00:10:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [1,of,2] repoview: move function for computing filtered hash From: Gregory Szorc X-Patchwork-Id: 8363 Message-Id: <2e21d3312350ce63785c.1427674217@vm-ubuntu-main.gateway.sonic.net> To: mercurial-devel@selenic.com Date: Sun, 29 Mar 2015 17:10:17 -0700 # HG changeset patch # User Gregory Szorc # Date 1427662441 25200 # Sun Mar 29 13:54:01 2015 -0700 # Node ID 2e21d3312350ce63785cda82526c951211e76bab # Parent efa094701a05d58d505c3b0c3b3c73dba4e51e97 repoview: move function for computing filtered hash An upcoming patch will establish per-filter tags caches. We'll want to use the same cache validation logic as the branch cache. Prepare for that by moving the logic for computing a filtered view hash to somewhere central. diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py --- a/mercurial/branchmap.py +++ b/mercurial/branchmap.py @@ -6,8 +6,9 @@ # GNU General Public License version 2 or any later version. from node import bin, hex, nullid, nullrev import encoding +import repoview import util import time from array import array from struct import calcsize, pack, unpack @@ -135,37 +136,17 @@ class branchcache(dict): self._closednodes = set() else: self._closednodes = closednodes - def _hashfiltered(self, repo): - """build hash of revision filtered in the current cache - - Tracking tipnode and tiprev is not enough to ensure validity of the - cache as they do not help to distinct cache that ignored various - revision bellow tiprev. - - To detect such difference, we build a cache of all ignored revisions. - """ - cl = repo.changelog - if not cl.filteredrevs: - return None - key = None - revs = sorted(r for r in cl.filteredrevs if r <= self.tiprev) - if revs: - s = util.sha1() - for rev in revs: - s.update('%s;' % rev) - key = s.digest() - return key - def validfor(self, repo): """Is the cache content valid regarding a repo - False when cached tipnode is unknown or if we detect a strip. - True when cache is up to date or a subset of current repo.""" try: return ((self.tipnode == repo.changelog.node(self.tiprev)) - and (self.filteredhash == self._hashfiltered(repo))) + and (self.filteredhash == \ + repoview.filteredhash(repo, self.tiprev))) except IndexError: return False def _branchtip(self, heads): @@ -282,9 +263,9 @@ class branchcache(dict): tiprev = max(cl.rev(node) for node in heads) if tiprev > self.tiprev: self.tipnode = cl.node(tiprev) self.tiprev = tiprev - self.filteredhash = self._hashfiltered(repo) + self.filteredhash = repoview.filteredhash(repo, self.tiprev) duration = time.time() - starttime repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n', repo.filtername, duration) diff --git a/mercurial/repoview.py b/mercurial/repoview.py --- a/mercurial/repoview.py +++ b/mercurial/repoview.py @@ -71,8 +71,32 @@ def cachehash(repo, hideable): h.update(''.join(repo.heads())) h.update(str(hash(frozenset(hideable)))) return h.digest() +def filteredhash(repo, maxrev): + """build hash of filtered revisions in the current repoview. + + Multiple caches perform up-to-date validation by checking that the + tiprev and tipnode stored in the cache file match the current repository. + However, this is not sufficient for validating repoviews because the set + of revisions in the view may change without the repository tiprev and + tipnode changing. + + This function hashes all the revs filtered from the view and returns + that SHA-1 digest. + """ + cl = repo.changelog + if not cl.filteredrevs: + return None + key = None + revs = sorted(r for r in cl.filteredrevs if r <= maxrev) + if revs: + s = util.sha1() + for rev in revs: + s.update('%s;' % rev) + key = s.digest() + return key + def _writehiddencache(cachefile, cachehash, hidden): """write hidden data to a cache file""" data = struct.pack('>%ii' % len(hidden), *sorted(hidden)) cachefile.write(struct.pack(">H", cacheversion))