changeset 6781:79c50e9635e1

topic: compatibility for branchmap.BranchCacheV2
author Anton Shestakov <av6@dwimlabs.net>
date Wed, 12 Jun 2024 19:27:31 +0400
parents efbefcb19739
children c81bb5135307
files hgext3rd/topic/topicmap.py
diffstat 1 files changed, 97 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/hgext3rd/topic/topicmap.py	Fri May 17 15:59:34 2024 +0400
+++ b/hgext3rd/topic/topicmap.py	Wed Jun 12 19:27:31 2024 +0400
@@ -120,13 +120,23 @@
     return ret
 
 def _wrapbmcache(ui):
-    class topiccache(_topiccache, branchmap.branchcache):
-        pass
-    branchmap.branchcache = topiccache
+    if util.safehasattr(branchmap, 'BranchCacheV2'):
+        class TopicCache(_TopicCacheV2, branchmap.BranchCacheV2):
+            pass
+        branchmap.BranchCacheV2 = TopicCache
 
-    class remotetopiccache(_topiccache, branchmap.remotebranchcache):
-        pass
-    branchmap.remotebranchcache = remotetopiccache
+        class remotetopiccache(_TopicCacheV2, branchmap.remotebranchcache):
+            pass
+        branchmap.remotebranchcache = remotetopiccache
+    else:
+        # hg <= 6.7 (ec640dc9cebd)
+        class topiccache(_topiccache, branchmap.branchcache):
+            pass
+        branchmap.branchcache = topiccache
+
+        class remotetopiccache(_topiccache, branchmap.remotebranchcache):
+            pass
+        branchmap.remotebranchcache = remotetopiccache
 
     def _wrapupdatebmcachemethod(orig, self, repo):
         # pass in the bound method as the original
@@ -226,3 +236,84 @@
 
         super(_topiccache, self).update(repo, revgen)
         self.phaseshash = _phaseshash(repo, self.tiprev)
+
+class _TopicCacheV2(object): # combine me with branchmap.BranchCacheV2
+
+    def __init__(self, *args, **kwargs):
+        super(_TopicCacheV2, self).__init__(*args, **kwargs)
+        self.phaseshash = None
+
+    def _load_heads(self, repo, lineiter):
+        """call BranchCacheV2._load_heads(), and then transform branch names to
+        be in the new "//" format
+        """
+        assert isinstance(self, branchmap.BranchCacheV2)  # help pytype
+        super(_TopicCacheV2, self)._load_heads(repo, lineiter)
+
+        for branch in tuple(self._entries):
+            formatted = common.formatfqbn(branch=branch)
+            if branch != formatted:
+                self._entries[formatted] = self._entries.pop(branch)
+
+    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."""
+        assert isinstance(self, (branchmap.BranchCacheV2, branchmap.remotebranchcache))  # help pytype
+        valid = super(_TopicCacheV2, self).validfor(repo)
+        if not valid:
+            return False
+        elif not istopicfilter(repo.filtername) or self.phaseshash is None:
+            # phasehash at None means this is a branchmap
+            # come from non topic thing
+            return True
+        else:
+            try:
+                valid = self.phaseshash == _phaseshash(repo, self.tiprev)
+                return valid
+            except IndexError:
+                return False
+
+    def write(self, repo):
+        """write cache to disk if it's not topic-only, but first transform
+        cache keys from branches in "//" format into bare branch names
+        """
+        # we expect mutable set to be small enough to be that computing it all
+        # the time will be fast enough
+        if not istopicfilter(repo.filtername):
+            entries = self._entries.copy()
+
+            for formatted in tuple(entries):
+                branch, tns, topic = common.parsefqbn(formatted)
+                if branch != formatted:
+                    entries[branch] = entries.pop(formatted)
+
+            oldentries = self._entries
+            try:
+                self._entries = entries
+                super(_TopicCacheV2, self).write(repo)
+            finally:
+                self._entries = oldentries
+
+    def update(self, repo, revgen):
+        """Given a branchhead cache, self, that may have extra nodes or be
+        missing heads, and a generator of nodes that are strictly a superset of
+        heads missing, this function updates self to be correct.
+        """
+        assert isinstance(self, (branchmap.BranchCacheV2, branchmap.remotebranchcache))  # help pytype
+        if not istopicfilter(repo.filtername):
+            return super(_TopicCacheV2, self).update(repo, revgen)
+
+        # See topic.discovery._headssummary(), where repo.unfiltered gets
+        # overridden to return .filtered('unfiltered-topic'). revbranchcache
+        # only can be created for unfiltered repo (filtername is None), so we
+        # do that here, and this revbranchcache will be cached inside repo.
+        # When we get rid of *-topic filters, then this workaround can be
+        # removed too.
+        repo.unfiltered().revbranchcache()
+
+        super(_TopicCacheV2, self).update(repo, revgen)
+        if util.safehasattr(self, 'tiprev'):
+            # remotebranchcache doesn't have self.tiprev
+            self.phaseshash = _phaseshash(repo, self.tiprev)