# HG changeset patch # User Anton Shestakov # Date 1718206051 -14400 # Node ID 79c50e9635e14d4af8b389ca286c84121720c412 # Parent efbefcb197391fe694e662eb8805bda9dfd3771a topic: compatibility for branchmap.BranchCacheV2 diff -r efbefcb19739 -r 79c50e9635e1 hgext3rd/topic/topicmap.py --- 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)