diff hgext3rd/topic/topicmap.py @ 6388:0baef8dde96b stable

branching: merge into stable in preparation for release
author Anton Shestakov <av6@dwimlabs.net>
date Mon, 06 Feb 2023 18:37:59 +0400
parents a87abe69a2f8 0bc90758f613
children d13cfd9eb6c0
line wrap: on
line diff
--- a/hgext3rd/topic/topicmap.py	Sun Feb 05 18:47:38 2023 +0400
+++ b/hgext3rd/topic/topicmap.py	Mon Feb 06 18:37:59 2023 +0400
@@ -14,6 +14,7 @@
 from . import (
     common,
     compat,
+    discovery,
 )
 
 basefilter = set([b'base', b'immutable'])
@@ -99,10 +100,12 @@
 def commitstatus(orig, repo, node, branch, bheads=None, tip=None, opts=None):
     # wrap commit status use the topic branch heads
     ctx = repo[node]
-    if ctx.topic() and ctx.branch() == branch:
+    ctxbranch = common.formatfqbn(branch=ctx.branch())
+    if ctx.topic() and ctxbranch == branch:
         bheads = repo.branchheads(b"%s:%s" % (branch, ctx.topic()))
 
-    ret = orig(repo, node, branch, bheads=bheads, tip=tip, opts=opts)
+    with discovery.override_context_branch(repo) as repo:
+        ret = orig(repo, node, branch, bheads=bheads, tip=tip, opts=opts)
 
     # logic copy-pasted from cmdutil.commitstatus()
     if opts is None:
@@ -112,7 +115,8 @@
     parents = ctx.parents()
 
     if (not opts.get(b'amend') and bheads and node not in bheads and not any(
-        p.node() in bheads and p.branch() == branch for p in parents
+        p.node() in bheads and common.formatfqbn(branch=p.branch()) == branch
+        for p in parents
     )):
         repo.ui.status(_(b"(consider using topic for lightweight branches."
                          b" See 'hg help topic')\n"))
@@ -137,7 +141,9 @@
     except AttributeError:
         # hg <= 4.9 (3461814417f3)
         extensions.wrapfunction(branchmap, 'updatecache', _wrapupdatebmcache)
-
+        # branchcache in hg <= 4.9 doesn't have load method, instead there's a
+        # module-level function to read on-disk cache and return a branchcache
+        extensions.wrapfunction(branchmap, 'read', _wrapbmread)
 
 def _wrapupdatebmcache(orig, repo):
     previous = getattr(repo, '_autobranchmaptopic', False)
@@ -170,12 +176,8 @@
 
     def copy(self):
         """return an deep copy of the branchcache object"""
-        if util.safehasattr(self, '_entries'):
-            _entries = self._entries
-        else:
-            # hg <= 4.9 (624d6683c705+b137a6793c51)
-            _entries = self
-        args = (_entries, self.tipnode, self.tiprev, self.filteredhash,
+        entries = compat.bcentries(self)
+        args = (entries, self.tipnode, self.tiprev, self.filteredhash,
                 self._closednodes)
         if util.safehasattr(self, '_repo'):
             # hg <= 5.7 (6266d19556ad)
@@ -184,18 +186,17 @@
         new.phaseshash = self.phaseshash
         return new
 
-    def branchtip(self, branch, topic=b''):
-        '''Return the tipmost open head on branch head, otherwise return the
-        tipmost closed head on branch.
-        Raise KeyError for unknown branch.'''
-        if topic:
-            branch = b'%s:%s' % (branch, topic)
-        return super(_topiccache, self).branchtip(branch)
+    def load(self, repo, lineiter):
+        """call branchmap.load(), and then transform branch names to be in the
+        new "//" format
+        """
+        super(_topiccache, self).load(repo, lineiter)
+        entries = compat.bcentries(self)
 
-    def branchheads(self, branch, closed=False, topic=b''):
-        if topic:
-            branch = b'%s:%s' % (branch, topic)
-        return super(_topiccache, self).branchheads(branch, closed=closed)
+        for branch in tuple(entries):
+            formatted = common.formatfqbn(branch=branch)
+            if branch != formatted:
+                entries[formatted] = entries.pop(branch)
 
     def validfor(self, repo):
         """Is the cache content valid regarding a repo
@@ -217,10 +218,21 @@
                 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):
-            super(_topiccache, self).write(repo)
+            cache = self.copy()
+            entries = compat.bcentries(cache)
+
+            for formatted in tuple(entries):
+                branch, tns, topic = common.parsefqbn(formatted)
+                if branch != formatted:
+                    entries[branch] = entries.pop(formatted)
+
+            super(_topiccache, cache).write(repo)
 
     def update(self, repo, revgen):
         """Given a branchhead cache, self, that may have extra nodes or be
@@ -229,22 +241,32 @@
         """
         if not istopicfilter(repo.filtername):
             return super(_topiccache, self).update(repo, revgen)
-        unfi = repo.unfiltered()
-        oldgetbranchinfo = unfi.revbranchcache().branchinfo
+
+        # 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(_topiccache, self).update(repo, revgen)
+        self.phaseshash = _phaseshash(repo, self.tiprev)
 
-        def branchinfo(r, changelog=None):
-            info = oldgetbranchinfo(r)
-            topic = b''
-            ctx = unfi[r]
-            if ctx.mutable():
-                topic = ctx.topic()
-            branch = info[0]
-            if topic:
-                branch = b'%s:%s' % (branch, topic)
-            return (branch, info[1])
-        try:
-            unfi.revbranchcache().branchinfo = branchinfo
-            super(_topiccache, self).update(repo, revgen)
-            self.phaseshash = _phaseshash(repo, self.tiprev)
-        finally:
-            unfi.revbranchcache().branchinfo = oldgetbranchinfo
+def _wrapbmread(orig, repo):
+    """call branchmap.read(), and then transform branch names to be in the
+    new "//" format
+    """
+    partial = orig(repo)
+    if partial is None:
+        # because of IOError or OSError
+        return partial
+
+    entries = compat.bcentries(partial)
+
+    for branch in tuple(entries):
+        formatted = common.formatfqbn(branch=branch)
+        if branch != formatted:
+            entries[formatted] = entries.pop(branch)
+
+    return partial