changeset 6231:d0f0a7b68d2d

branching: merge with stable
author Anton Shestakov <av6@dwimlabs.net>
date Tue, 26 Apr 2022 17:39:11 +0400
parents 6020b7e92a86 (diff) ab92c510ab05 (current diff)
children 1d553662fc1b
files CHANGELOG hgext3rd/evolve/cmdrewrite.py hgext3rd/evolve/evolvecmd.py hgext3rd/evolve/metadata.py hgext3rd/evolve/state.py tests/test-fixup.t
diffstat 18 files changed, 388 insertions(+), 226 deletions(-) [+]
line wrap: on
line diff
--- a/.gitlab-ci.yml	Tue Apr 26 13:09:23 2022 +0400
+++ b/.gitlab-ci.yml	Tue Apr 26 17:39:11 2022 +0400
@@ -30,34 +30,11 @@
         - ("$PYTHON" --version)
         - (cd tests; set -x; HGMODULEPOLICY="$TEST_HGMODULEPOLICY" "$PYTHON" /ci/repos/mercurial/tests/run-tests.py --color=always $RUNTEST_ARGS)
 
-checks-py2:
-    <<: *runtests
-    variables:
-        PY: py2
-        PYTHON: python2
-        RUNTEST_ARGS: "--test-list /tmp/check-tests.txt"
-
 checks-py3:
     <<: *runtests
     variables:
         RUNTEST_ARGS: "--test-list /tmp/check-tests.txt"
 
-tests-py2-cext:
-    <<: *runtests
-    variables:
-        PY: py2
-        PYTHON: python2
-        RUNTEST_ARGS: "--no-rust --blacklist /tmp/check-tests.txt"
-        TEST_HGMODULEPOLICY: "c"
-
-tests-py2-pure:
-    <<: *runtests
-    variables:
-        PY: py2
-        PYTHON: python2
-        RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt"
-        TEST_HGMODULEPOLICY: "py"
-
 tests-py3-cext:
     <<: *runtests
     variables:
@@ -70,6 +47,16 @@
         RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt"
         TEST_HGMODULEPOLICY: "py"
 
+tests-py2-6.1:
+    <<: *runtests
+    variables:
+        PY: py2
+        PYTHON: python2
+        RUNTEST_ARGS: "--no-rust --blacklist /tmp/check-tests.txt"
+        TEST_HGMODULEPOLICY: "c"
+        HG_BRANCH: 'max(tag("re:^6\.1"))'
+    allow_failure: true
+
 doc:
     image: registry.heptapod.net/mercurial/ci-images/py3-evolve-doc
     script:
--- a/CHANGELOG	Tue Apr 26 13:09:23 2022 +0400
+++ b/CHANGELOG	Tue Apr 26 17:39:11 2022 +0400
@@ -1,6 +1,16 @@
 Changelog
 =========
 
+10.6.0 - in progress
+--------------------
+
+  * prune: pruning (without any successors) an already obsolete revision will
+    no longer give a false warning about divergence
+
+topic (0.25.0)
+
+  * topic: allow Unicode word characters in topic names
+
 10.5.1 -- 2022-04-26
 --------------------
 
