Patchwork [10,of,10,V2] branchmap: move validity logic in the object itself

login
register
mail settings
Submitter Pierre-Yves David
Date Dec. 24, 2012, 1:53 a.m.
Message ID <db25bf1dc828f29ef0b5.1356314022@yamac.lan>
Download mbox | patch
Permalink /patch/288/
State Accepted
Commit db25bf1dc828f29ef0b5de6b7022c082c153a419
Headers show

Comments

Pierre-Yves David - Dec. 24, 2012, 1:53 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
# Date 1356313799 -3600
# Node ID db25bf1dc828f29ef0b5de6b7022c082c153a419
# Parent  f0eeb9b3444aaf4934a03cff079337377bec7737
branchmap: move validity logic in the object itself

In several place, We check if a branchcache is still valid regarding the current
state of the repository. This changeset puts this logic in a method of the object
that can be reused when necessary.

A branch map is considered valid whenever it is up to date or a strict subset of
the repository state.

The change will help making branchcache aware of filtered revision.

The change in keyword is expected. the branch cache is actually invalid after
the amend. The previous check did not detected it.

Patch

diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -7,22 +7,22 @@ 
 
 from node import bin, hex, nullid, nullrev
 import encoding
 
 def read(repo):
-    partial = branchcache()
     try:
         f = repo.opener("cache/branchheads")
         lines = f.read().split('\n')
         f.close()
     except (IOError, OSError):
         return branchcache()
 
     try:
         last, lrev = lines.pop(0).split(" ", 1)
         last, lrev = bin(last), int(lrev)
-        if lrev >= len(repo) or repo[lrev].node() != last:
+        partial = branchcache(tipnode=last, tiprev=lrev)
+        if not partial.validfor(repo):
             # invalidate the cache
             raise ValueError('invalidating branch cache (tip differs)')
         for l in lines:
             if not l:
                 continue
@@ -30,12 +30,10 @@  def read(repo):
             label = encoding.tolocal(label.strip())
             if not node in repo:
                 raise ValueError('invalidating branch cache because node '+
                                  '%s does not exist' % node)
             partial.setdefault(label, []).append(bin(node))
-        partial.tipnode = last
-        partial.tiprev = lrev
     except KeyboardInterrupt:
         raise
     except Exception, inst:
         if repo.ui.debugflag:
             repo.ui.warn(str(inst), '\n')
@@ -45,16 +43,13 @@  def read(repo):
 
 
 def updatecache(repo):
     repo = repo.unfiltered()  # Until we get a smarter cache management
     cl = repo.changelog
-    tip = cl.tip()
     partial = repo._branchcache
-    if partial is not None and partial.tipnode == tip:
-        return
 
-    if partial is None or partial.tipnode not in cl.nodemap:
+    if partial is None or not partial.validfor(repo):
         partial = read(repo)
 
     catip = repo._cacheabletip()
     # if partial.tiprev == catip: cache is already up to date
     # if partial.tiprev >  catip: we have uncachable element in `partial` can't
@@ -78,10 +73,21 @@  class branchcache(dict):
     def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev):
         super(branchcache, self).__init__(entries)
         self.tipnode = tipnode
         self.tiprev = tiprev
 
+    def validfor(self, repo):
+        """Is the cache content valide regarding a repo
+
+        - False when cached tipnode are 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)
+        except IndexError:
+            return False
+
+
     def write(self, repo):
         try:
             f = repo.opener("cache/branchheads", "w", atomictemp=True)
             f.write("%s %s\n" % (hex(self.tipnode), self.tiprev))
             for label, nodes in self.iteritems():
@@ -155,16 +161,12 @@  class branchcache(dict):
             nodes = [head for head in self[branch]
                      if cl.hasnode(head)]
             if not nodes:
                 droppednodes.extend(nodes)
                 del self[branch]
-        try:
-            node = cl.node(self.tiprev)
-        except IndexError:
-            node = None
-        if ((self.tipnode != node)
-            or (self.tipnode in droppednodes)):
+        if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
+
             # cache key are not valid anymore
             self.tipnode = nullid
             self.tiprev = nullrev
             for heads in self.values():
                 tiprev = max(cl.rev(node) for node in heads)
diff --git a/tests/test-keyword.t b/tests/test-keyword.t
--- a/tests/test-keyword.t
+++ b/tests/test-keyword.t
@@ -505,10 +505,11 @@  amend
   $ echo amend >> a
   $ echo amend >> b
   $ hg -q commit -d '14 1' -m 'prepare amend'
 
   $ hg --debug commit --amend -d '15 1' -m 'amend without changes' | grep keywords
+  invalidating branch cache (tip differs)
   overwriting a expanding keywords
   $ hg -q id
   67d8c481a6be
   $ head -1 a
   expand $Id: a,v 67d8c481a6be 1970/01/01 00:00:15 test $