changeset 6816:e885fc210015 mercurial-4.9

test-compat: merge mercurial-5.0 into mercurial-4.9
author Anton Shestakov <av6@dwimlabs.net>
date Thu, 27 Jun 2024 09:47:05 +0400
parents cde3f4bc3075 (diff) 365bdacd7f6a (current diff)
children 4b843ae726de
files
diffstat 11 files changed, 191 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/.gitlab-ci.yml	Thu Apr 11 17:57:48 2024 -0300
+++ b/.gitlab-ci.yml	Thu Jun 27 09:47:05 2024 +0400
@@ -1,6 +1,5 @@
 .prepare_hg: &prepare_hg
-    - hg pull -R /ci/repos/mercurial/
-    - hg pull -R /ci/repos/mercurial/ https://www.mercurial-scm.org/repo/hg-committed
+    - hg pull -R /ci/repos/mercurial/ https://repo.mercurial-scm.org/hg
     - hg_branch=${HG_BRANCH:-$(tests/testlib/map-hg-rev.sh "$(hg identify --branch)")}
     - hg -R /ci/repos/mercurial/ update "$hg_branch"
     - hg_rev=$(hg log -R /ci/repos/mercurial/ -r . -T '{node}')
--- a/.hgtags	Thu Apr 11 17:57:48 2024 -0300
+++ b/.hgtags	Thu Jun 27 09:47:05 2024 +0400
@@ -109,3 +109,4 @@
 a625eb5acea4d682becd21759170306ab769afb2 11.1.0
 369e248b6312cc3b0777033a4632f2c9e18a0897 11.1.1
 c31c6638381080bc5905fad37545610fde3b98bc 11.1.2
+2d2da4f7742a0da2c2fbd5a95c48937720eeafd4 11.1.3
--- a/CHANGELOG	Thu Apr 11 17:57:48 2024 -0300
+++ b/CHANGELOG	Thu Jun 27 09:47:05 2024 +0400
@@ -1,7 +1,16 @@
 Changelog
 =========
 
-11.1.3 - in progress
+11.1.4 - in progress
+--------------------
+
+  * compatibility with Mercurial 6.8
+
+topic (1.1.4)
+
+  * compatibility with Mercurial 6.8
+
+11.1.3 -- 2024-04-12
 --------------------
 
 topic (1.1.3)
--- a/debian/changelog	Thu Apr 11 17:57:48 2024 -0300
+++ b/debian/changelog	Thu Jun 27 09:47:05 2024 +0400
@@ -1,3 +1,9 @@
+mercurial-evolve (11.1.3-1) unstable; urgency=medium
+
+  * new upstream release
+
+ -- Anton Shestakov <av6@dwimlabs.net>  Fri, 12 Apr 2024 14:32:49 -0300
+
 mercurial-evolve (11.1.2-1) unstable; urgency=medium
 
   * new upstream release
--- a/hgext3rd/evolve/headchecking.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/evolve/headchecking.py	Thu Jun 27 09:47:05 2024 +0400
@@ -25,10 +25,12 @@
 @eh.uisetup
 def uisetup(ui):
     extensions.wrapfunction(discovery, '_postprocessobsolete', _postprocessobsolete)
-    code = scmutil.filteredhash.__code__
-    if r'needobsolete' not in code.co_varnames[:code.co_argcount]:
-        # hg <= 6.0 (053a5bf508da)
-        extensions.wrapfunction(scmutil, 'enforcesinglehead', enforcesinglehead)
+    if util.safehasattr(scmutil, 'filteredhash'):
+        # hg <= 6.7 (a03fa40afd01)
+        code = scmutil.filteredhash.__code__
+        if 'needobsolete' not in code.co_varnames[:code.co_argcount]:
+            # hg <= 6.0 (053a5bf508da)
+            extensions.wrapfunction(scmutil, 'enforcesinglehead', enforcesinglehead)
 
 def branchinfo(pushop, repo, node):
     return repo[node].branch()
--- a/hgext3rd/evolve/metadata.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/evolve/metadata.py	Thu Jun 27 09:47:05 2024 +0400
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-__version__ = b'11.1.3.dev0'
-testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7'
+__version__ = b'11.1.4.dev0'
+testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8'
 minimumhgversion = b'4.9'
 buglink = b'https://bz.mercurial-scm.org/'
--- a/hgext3rd/topic/__init__.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/topic/__init__.py	Thu Jun 27 09:47:05 2024 +0400
@@ -238,9 +238,9 @@
               b'log.topic': b'green_background',
               }
 
-__version__ = b'1.1.3.dev0'
+__version__ = b'1.1.4.dev0'
 
-testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7'
+testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8'
 minimumhgversion = b'4.9'
 buglink = b'https://bz.mercurial-scm.org/'
 
