# HG changeset patch # User Anton Shestakov # Date 1719467225 -14400 # Node ID e885fc2100155186c72f448698b30863160ef102 # Parent cde3f4bc3075d118e0526a8038446ee0058ef206# Parent 365bdacd7f6a14979daba92992bb9ec1097d1755 test-compat: merge mercurial-5.0 into mercurial-4.9 diff -r 365bdacd7f6a -r e885fc210015 .gitlab-ci.yml --- 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}') diff -r 365bdacd7f6a -r e885fc210015 .hgtags --- 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 diff -r 365bdacd7f6a -r e885fc210015 CHANGELOG --- 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) diff -r 365bdacd7f6a -r e885fc210015 debian/changelog --- 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 Fri, 12 Apr 2024 14:32:49 -0300 + mercurial-evolve (11.1.2-1) unstable; urgency=medium * new upstream release diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/evolve/headchecking.py --- 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() diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/evolve/metadata.py --- 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/' diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/topic/__init__.py --- 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/' diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/topic/discovery.py --- 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]) diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/topic/flow.py --- 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 diff -r 365bdacd7f6a -r e885fc210015 hgext3rd/topic/topicmap.py --- 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 diff -r 365bdacd7f6a -r e885fc210015 tests/test-evolve-interrupted.t --- 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