--- a/hgext3rd/evolve/__init__.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/__init__.py	Tue Apr 26 17:39:11 2022 +0400
@@ -1167,14 +1167,17 @@
         statemod.addunfinished(b'evolve', fname=b'evolvestate',
                                continueflag=True, stopflag=True,
                                statushint=_msg,
-                               abortfunc=evolvecmd.hgabortevolve)
+                               abortfunc=evolvecmd.hgabortevolve,
+                               continuefunc=evolvecmd.hgcontinueevolve)
         statemod.addunfinished(b'pick', fname=b'pickstate', continueflag=True,
-                               abortfunc=cmdrewrite.hgabortpick)
+                               abortfunc=cmdrewrite.hgabortpick,
+                               continuefunc=cmdrewrite.hgcontinuepick)
         _fixup_msg = _(b'To continue:    hg fixup --continue\n'
                        b'To abort:       hg fixup --abort\n')
         statemod.addunfinished(b'fixup', fname=b'fixup-state',
                                continueflag=True, statushint=_fixup_msg,
-                               abortfunc=cmdrewrite.hgabortfixup)
+                               abortfunc=cmdrewrite.hgabortfixup,
+                               continuefunc=cmdrewrite.hgcontinuefixup)
     else:
         # hg <= 5.0 (5f2f6912c9e6)
         estate = (b'evolvestate', False, False, _(b'evolve in progress'),
@@ -1204,5 +1207,5 @@
 @eh.wrapfunction(hg, 'clean')
 def clean(orig, repo, *args, **kwargs):
     ret = orig(repo, *args, **kwargs)
-    util.unlinkpath(repo.vfs.join(b'evolvestate'), ignoremissing=True)
+    repo.vfs.unlinkpath(b'evolvestate', ignoremissing=True)
     return ret
--- a/hgext3rd/evolve/cmdrewrite.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/cmdrewrite.py	Tue Apr 26 17:39:11 2022 +0400
@@ -941,7 +941,7 @@
     try:
         wlock = repo.wlock()
         lock = repo.lock()
-        rewriteutil.precheck(repo, revs, b'prune')
+        rewriteutil.precheck(repo, revs, b'prune', check_divergence=bool(succs))
         tr = repo.transaction(b'prune')
         # defines pruned changesets
         precs = []
@@ -1403,28 +1403,41 @@
                 pickstate.save()
                 raise error.InterventionRequired(_(b"unresolved merge conflicts"
                                                    b" (see hg help resolve)"))
-        overrides = {(b'phases', b'new-commit'): origctx.phase()}
-        with repo.ui.configoverride(overrides, b'pick'):
-            newnode = repo.commit(text=origctx.description(),
-                                  user=origctx.user(),
-                                  date=origctx.date(), extra=origctx.extra())
-        repo.dirstate.setbranch(origctx.branch())
+        return _dopick(ui, repo, pickstate, origctx)
+
+def _dopick(ui, repo, pickstate, origctx):
+    """shared logic for performing or continuing a pick"""
+    overrides = {(b'phases', b'new-commit'): origctx.phase()}
+    with repo.ui.configoverride(overrides, b'pick'):
+        newnode = repo.commit(text=origctx.description(),
+                              user=origctx.user(),
+                              date=origctx.date(), extra=origctx.extra())
+    repo.dirstate.setbranch(origctx.branch())
 
-        if pickstate:
-            pickstate.delete()
-        if newnode is None:
-            replacements = {(origctx.node(),): []}
-        else:
-            newctx = repo[newnode]
-            replacements = {(origctx.node(),): [newctx.node()]}
-        compat.cleanupnodes(repo, replacements, operation=b"pick")
+    if pickstate:
+        pickstate.delete()
+    if newnode is None:
+        replacements = {(origctx.node(),): []}
+    else:
+        newctx = repo[newnode]
+        replacements = {(origctx.node(),): [newctx.node()]}
+    compat.cleanupnodes(repo, replacements, operation=b"pick")
 
-        if newnode is None:
-            ui.warn(_(b"note: picking %d:%s created no changes to commit\n") %
-                    (origctx.rev(), origctx))
-            return 0
+    if newnode is None:
+        ui.warn(_(b"note: picking %d:%s created no changes to commit\n") %
+                (origctx.rev(), origctx))
+        return 0
+
+    return 0
 
-        return 0
+def hgcontinuepick(ui, repo):
+    """logic to continue pick using 'hg continue'"""
+    with repo.wlock(), repo.lock():
+        pickstate = state.cmdstate(repo, path=b'pickstate')
+        pickstate.load()
+        orignode = pickstate[b'orignode']
+        origctx = repo[orignode]
+        return _dopick(ui, repo, pickstate, origctx)
 
 def abortpick(ui, repo, pickstate, abortcmd=False):
     """logic to abort pick"""
@@ -1485,28 +1498,28 @@
     abortopt = opts.get('abort')
     if node or opts.get('rev'):
         if contopt:
-            raise error.Abort(_(b'cannot specify a revision with --continue'))
+            raise compat.InputError(_(b'cannot specify a revision with --continue'))
         if abortopt:
-            raise error.Abort(_(b'cannot specify a revision with --abort'))
+            raise compat.InputError(_(b'cannot specify a revision with --abort'))
     # state file for --continue/--abort cases
     fixup_state = state.cmdstate(repo, b'fixup-state')
     if contopt:
         if not fixup_state.exists():
-            raise error.Abort(_(b'no interrupted fixup to continue'))
+            raise compat.StateError(_(b'no interrupted fixup to continue'))
         fixup_state.load()
         return continuefixup(ui, repo, fixup_state)
     if abortopt:
         if not fixup_state.exists():
-            raise error.Abort(_(b'no interrupted fixup to abort'))
+            raise compat.StateError(_(b'no interrupted fixup to abort'))
         fixup_state.load()
         return abortfixup(ui, repo, fixup_state)
 
     if node and opts.get('rev'):
-        raise error.Abort(_(b'please specify just one revision'))
+        raise compat.InputError(_(b'please specify just one revision'))
     if not node:
         node = opts.get('rev')
     if not node:
-        raise error.Abort(_(b'please specify a revision to fixup'))
+        raise compat.InputError(_(b'please specify a revision to fixup'))
     target_ctx = scmutil.revsingle(repo, node)
 
     fixup_state.addopts({
@@ -1579,6 +1592,13 @@
         compat.update(repo.unfiltered()[tempnode])
         return 0
 
+def hgcontinuefixup(ui, repo):
+    """logic for handling `hg continue' for fixup"""
+    with repo.wlock(), repo.lock():
+        fixup_state = state.cmdstate(repo, b'fixup-state')
+        fixup_state.load()
+        return continuefixup(ui, repo, fixup_state)
+
 def abortfixup(ui, repo, fixup_state):
     """logic for handling of `hg fixup --abort`"""
     with repo.wlock(), repo.lock():
--- a/hgext3rd/evolve/compat.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/compat.py	Tue Apr 26 17:39:11 2022 +0400
@@ -424,17 +424,12 @@
         def to_display(name):
             return pycompat.sysbytes(name).replace(b'_', b'-')
 
-        if util.safehasattr(error, 'InputError'):
-            err = error.InputError
-        else:
-            # hg <= 5.6 (8d72e29ad1e0)
-            err = error.Abort
         previous = None
         for x in args:
             if opts.get(x):
                 if previous:
-                    raise err(_(b'cannot specify both --%s and --%s')
-                              % (to_display(previous), to_display(x)))
+                    raise InputError(_(b'cannot specify both --%s and --%s')
+                                     % (to_display(previous), to_display(x)))
                 previous = x
         return previous
 
@@ -570,3 +565,15 @@
     # hg <= 5.9 (dcd97b082b3b)
     def dirchanges(dirstate):
         return [f for f in dirstate if dirstate[f] != b'n']
+
+if util.safehasattr(error, 'InputError'):
+    InputError = error.InputError
+else:
+    # hg <= 5.6 (8d72e29ad1e0)
+    InputError = error.Abort
+
+if util.safehasattr(error, 'StateError'):
+    StateError = error.StateError
+else:
+    # hg <= 5.6 (527ce85c2e60)
+    StateError = error.Abort
--- a/hgext3rd/evolve/evolvecmd.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/evolvecmd.py	Tue Apr 26 17:39:11 2022 +0400
@@ -1001,8 +1001,7 @@
         if not orig.topic() and repo.vfs.exists(b'topic'):
             repo.vfs.unlink(b'topic')
         else:
-            with repo.vfs.open(b'topic', b'w') as f:
-                f.write(orig.topic())
+            repo.vfs.write(b'topic', orig.topic())
 
     stats = merge.graft(repo, orig, pctx, [b'destination', b'evolving'], True)
 
@@ -2048,6 +2047,23 @@
     progress.complete()
     return headnode
 
+def hgcontinueevolve(ui, repo):
+    """logic for continuing evolve using 'hg continue'"""
+    with repo.wlock(), repo.lock():
+        evolvestate = state.cmdstate(repo)
+        evolvestate.load()
+        headnode = continueevolve(ui, repo, evolvestate)
+        if evolvestate[b'command'] != b'evolve':
+            evolvestate.delete()
+            return
+        startnode = evolvestate[b'startnode']
+        shouldupdate = False
+        if b'update' in evolvestate:
+            shouldupdate = evolvestate[b'update']
+        evolvestate.delete()
+
+        _cleanup(ui, repo, startnode, shouldupdate, headnode)
+
 def _continuecontentdivergent(ui, repo, evolvestate, progresscb):
     """function to continue the interrupted content-divergence resolution."""
     tr = repo.transaction(b'evolve')
--- a/hgext3rd/evolve/metadata.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/metadata.py	Tue Apr 26 17:39:11 2022 +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'10.5.2.dev'
+__version__ = b'10.6.0.dev'
 testedwith = b'4.8 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'
 minimumhgversion = b'4.8'
 buglink = b'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/rewriteutil.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/rewriteutil.py	Tue Apr 26 17:39:11 2022 +0400
@@ -54,37 +54,43 @@
         summary %= (node.short(tonode(first)), numrevs - 1)
     return summary
 
-def precheck(repo, revs, action=b'rewrite'):
+def precheck(repo, revs, action=b'rewrite', check_divergence=True):
     """check if <revs> can be rewritten
 
     <action> can be used to control the commit message.
     """
-    # If this attribute exists, then core's rewriteutil is recent enough
-    # that it has all the features from our own implementation.
-    if util.safehasattr(corerewriteutil, 'find_new_divergence_from'):
-        return corerewriteutil.precheck(repo, revs, action)
+    # hg <= 6.1 (d4752aeb20f1)
+    code = corerewriteutil.precheck.__code__
+    if r'check_divergence' in code.co_varnames[:code.co_argcount]:
+        return corerewriteutil.precheck(repo, revs, action,
+                                        check_divergence=check_divergence)
 
     # hg <= 5.8 (d90f6237)
     if node.nullrev in revs:
         msg = _(b"cannot %s the null revision") % (action)
         hint = _(b"no changeset checked out")
-        raise error.Abort(msg, hint=hint)
+        raise compat.InputError(msg, hint=hint)
     if any(util.safehasattr(r, 'rev') for r in revs):
         msg = b"rewriteutil.precheck called with ctx not revs"
         repo.ui.develwarn(msg)
         revs = (r.rev() for r in revs)
+    if len(repo[None].parents()) > 1:
+        raise compat.StateError(_(b"cannot %s changesets while merging")
+                                % action)
     publicrevs = repo.revs(b'%ld and public()', revs)
     if publicrevs:
         summary = _formatrevs(repo, publicrevs)
         msg = _(b"cannot %s public changesets: %s") % (action, summary)
         hint = _(b"see 'hg help phases' for details")
-        raise error.Abort(msg, hint=hint)
+        raise compat.InputError(msg, hint=hint)
     newunstable = disallowednewunstable(repo, revs)
     if newunstable:
-        msg = _(b"%s will orphan %i descendants")
+        msg = _(b"cannot %s changeset, as that will orphan %i descendants")
         msg %= (action, len(newunstable))
         hint = _(b"see 'hg help evolution.instability'")
-        raise error.Abort(msg, hint=hint)
+        raise compat.InputError(msg, hint=hint)
+    if not check_divergence:
+        return
     allowdivergence = compat.isenabled(repo, compat.allowdivergenceopt)
     if allowdivergence:
         return
@@ -93,7 +99,7 @@
         local, other, common_prec = divergence
         localdiv = repo[local]
         otherdiv, base = repo[other], repo[common_prec]
-        msg = _(b"%s of %s creates content-divergence "
+        msg = _(b"cannot %s %s, as that creates content-divergence "
                 b"with %s") % (action, localdiv, otherdiv)
         if localdiv.rev() != base.rev():
             msg += _(b', from %s') % base
@@ -101,17 +107,17 @@
                  b"'hg help evolution.instability'")
         if repo.ui.verbose:
             if localdiv.rev() != base.rev():
-                msg += _(b'\n    changeset %s is an evolution of '
+                msg += _(b'\n    changeset %s is a successor of '
                          b'changeset %s') % (localdiv, base)
-            msg += _(b'\n    changeset %s already have a successors as '
+            msg += _(b'\n    changeset %s already has a successor in '
                      b'changeset %s\n'
                      b'    rewriting changeset %s would create '
                      b'"content-divergence"\n'
                      b'    set experimental.evolution.allowdivergence=True to '
-                     b'overwrite this check') % (base, otherdiv, localdiv)
+                     b'skip this check') % (base, otherdiv, localdiv)
             hint = _(b"see 'hg help evolution.instability' for details "
                      b"on content-divergence")
-        raise error.Abort(msg, hint=hint)
+        raise compat.InputError(msg, hint=hint)
 
 def bookmarksupdater(repo, oldid, tr):
     """Return a callable update(newid) updating the current bookmark
--- a/hgext3rd/evolve/state.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/evolve/state.py	Tue Apr 26 17:39:11 2022 +0400
@@ -30,7 +30,6 @@
 
 from mercurial import (
     error,
-    util,
 )
 
 from mercurial.i18n import _
@@ -100,7 +99,7 @@
 
     def delete(self):
         """drop the evolvestate file if exists"""
-        util.unlinkpath(self._repo.vfs.join(self.path), ignoremissing=True)
+        self._repo.vfs.unlinkpath(self.path, ignoremissing=True)
 
     def exists(self):
         """check whether the evolvestate file exists or not"""
--- a/hgext3rd/pullbundle.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/pullbundle.py	Tue Apr 26 17:39:11 2022 +0400
@@ -92,7 +92,7 @@
 
 from mercurial.i18n import _
 
-__version__ = b'0.1.4.dev'
+__version__ = b'0.2.0.dev'
 testedwith = b'4.8 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'
 minimumhgversion = b'4.8'
 buglink = b'https://bz.mercurial-scm.org/'
--- a/hgext3rd/topic/__init__.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/topic/__init__.py	Tue Apr 26 17:39:11 2022 +0400
@@ -169,6 +169,7 @@
     cmdutil,
     commands,
     context,
+    encoding,
     error,
     exchange,
     extensions,
@@ -231,7 +232,7 @@
               b'log.topic': b'green_background',
               }
 
-__version__ = b'0.24.1.dev'
+__version__ = b'0.25.0.dev'
 
 testedwith = b'4.8 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'
 minimumhgversion = b'4.8'
@@ -823,14 +824,20 @@
     if topic:
         topic = topic.strip()
         if not topic:
-            raise error.Abort(_(b"topic name cannot consist entirely of whitespaces"))
+            raise error.Abort(_(b"topic names cannot consist entirely of whitespace"))
         # Have some restrictions on the topic name just like bookmark name
         scmutil.checknewlabel(repo, topic, b'topic')
 
-        rmatch = re.match(br'[-_.\w]+', topic)
-        if not rmatch or rmatch.group(0) != topic:
-            helptxt = _(b"topic names can only consist of alphanumeric, '-'"
-                        b" '_' and '.' characters")
+        helptxt = _(b"topic names can only consist of alphanumeric, '-'"
+                    b" '_' and '.' characters")
+        try:
+            utopic = encoding.unifromlocal(topic)
+        except error.Abort:
+            # Maybe we should allow these topic names as well, as long as they
+            # don't break any other rules
+            utopic = ''
+        rmatch = re.match(r'[-_.\w]+', utopic, re.UNICODE)
+        if not utopic or not rmatch or rmatch.group(0) != utopic:
             raise error.Abort(_(b"invalid topic name: '%s'") % topic, hint=helptxt)
 
     if list:
@@ -1054,8 +1061,7 @@
 
     if newtopic:
         with repo.wlock():
-            with repo.vfs.open(b'topic', b'w') as f:
-                f.write(newtopic)
+            repo.vfs.write(b'topic', newtopic)
     else:
         if repo.vfs.exists(b'topic'):
             repo.vfs.unlink(b'topic')
@@ -1317,8 +1323,7 @@
         hint = _(b"see 'hg help -e topic.topic-mode' for details")
         if opts.get('topic'):
             t = opts['topic']
-            with repo.vfs.open(b'topic', b'w') as f:
-                f.write(t)
+            repo.vfs.write(b'topic', t)
         elif opts.get('amend'):
             pass
         elif notopic and mayabort:
@@ -1329,8 +1334,7 @@
             if not ui.quiet:
                 ui.warn((b"(%s)\n") % hint)
         elif notopic and mayrandom:
-            with repo.vfs.open(b'topic', b'w') as f:
-                f.write(randomname.randomtopicname(ui))
+            repo.vfs.write(b'topic', randomname.randomtopicname(ui))
         return orig(ui, repo, *args, **opts)
 
 def committextwrap(orig, repo, ctx, subs, extramsg):
@@ -1407,8 +1411,7 @@
             pctx = repo[node]
             if pctx.phase() > phases.public:
                 t = pctx.topic()
-            with repo.vfs.open(b'topic', b'w') as f:
-                f.write(t)
+            repo.vfs.write(b'topic', t)
             if t and t != ot:
                 repo.ui.status(_(b"switching to topic %s\n") % t)
             if ot and not t:
--- a/hgext3rd/topic/revset.py	Tue Apr 26 13:09:23 2022 +0400
+++ b/hgext3rd/topic/revset.py	Tue Apr 26 17:39:11 2022 +0400
@@ -7,20 +7,13 @@
     util,
 )
 
+from mercurial.utils import stringutil
+
 from . import (
     destination,
     stack,
 )
 
-try:
-    mkmatcher = revset._stringmatcher
-except AttributeError:
-    try:
-        from mercurial.utils import stringutil
-        mkmatcher = stringutil.stringmatcher
-    except (ImportError, AttributeError):
-        mkmatcher = util.stringmatcher
-
 revsetpredicate = registrar.revsetpredicate()
 
 def getstringstrict(x, err):
@@ -33,8 +26,8 @@
     """All changesets with the specified topic or the topics of the given
     changesets. Without the argument, all changesets with any topic specified.
 
-    If `string` starts with `re:` the remainder of the name is treated
-    as a regular expression.
+     Pattern matching is supported for `string`. See
+    :hg:`help revisions.patterns`.
     """
     args = revset.getargs(x, 0, 1, b'topic takes one or no arguments')
 
@@ -49,7 +42,7 @@
         # not a string, but another revset
         pass
     else:
-        kind, pattern, matcher = mkmatcher(topic)
+        kind, pattern, matcher = stringutil.stringmatcher(topic)
 
         if topic.startswith(b'literal:') and pattern not in repo.topics:
             raise error.RepoLookupError(b"topic '%s' does not exist" % pattern)
--- a/tests/test-evolve-continue.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-evolve-continue.t	Tue Apr 26 17:39:11 2022 +0400
@@ -41,7 +41,7 @@
 
 Simple case of evolve --continue
 
-  $ hg up ca1b80f7960a
+  $ hg up 'desc("added c")'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo bar > d
   $ hg add d
@@ -95,28 +95,86 @@
   $ hg up
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
+Testing hg continue for evolve
+
+  $ hg up 'desc("added b")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > c
+  $ hg add c
+  $ hg amend
+  2 new orphan changesets
+  $ hg glog
+  @  7:8591ebad2ee8 added b
+  |   () draft
+  | *  6:2a4e03d422e2 added d
+  | |   () draft orphan
+  | *  5:cb6a2ab625bb added c
+  | |   () draft orphan
+  | x  2:b1661037fa25 added b
+  |/    () draft
+  o  1:c7586e2a9264 added a
+  |   () draft
+  o  0:8fa14d15e168 added hgignore
+      () draft
+
+  $ hg evolve --all
+  move:[5] added c
+  atop:[7] added b
+  merging c (inmemory !)
+  hit merge conflicts; retrying merge in working copy (inmemory !)
+  merging c
+  warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+
+  $ echo foo > c
+  $ hg resolve -m
+  (no more unresolved files)
+  continue: hg evolve --continue
+
+  $ hg continue
+  evolving 5:cb6a2ab625bb "added c"
+  move:[6] added d
+  atop:[8] added c
+
+  $ hg glog
+  o  9:ee53d012d45b added d
+  |   () draft
+  o  8:ba3724c42438 added c
+  |   () draft
+  @  7:8591ebad2ee8 added b
+  |   () draft
+  o  1:c7586e2a9264 added a
+  |   () draft
+  o  0:8fa14d15e168 added hgignore
+      () draft
+
+  $ hg up
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
 Case when conflicts resolution lead to empty wdir in evolve --continue
 
   $ echo foo > e
   $ hg ci -Aqm "added e"
   $ hg prev
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  [6] added d
+  [9] added d
   $ echo bar > e
   $ hg add e
   $ hg amend
   1 new orphan changesets
 
   $ hg glog
-  @  8:00a5c774cc37 added d
+  @  11:184dba7cf613 added d
   |   () draft
-  | *  7:ad0a59d83efe added e
+  | *  10:87d7311179ee added e
   | |   () draft orphan
-  | x  6:2a4e03d422e2 added d
+  | x  9:ee53d012d45b added d
   |/    () draft
-  o  5:cb6a2ab625bb added c
+  o  8:ba3724c42438 added c
   |   () draft
-  o  2:b1661037fa25 added b
+  o  7:8591ebad2ee8 added b
   |   () draft
   o  1:c7586e2a9264 added a
   |   () draft
@@ -124,8 +182,8 @@
       () draft
 
   $ hg evolve --update
-  move:[7] added e
-  atop:[8] added d
+  move:[10] added e
+  atop:[11] added d
   merging e (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
   merging e
@@ -141,15 +199,15 @@
   $ hg diff
 
   $ hg evolve --continue
-  evolving 7:ad0a59d83efe "added e"
-  evolution of 7:ad0a59d83efe created no changes to commit
+  evolving 10:87d7311179ee "added e"
+  evolution of 10:87d7311179ee created no changes to commit
 
   $ hg glog
-  @  8:00a5c774cc37 added d
+  @  11:184dba7cf613 added d
   |   () draft
-  o  5:cb6a2ab625bb added c
+  o  8:ba3724c42438 added c
   |   () draft
-  o  2:b1661037fa25 added b
+  o  7:8591ebad2ee8 added b
   |   () draft
   o  1:c7586e2a9264 added a
   |   () draft
@@ -158,7 +216,7 @@
 
 Case when there are a lot of revision to continue
 
-  $ hg up c7586e2a9264
+  $ hg up 'desc("added a")'
   0 files updated, 0 files merged, 4 files removed, 0 files unresolved
   $ echo bar > b
   $ hg add b
@@ -166,8 +224,8 @@
   3 new orphan changesets
 
   $ hg evolve --all --update
-  move:[2] added b
-  atop:[9] added a
+  move:[7] added b
+  atop:[12] added a
   merging b (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
   merging b
@@ -181,20 +239,20 @@
   (no more unresolved files)
   continue: hg evolve --continue
   $ hg evolve --continue
-  evolving 2:b1661037fa25 "added b"
-  move:[5] added c
-  atop:[10] added b
-  move:[8] added d
-  working directory is now at 6642d2c9176e
+  evolving 7:8591ebad2ee8 "added b"
+  move:[8] added c
+  atop:[13] added b
+  move:[11] added d
+  working directory is now at 44cb92e89781
 
   $ hg glog
-  @  12:6642d2c9176e added d
+  @  15:44cb92e89781 added d
   |   () draft
-  o  11:95665a2de664 added c
+  o  14:152ba81b0477 added c
   |   () draft
-  o  10:87f748868183 added b
+  o  13:58b400d15a91 added b
   |   () draft
-  o  9:53b632d203d8 added a
+  o  12:53b632d203d8 added a
   |   () draft
   o  0:8fa14d15e168 added hgignore
       () draft
@@ -205,24 +263,24 @@
   $ for ch in f g h; do echo foo > $ch; hg add $ch; hg ci -m "added "$ch; done;
 
   $ hg glog
-  @  15:09becba8f97d added h
+  @  18:bc3b992c22bd added h
   |   () draft
-  o  14:5aa7b2bbd944 added g
+  o  17:28352edcd58d added g
   |   () draft
-  o  13:be88f889b6dc added f
+  o  16:f9f6a4a00822 added f
   |   () draft
-  o  12:6642d2c9176e added d
+  o  15:44cb92e89781 added d
   |   () draft
-  o  11:95665a2de664 added c
+  o  14:152ba81b0477 added c
   |   () draft
-  o  10:87f748868183 added b
+  o  13:58b400d15a91 added b
   |   () draft
-  o  9:53b632d203d8 added a
+  o  12:53b632d203d8 added a
   |   () draft
   o  0:8fa14d15e168 added hgignore
       () draft
 
-  $ hg up 95665a2de664
+  $ hg up 'desc("added c")'
   1 files updated, 0 files merged, 4 files removed, 0 files unresolved
 
   $ echo bar > f
@@ -232,29 +290,29 @@
   4 new orphan changesets
 
   $ hg glog
-  @  16:645135c5caa4 added c
+  @  19:f4023955bf12 added c
   |   () draft
-  | *  15:09becba8f97d added h
+  | *  18:bc3b992c22bd added h
   | |   () draft orphan
-  | *  14:5aa7b2bbd944 added g
+  | *  17:28352edcd58d added g
   | |   () draft orphan
-  | *  13:be88f889b6dc added f
+  | *  16:f9f6a4a00822 added f
   | |   () draft orphan
-  | *  12:6642d2c9176e added d
+  | *  15:44cb92e89781 added d
   | |   () draft orphan
-  | x  11:95665a2de664 added c
+  | x  14:152ba81b0477 added c
   |/    () draft
-  o  10:87f748868183 added b
+  o  13:58b400d15a91 added b
   |   () draft
-  o  9:53b632d203d8 added a
+  o  12:53b632d203d8 added a
   |   () draft
   o  0:8fa14d15e168 added hgignore
       () draft
 
   $ hg evolve --all --update
-  move:[12] added d
-  atop:[16] added c
-  move:[13] added f
+  move:[15] added d
+  atop:[19] added c
+  move:[16] added f
   merging f (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
   merging f
@@ -268,10 +326,10 @@
   (no more unresolved files)
   continue: hg evolve --continue
   $ hg evolve --continue
-  evolving 13:be88f889b6dc "added f"
-  move:[14] added g
-  atop:[18] added f
-  move:[15] added h
+  evolving 16:f9f6a4a00822 "added f"
+  move:[17] added g
+  atop:[21] added f
+  move:[18] added h
   merging h (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
   merging h
@@ -285,30 +343,30 @@
   (no more unresolved files)
   continue: hg evolve --continue
   $ hg evolve --continue
-  evolving 15:09becba8f97d "added h"
-  working directory is now at 3ba9d3d1b089
+  evolving 18:bc3b992c22bd "added h"
+  working directory is now at b4b76f2b86eb
 
 Make sure, confirmopt is respected while continue
 
   $ hg glog
-  @  20:3ba9d3d1b089 added h
+  @  23:b4b76f2b86eb added h
   |   () draft
-  o  19:981e615b14ca added g
+  o  22:c75da1c807b4 added g
   |   () draft
-  o  18:5794f1a3cbb2 added f
+  o  21:1b1bb06b1b76 added f
   |   () draft
-  o  17:e47537da02b3 added d
+  o  20:63d80a6d5203 added d
   |   () draft
-  o  16:645135c5caa4 added c
+  o  19:f4023955bf12 added c
   |   () draft
-  o  10:87f748868183 added b
+  o  13:58b400d15a91 added b
   |   () draft
-  o  9:53b632d203d8 added a
+  o  12:53b632d203d8 added a
   |   () draft
   o  0:8fa14d15e168 added hgignore
       () draft
 
-  $ hg up 5794f1a3cbb2
+  $ hg up 'desc("added f")'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo bar > g
   $ hg add g
@@ -318,8 +376,8 @@
   $ hg evolve --all --update --confirm << EOF
   > y
   > EOF
-  move:[19] added g
-  atop:[21] added f
+  move:[22] added g
+  atop:[24] added f
   perform evolve? [Ny] y
   merging g (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
@@ -337,26 +395,26 @@
   $ hg evolve --continue << EOF
   > y
   > EOF
-  evolving 19:981e615b14ca "added g"
-  move:[20] added h
-  atop:[22] added g
+  evolving 22:c75da1c807b4 "added g"
+  move:[23] added h
+  atop:[25] added g
   perform evolve? [Ny] y
-  working directory is now at af6bd002a48d
+  working directory is now at 53fa2be5b910
 
   $ hg glog
-  @  23:af6bd002a48d added h
+  @  26:53fa2be5b910 added h
   |   () draft
-  o  22:d2c94a8f44bd added g
+  o  25:3efe414bea19 added g
   |   () draft
-  o  21:9849fa96c885 added f
+  o  24:a8dd354780ea added f
   |   () draft
-  o  17:e47537da02b3 added d
+  o  20:63d80a6d5203 added d
   |   () draft
-  o  16:645135c5caa4 added c
+  o  19:f4023955bf12 added c
   |   () draft
-  o  10:87f748868183 added b
+  o  13:58b400d15a91 added b
   |   () draft
-  o  9:53b632d203d8 added a
+  o  12:53b632d203d8 added a
   |   () draft
   o  0:8fa14d15e168 added hgignore
       () draft
@@ -370,8 +428,8 @@
   2 new orphan changesets
 
   $ hg next --evolve
-  move:[22] added g
-  atop:[24] added f
+  move:[25] added g
+  atop:[27] added f
   merging g (inmemory !)
   hit merge conflicts; retrying merge in working copy (inmemory !)
   merging g
@@ -384,7 +442,7 @@
   (no more unresolved files)
   continue: hg evolve --continue
   $ hg evolve --continue
-  evolving 22:d2c94a8f44bd "added g"
+  evolving 25:3efe414bea19 "added g"
 
 Testing that interrupted evolve don't get confused about copies (issue5930):
 ----------------------------------------------------------------------------
--- a/tests/test-fixup.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-fixup.t	Tue Apr 26 17:39:11 2022 +0400
@@ -271,6 +271,43 @@
   1 files updated, 0 files merged, 2 files removed, 0 files unresolved
   working directory is now at fed7e534b3bb
 
+testing continue command
+
+  $ hg up -r 'desc("baz")'
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo 'not foo' > foo
+
+  $ hg fixup -r 'desc("update foo")'
+  merging foo
+  warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ echo 'bonjour fixed' > foo
+  $ hg resolve --mark foo
+  (no more unresolved files)
+  continue: hg fixup --continue
+
+  $ hg continue
+  evolving 14:6b0b1270d7dd "temporary fixup commit"
+
+  $ hg glog
+  o  16:0dd54868f420 update foo
+  |   () draft
+  | @  14:6b0b1270d7dd temporary fixup commit
+  | |   () secret
+  | o  9:12b5e442244f baz
+  | |   () secret
+  | o  5:2eec5320cfc7 bar
+  |/    (bm) draft
+  o  0:e63c23eaa88a foo
+      () draft
+
+  $ hg evolve
+  update:[16] update foo
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  working directory is now at 0dd54868f420
+
 amending a descendant of wdp
 
   $ hg up 0
@@ -279,11 +316,11 @@
   $ hg add foobar
   $ hg fixup -r 'desc(baz)'
   $ hg glog
-  o  16:b50fd0850076 baz
+  o  19:b50fd0850076 baz
   |   () secret
-  | @  14:4a9c4d14d447 temporary fixup commit
+  | @  17:4a9c4d14d447 temporary fixup commit
   | |   () draft
-  | | o  13:fed7e534b3bb update foo
+  | | o  16:0dd54868f420 update foo
   | |/    () draft
   o |  5:2eec5320cfc7 bar
   |/    (bm) draft
@@ -291,14 +328,14 @@
       () draft
 
   $ hg evolve
-  update:[16] baz
+  update:[19] baz
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory is now at b50fd0850076
 
   $ hg glog
-  @  16:b50fd0850076 baz
+  @  19:b50fd0850076 baz
   |   () secret
-  | o  13:fed7e534b3bb update foo
+  | o  16:0dd54868f420 update foo
   | |   () draft
   o |  5:2eec5320cfc7 bar
   |/    (bm) draft
@@ -323,25 +360,25 @@
 
   $ hg fixup --continue
   abort: no interrupted fixup to continue
-  [255]
+  [20]
 
   $ hg fixup --abort
   abort: no interrupted fixup to abort
-  [255]
+  [20]
 
 testing error cases
 
   $ hg fixup tip --abort
   abort: cannot specify a revision with --abort
-  [255]
+  [10]
 
   $ hg fixup -r tip --continue
   abort: cannot specify a revision with --continue
-  [255]
+  [10]
 
   $ hg fixup
   abort: please specify a revision to fixup
-  [255]
+  [10]
 
   $ hg fixup tip
   nothing changed
@@ -368,7 +405,7 @@
 
   $ hg fixup :10 -r 5
   abort: please specify just one revision
-  [255]
+  [10]
 
   $ cd ..
 
--- a/tests/test-pick.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-pick.t	Tue Apr 26 17:39:11 2022 +0400
@@ -1,4 +1,4 @@
-#testcases abortcommand abortflag
+#testcases abortcontinuecommand abortcontinueflag
 Test for the pick command
 
   $ cat >> $HGRCPATH <<EOF
@@ -9,10 +9,11 @@
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
 
-#if abortflag
+#if abortcontinueflag
   $ cat >> $HGRCPATH <<EOF
   > [alias]
   > abort = pick --abort
+  > continue = pick --continue
   > EOF
 #endif
 
@@ -83,13 +84,18 @@
   $ hg pick --continue
   abort: no interrupted pick state exists
   [255]
+#if abortcontinuecommand
+  $ hg continue
+  abort: no operation in progress
+  [20]
+#endif
 
 Aborting without interrupted pick
 
   $ hg pick --abort
   abort: no interrupted pick state exists
   [255]
-#if abortcommand
+#if abortcontinuecommand
   $ hg abort
   abort: no operation in progress
   [20]
@@ -205,7 +211,11 @@
   $ hg resolve --all --mark
   (no more unresolved files)
   continue: hg pick --continue
-  $ hg pick --continue
+#if abortcontinuecommand
+  $ hg continue --dry-run
+  pick in progress, will be resumed
+#endif
+  $ hg continue
   $ hg glog
   @  8:44e155eb95c7 add c
   |
@@ -243,7 +253,7 @@
   (no more unresolved files)
   continue: hg pick --continue
 
-  $ hg pick --continue
+  $ hg continue
   note: picking 9:4e04628911f6 created no changes to commit
 
 Testing the abort functionality of hg pick
@@ -264,7 +274,7 @@
   unresolved merge conflicts (see hg help resolve)
   [240]
 
-#if abortcommand
+#if abortcontinuecommand
   $ hg abort --dry-run
   pick in progress, will be aborted
 #endif
@@ -330,7 +340,7 @@
   (no more unresolved files)
   continue: hg pick --continue
 
-  $ hg pick --continue
+  $ hg continue
   $ hg phase -r .
   11: secret
 
@@ -466,7 +476,7 @@
   $ hg resolve -t :other a
   (no more unresolved files)
   continue: hg pick --continue
-  $ hg pick --continue
+  $ hg continue
 
 Demonstrate that b was not forgotten and is definitely included in 4
 
--- a/tests/test-prune.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-prune.t	Tue Apr 26 17:39:11 2022 +0400
@@ -488,3 +488,16 @@
   (use 'hg evolve' to update to its parent successor)
 
   $ cd ..
+
+Test that pruning (without any successors) an already pruned
+revision doesn't give false warning about divergence creation:
+
+  $ hg init nofalsewarn
+  $ cd nofalsewarn
+  $ echo a > A
+  $ hg ci -Aqm "added a"
+  $ hg ci --amend -m "added A"
+  $ hg prune 0 --hidden
+  1 changesets pruned
+
+  $ cd ..
--- a/tests/test-topic-mode.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-topic-mode.t	Tue Apr 26 17:39:11 2022 +0400
@@ -1,14 +1,15 @@
   $ . "$TESTDIR/testlib/topic_setup.sh"
 
+  $ cat <<EOF >> $HGRCPATH
+  > [phases]
+  > publish = false
+  > EOF
+
 Testing the config knob to forbid untopiced commit
 ======================================================
 
   $ hg init $TESTTMP/untopic-commit
   $ cd $TESTTMP/untopic-commit
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = enforce
@@ -40,10 +41,6 @@
 
   $ hg init $TESTTMP/untopic-warn-commit
   $ cd $TESTTMP/untopic-warn-commit
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = warning
@@ -91,10 +88,6 @@
 
   $ hg init $TESTTMP/test-untopic-merge-commit
   $ cd $TESTTMP/test-untopic-merge-commit
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = enforce
@@ -155,10 +148,6 @@
 
   $ hg init $TESTTMP/test-untopic-merge-commit-abort
   $ cd $TESTTMP/test-untopic-merge-commit-abort
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = enforce-all
@@ -212,10 +201,6 @@
 
   $ hg init $TESTTMP/test-untopic-random
   $ cd $TESTTMP/test-untopic-random
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = random
@@ -271,15 +256,12 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg ci -m 'merge'
+
 Testing the config knob to use a random topic for untopic commit (even for merge)
 =================================================================================
 
   $ hg init $TESTTMP/test-untopic-random-all
   $ cd $TESTTMP/test-untopic-random-all
-  $ cat <<EOF >> .hg/hgrc
-  > [phases]
-  > publish=false
-  > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
   > topic-mode = random-all
--- a/tests/test-topic.t	Tue Apr 26 13:09:23 2022 +0400
+++ b/tests/test-topic.t	Tue Apr 26 17:39:11 2022 +0400
@@ -277,7 +277,7 @@
   abort: cannot use an integer as a name
   [10]
   $ hg topic '   '
-  abort: topic name cannot consist entirely of whitespaces
+  abort: topic names cannot consist entirely of whitespace
   [255]
 
   $ hg topic 'a12#45'
@@ -317,6 +317,24 @@
   $ hg topic
    * topicflag (0 changesets)
 
+Non-ascii topic name
+
+  $ hg --encoding utf-8 topic æ
+  $ hg topics
+   * \xc3\xa6 (0 changesets) (esc)
+  $ hg --encoding latin1 topics
+   * \xc3\xa6 (0 changesets) (esc)
+
+  $ hg --encoding utf-8 topic ©
+  abort: invalid topic name: '\xc2\xa9' (esc)
+  (topic names can only consist of alphanumeric, '-' '_' and '.' characters)
+  [255]
+
+  $ hg --encoding latin1 topic æ
+  abort: invalid topic name: '\xc3\xa6' (esc)
+  (topic names can only consist of alphanumeric, '-' '_' and '.' characters)
+  [255]
+
 Make a topic
 
   $ hg topic narf