--- a/hgext3rd/topic/discovery.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/topic/discovery.py	Thu Jun 27 09:47:05 2024 +0400
@@ -89,9 +89,11 @@
     else:
         origremotebranchmap = remote.branchmap
     publishednode = [c.node() for c in pushop.outdatedphases]
-    publishedset = repo.revs(b'ancestors(%ln + %ln)',
-                             publishednode,
-                             pushop.remotephases.publicheads)
+    if util.safehasattr(pushop.remotephases, 'publicheads'):
+        # hg <= 6.7 (22cc679a7312)
+        publishedset = repo.revs(b'ancestors(%ln + %ln)', publishednode, pushop.remotephases.publicheads)
+    else:
+        publishedset = repo.revs(b'ancestors(%ln + %ld)', publishednode, pushop.remotephases.public_heads)
 
     publishing = (b'phases' not in remote.listkeys(b'namespaces')
                   or bool(remote.listkeys(b'phases').get(b'publishing', False)))
@@ -240,12 +242,13 @@
 #
 # Handle this by doing an extra check for new head creation server side
 def _nbheads(repo):
-    code = scmutil.filteredhash.__code__
-    if r'needobsolete' not in code.co_varnames[:code.co_argcount]:
-        # hg <= 6.0 (053a5bf508da)
-        filterfn = _filter_obsolete_heads
-    else:
-        filterfn = lambda repo, heads: heads
+    filterfn = lambda repo, heads: heads
+    if util.safehasattr(scmutil, 'filteredhash'):
+        # hg <= 6.7 (a03fa40afd01)
+        code = scmutil.filteredhash.__code__
+        if 'needobsolete' not in code.co_varnames[:code.co_argcount]:
+            # hg <= 6.0 (053a5bf508da)
+            filterfn = _filter_obsolete_heads
     data = {}
     for b in repo.branchmap().iterbranches():
         namedbranch, tns, topic = common.parsefqbn(b[0])
--- a/hgext3rd/topic/flow.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/topic/flow.py	Thu Jun 27 09:47:05 2024 +0400
@@ -127,8 +127,13 @@
     if getattr(pushop, 'publish', False):
         if not pushop.remotephases.publishing:
             unfi = pushop.repo.unfiltered()
-            droots = pushop.remotephases.draftroots
-            revset = b'%ln and (not public() or %ln::)'
+            if util.safehasattr(pushop.remotephases, 'draftroots'):
+                # hg <= 6.7 (22cc679a7312)
+                droots = pushop.remotephases.draftroots
+                revset = b'%ln and (not public() or %ln::)'
+            else:
+                droots = pushop.remotephases.draft_roots
+                revset = b'%ln and (not public() or %ld::)'
             future = list(unfi.set(revset, pushop.futureheads, droots))
             pushop.outdatedphases = future
 
--- a/hgext3rd/topic/topicmap.py	Thu Apr 11 17:57:48 2024 -0300
+++ b/hgext3rd/topic/topicmap.py	Thu Jun 27 09:47:05 2024 +0400
@@ -38,7 +38,7 @@
     if not common.hastopicext(repo):
         return repo
     filtername = topicfilter(repo.filtername)
-    if filtername == repo.filtername:
+    if filtername is None or filtername == repo.filtername:
         return repo
     return repo.filtered(filtername)
 
@@ -48,11 +48,10 @@
     # hg <= 4.9 (caebe5e7f4bd)
     partialmap = branchmap.subsettable
 
-    # filter level not affected by topic that we should not override
-
     for plainname in list(funcmap):
         newfilter = topicfilter(plainname)
         if newfilter == plainname:
+            # filter level not affected by topic that we should not override
             continue
 
         def revsfunc(repo, name=plainname):
@@ -94,7 +93,11 @@
 
 def cgapply(orig, self, repo, *args, **kwargs):
     """make sure a topicmap is used when applying a changegroup"""
-    other = repo.filtered(topicfilter(repo.filtername))
+    newfilter = topicfilter(repo.filtername)
+    if newfilter is None:
+        other = repo
+    else:
+        other = repo.filtered(newfilter)
     return orig(self, other, *args, **kwargs)
 
 def commitstatus(orig, repo, node, branch, bheads=None, tip=None, **opts):
@@ -122,26 +125,36 @@
     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
 
-    try:
-        # Mercurial 5.0
-        class remotetopiccache(_topiccache, branchmap.remotebranchcache):
+        class remotetopiccache(_TopicCacheV2, branchmap.remotebranchcache):
             pass
         branchmap.remotebranchcache = remotetopiccache
+    else:
+        # hg <= 6.7 (ec640dc9cebd)
+        class topiccache(_topiccache, branchmap.branchcache):
+            pass
+        branchmap.branchcache = topiccache
 
-        def _wrapupdatebmcachemethod(orig, self, repo):
-            # pass in the bound method as the original
-            return _wrapupdatebmcache(orig.__get__(self), repo)
-        extensions.wrapfunction(branchmap.BranchMapCache, 'updatecache', _wrapupdatebmcachemethod)
-    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)
+        try:
+            # Mercurial 5.0
+            class remotetopiccache(_topiccache, branchmap.remotebranchcache):
+                pass
+            branchmap.remotebranchcache = remotetopiccache
+
+            def _wrapupdatebmcachemethod(orig, self, repo):
+                # pass in the bound method as the original
+                return _wrapupdatebmcache(orig.__get__(self), repo)
+            extensions.wrapfunction(branchmap.BranchMapCache, 'updatecache', _wrapupdatebmcachemethod)
+        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)
@@ -151,29 +164,38 @@
     finally:
         repo._autobranchmaptopic = previous
 
-# needed to prevent reference used for 'super()' call using in branchmap.py to
-# no go into cycle. (yes, URG)
-_oldbranchmap = branchmap.branchcache
+if util.safehasattr(branchmap, 'branchcache') and dict in branchmap.branchcache.__mro__:
+    # hg <= 4.9 (624d6683c705)
+    # let's break infinite recursion in __init__() that uses super()
+    orig = branchmap.branchcache
 
-@contextlib.contextmanager
-def oldbranchmap():
-    previous = branchmap.branchcache
-    try:
-        branchmap.branchcache = _oldbranchmap
-        yield
-    finally:
-        branchmap.branchcache = previous
+    @contextlib.contextmanager
+    def oldbranchmap():
+        current = branchmap.branchcache
+        try:
+            branchmap.branchcache = orig
+            yield
+        finally:
+            branchmap.branchcache = current
+else:
+    oldbranchmap = util.nullcontextmanager
+
+if util.safehasattr(branchmap, 'branchcache'):
+    allbccls = (branchmap.branchcache,)
+    if util.safehasattr(branchmap, 'remotebranchcache'):
+        # hg <= 4.9 (eb7ce452e0fb)
+        allbccls = (branchmap.branchcache, branchmap.remotebranchcache)
 
 class _topiccache(object): # combine me with branchmap.branchcache
 
     def __init__(self, *args, **kwargs):
-        # super() call may fail otherwise
         with oldbranchmap():
             super(_topiccache, self).__init__(*args, **kwargs)
         self.phaseshash = None
 
     def copy(self):
         """return an deep copy of the branchcache object"""
+        assert isinstance(self, allbccls)  # help pytype
         entries = compat.bcentries(self)
         args = (entries, self.tipnode, self.tiprev, self.filteredhash,
                 self._closednodes)
@@ -188,6 +210,7 @@
         """call branchmap.load(), and then transform branch names to be in the
         new "//" format
         """
+        assert isinstance(self, branchmap.branchcache)  # help pytype
         super(_topiccache, self).load(repo, lineiter)
         entries = compat.bcentries(self)
 
@@ -201,6 +224,7 @@
 
         - 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, allbccls)  # help pytype
         valid = super(_topiccache, self).validfor(repo)
         if not valid:
             return False
@@ -237,6 +261,7 @@
         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, allbccls)  # help pytype
         if not istopicfilter(repo.filtername):
             return super(_topiccache, self).update(repo, revgen)
 
@@ -251,6 +276,87 @@
         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)
+
 def _wrapbmread(orig, repo):
     """call branchmap.read(), and then transform branch names to be in the
     new "//" format
--- a/tests/test-evolve-interrupted.t	Thu Apr 11 17:57:48 2024 -0300
+++ b/tests/test-evolve-interrupted.t	Thu Jun 27 09:47:05 2024 +0400
@@ -45,8 +45,8 @@
   $ hg evolve --update --config hooks.precommit=false --config ui.merge=:other
   move:[1] banana
   atop:[2] apricot and blueberry
-  transaction abort! (no-hg64 !)
-  rollback completed (no-hg64 !)
+  transaction abort!
+  rollback completed
   abort: precommit hook exited with status 1
   [255]
   $ hg l
@@ -104,8 +104,8 @@
   $ hg evolve --update --config hooks.precommit=false --config ui.merge=:other
   move:[1] banana
   atop:[2] apricot and blueberry
-  transaction abort! (no-hg64 !)
-  rollback completed (no-hg64 !)
+  transaction abort!
+  rollback completed
   abort: precommit hook exited with status 1
   [255]
   $ cat b
@@ -129,8 +129,8 @@
   $ hg evolve --update --config hooks.precommit=false --config ui.merge=:other
   move:[1] banana
   atop:[2] apricot and blueberry
-  transaction abort! (no-hg64 !)
-  rollback completed (no-hg64 !)
+  transaction abort!
+  rollback completed
   abort: precommit hook exited with status 1
   [255]
   $ hg evolve --continue