changeset 45827:8d72e29ad1e0

errors: introduce InputError and use it from commands and cmdutil This patch introduces a `InputError` class and replaces many uses of `error.Abort` by it in `commands` and `cmdutil`. This is a part of https://www.mercurial-scm.org/wiki/ErrorCategoriesPlan. There will later be a different class for state errors (to raise e.g. when there's an unfinished operation). It's not always clear when one should report an input error and when it should be a state error. We can always adjust later if I got something wrong in this patch (but feel free to point out any you notice now). Differential Revision: https://phab.mercurial-scm.org/D9167
author Martin von Zweigbergk <martinvonz@google.com>
date Tue, 06 Oct 2020 22:36:15 -0700
parents 21733e8c924f
children e0dbfbd4062c
files mercurial/cmdutil.py mercurial/commands.py mercurial/error.py mercurial/scmutil.py tests/test-add.t tests/test-amend.t tests/test-archive.t tests/test-backout.t tests/test-bisect.t tests/test-bookmarks-pushpull.t tests/test-bookmarks.t tests/test-branch-change.t tests/test-branches.t tests/test-bundle-r.t tests/test-bundle-type.t tests/test-bundle.t tests/test-clone-update-order.t tests/test-clone.t tests/test-commandserver.t tests/test-commit-amend.t tests/test-commit-interactive.t tests/test-commit-unresolved.t tests/test-commit.t tests/test-config.t tests/test-confused-revert.t tests/test-copy.t tests/test-dirstate-backup.t tests/test-export.t tests/test-fix-topology.t tests/test-graft-interrupted.t tests/test-graft.t tests/test-identify.t tests/test-import-bypass.t tests/test-import.t tests/test-keyword.t tests/test-largefiles.t tests/test-log-linerange.t tests/test-manifest.t tests/test-merge-default.t tests/test-merge2.t tests/test-merge9.t tests/test-missing-capability.t tests/test-mq-qrefresh-interactive.t tests/test-newbranch.t tests/test-parents.t tests/test-push-warn.t tests/test-push.t tests/test-rebase-inmemory.t tests/test-rebase-obsolete.t tests/test-rebase-parameters.t tests/test-record.t tests/test-remotefilelog-prefetch.t tests/test-rename-after-merge.t tests/test-rename-rev.t tests/test-rename.t tests/test-resolve.t tests/test-revert.t tests/test-share-safe.t tests/test-shelve.t tests/test-simple-update.t tests/test-status-terse.t tests/test-subrepo-recursion.t tests/test-tag.t tests/test-tags.t tests/test-transplant.t tests/test-uncommit.t tests/test-update-dest.t
diffstat 67 files changed, 389 insertions(+), 340 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Wed Oct 21 19:00:16 2020 -0700
+++ b/mercurial/cmdutil.py	Tue Oct 06 22:36:15 2020 -0700
@@ -279,7 +279,7 @@
     for x in args:
         if opts.get(x):
             if previous:
-                raise error.Abort(
+                raise error.InputError(
                     _(b'cannot specify both --%s and --%s')
                     % (to_display(previous), to_display(x))
                 )
@@ -332,9 +332,9 @@
         return
 
     if len(note) > 255:
-        raise error.Abort(_(b"cannot store a note of more than 255 bytes"))
+        raise error.InputError(_(b"cannot store a note of more than 255 bytes"))
     if b'\n' in note:
-        raise error.Abort(_(b"note cannot contain a newline"))
+        raise error.InputError(_(b"note cannot contain a newline"))
 
 
 def ishunk(x):
@@ -426,7 +426,7 @@
             msg = _(b'running non-interactively, use %s instead') % cmdsuggest
         else:
             msg = _(b'running non-interactively')
-        raise error.Abort(msg)
+        raise error.InputError(msg)
 
     # make sure username is set before going interactive
     if not opts.get(b'user'):
@@ -451,7 +451,7 @@
         wctx = repo[None]
         merge = len(wctx.parents()) > 1
         if merge:
-            raise error.Abort(
+            raise error.InputError(
                 _(
                     b'cannot partially commit a merge '
                     b'(use "hg commit" instead)'
@@ -510,7 +510,7 @@
         try:
             chunks, newopts = filterfn(ui, originalchunks, match)
         except error.PatchError as err:
-            raise error.Abort(_(b'error parsing patch: %s') % err)
+            raise error.InputError(_(b'error parsing patch: %s') % err)
         opts.update(newopts)
 
         # We need to keep a backup of files that have been newly added and
@@ -600,7 +600,7 @@
                     ui.debug(fp.getvalue())
                     patch.internalpatch(ui, repo, fp, 1, eolmode=None)
                 except error.PatchError as err:
-                    raise error.Abort(pycompat.bytestr(err))
+                    raise error.InputError(pycompat.bytestr(err))
             del fp
 
             # 4. We prepared working directory according to filtered
@@ -762,7 +762,7 @@
     # checking the argument validity
     for s in pycompat.bytestr(terseargs):
         if s not in allst:
-            raise error.Abort(_(b"'%s' not recognized") % s)
+            raise error.InputError(_(b"'%s' not recognized") % s)
 
     # creating a dirnode object for the root of the repo
     rootobj = dirnode(b'')
@@ -968,10 +968,10 @@
         bailifchanged(repo)
         revs = scmutil.revrange(repo, revs)
         if not revs:
-            raise error.Abort(b"empty revision set")
+            raise error.InputError(b"empty revision set")
         roots = repo.revs(b'roots(%ld)', revs)
         if len(roots) > 1:
-            raise error.Abort(
+            raise error.InputError(
                 _(b"cannot change branch of non-linear revisions")
             )
         rewriteutil.precheck(repo, revs, b'change branch of')
@@ -983,16 +983,20 @@
             and label not in rpb
             and label in repo.branchmap()
         ):
-            raise error.Abort(_(b"a branch of the same name already exists"))
+            raise error.InputError(
+                _(b"a branch of the same name already exists")
+            )
 
         if repo.revs(b'obsolete() and %ld', revs):
-            raise error.Abort(
+            raise error.InputError(
                 _(b"cannot change branch of a obsolete changeset")
             )
 
         # make sure only topological heads
         if repo.revs(b'heads(%ld) - head()', revs):
-            raise error.Abort(_(b"cannot change branch in middle of a stack"))
+            raise error.InputError(
+                _(b"cannot change branch in middle of a stack")
+            )
 
         replacements = {}
         # avoid import cycle mercurial.cmdutil -> mercurial.context ->
@@ -1373,7 +1377,7 @@
                 b'without a repository'
             )
     if msg:
-        raise error.Abort(msg)
+        raise error.InputError(msg)
 
     r = None
     if repo:
@@ -1381,7 +1385,7 @@
             r = repo.unfiltered().changelog
         elif dir:
             if not scmutil.istreemanifest(repo):
-                raise error.Abort(
+                raise error.InputError(
                     _(
                         b"--dir can only be used on repos with "
                         b"treemanifest enabled"
@@ -1407,16 +1411,18 @@
             elif util.safehasattr(r, b'_revlog'):
                 r = r._revlog  # pytype: disable=attribute-error
             elif r is not None:
-                raise error.Abort(_(b'%r does not appear to be a revlog') % r)
+                raise error.InputError(
+                    _(b'%r does not appear to be a revlog') % r
+                )
 
     if not r:
         if not returnrevlog:
-            raise error.Abort(_(b'cannot give path to non-revlog'))
+            raise error.InputError(_(b'cannot give path to non-revlog'))
 
         if not file_:
             raise error.CommandError(cmd, _(b'invalid arguments'))
         if not os.path.isfile(file_):
-            raise error.Abort(_(b"revlog '%s' not found") % file_)
+            raise error.InputError(_(b"revlog '%s' not found") % file_)
         r = revlog.revlog(
             vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i"
         )
@@ -1453,10 +1459,12 @@
         if not forget and not after:
             # TODO: Remove this restriction and make it also create the copy
             #       targets (and remove the rename source if rename==True).
-            raise error.Abort(_(b'--at-rev requires --after'))
+            raise error.InputError(_(b'--at-rev requires --after'))
         ctx = scmutil.revsingle(repo, rev)
         if len(ctx.parents()) > 1:
-            raise error.Abort(_(b'cannot mark/unmark copy in merge commit'))
+            raise error.InputError(
+                _(b'cannot mark/unmark copy in merge commit')
+            )
     else:
         ctx = repo[None]
 
@@ -1469,7 +1477,7 @@
             new_ctx = ctx
         else:
             if len(ctx.parents()) > 1:
-                raise error.Abort(_(b'cannot unmark copy in merge commit'))
+                raise error.InputError(_(b'cannot unmark copy in merge commit'))
             # avoid cycle context -> subrepo -> cmdutil
             from . import context
 
@@ -1512,9 +1520,9 @@
 
     pats = scmutil.expandpats(pats)
     if not pats:
-        raise error.Abort(_(b'no source or destination specified'))
+        raise error.InputError(_(b'no source or destination specified'))
     if len(pats) == 1:
-        raise error.Abort(_(b'no destination specified'))
+        raise error.InputError(_(b'no destination specified'))
     dest = pats.pop()
 
     def walkpat(pat):
@@ -1554,12 +1562,12 @@
         rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
         absdest = pathutil.canonpath(repo.root, cwd, dest)
         if ctx.hasdir(absdest):
-            raise error.Abort(
+            raise error.InputError(
                 _(b'%s: --at-rev does not support a directory as destination')
                 % uipathfn(absdest)
             )
         if absdest not in ctx:
-            raise error.Abort(
+            raise error.InputError(
                 _(b'%s: copy destination does not exist in %s')
                 % (uipathfn(absdest), ctx)
             )
@@ -1576,12 +1584,12 @@
                 copylist.append(abs)
 
         if not copylist:
-            raise error.Abort(_(b'no files to copy'))
+            raise error.InputError(_(b'no files to copy'))
         # TODO: Add support for `hg cp --at-rev . foo bar dir` and
         # `hg cp --at-rev . dir1 dir2`, preferably unifying the code with the
         # existing functions below.
         if len(copylist) != 1:
-            raise error.Abort(_(b'--at-rev requires a single source'))
+            raise error.InputError(_(b'--at-rev requires a single source'))
 
         new_ctx = context.overlayworkingctx(repo)
         new_ctx.setbase(ctx.p1())
@@ -1809,14 +1817,16 @@
     destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
     if not destdirexists:
         if len(pats) > 1 or matchmod.patkind(pats[0]):
-            raise error.Abort(
+            raise error.InputError(
                 _(
                     b'with multiple sources, destination must be an '
                     b'existing directory'
                 )
             )
         if util.endswithsep(dest):
-            raise error.Abort(_(b'destination %s is not a directory') % dest)
+            raise error.InputError(
+                _(b'destination %s is not a directory') % dest
+            )
 
     tfn = targetpathfn
     if after:
@@ -1828,7 +1838,7 @@
             continue
         copylist.append((tfn(pat, dest, srcs), srcs))
     if not copylist:
-        raise error.Abort(_(b'no files to copy'))
+        raise error.InputError(_(b'no files to copy'))
 
     errors = 0
     for targetpath, srcs in copylist:
@@ -1919,7 +1929,7 @@
         parents.append(repo[nullid])
     if opts.get(b'exact'):
         if not nodeid or not p1:
-            raise error.Abort(_(b'not a Mercurial patch'))
+            raise error.InputError(_(b'not a Mercurial patch'))
         p1 = repo[p1]
         p2 = repo[p2 or nullid]
     elif p2:
@@ -2255,7 +2265,7 @@
     try:
         rev = mrevs.max()
     except ValueError:
-        raise error.Abort(_(b"revision matching date not found"))
+        raise error.InputError(_(b"revision matching date not found"))
 
     ui.status(
         _(b"found revision %d from %s\n")
@@ -2338,7 +2348,9 @@
     ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive
 ):
     if dryrun and interactive:
-        raise error.Abort(_(b"cannot specify both --dry-run and --interactive"))
+        raise error.InputError(
+            _(b"cannot specify both --dry-run and --interactive")
+        )
     bad = []
     badfn = lambda x, y: bad.append(x) or match.bad(x, y)
     wctx = repo[None]
@@ -3050,9 +3062,9 @@
     if finishdesc:
         text = finishdesc(text)
     if not text.strip():
-        raise error.Abort(_(b"empty commit message"))
+        raise error.InputError(_(b"empty commit message"))
     if unchangedmessagedetection and editortext == templatetext:
-        raise error.Abort(_(b"commit message unchanged"))
+        raise error.InputError(_(b"commit message unchanged"))
 
     return text
 
--- a/mercurial/commands.py	Wed Oct 21 19:00:16 2020 -0700
+++ b/mercurial/commands.py	Tue Oct 06 22:36:15 2020 -0700
@@ -189,7 +189,7 @@
     if not abortstate:
         raise error.Abort(_(b'no operation in progress'))
     if not abortstate.abortfunc:
-        raise error.Abort(
+        raise error.InputError(
             (
                 _(b"%s in progress but does not support 'hg abort'")
                 % (abortstate._opname)
@@ -418,7 +418,9 @@
     """
     opts = pycompat.byteskwargs(opts)
     if not pats:
-        raise error.Abort(_(b'at least one filename or pattern is required'))
+        raise error.InputError(
+            _(b'at least one filename or pattern is required')
+        )
 
     if opts.get(b'follow'):
         # --follow is deprecated and now just an alias for -f/--file
@@ -439,7 +441,7 @@
         and (not opts.get(b'changeset'))
         and (not opts.get(b'number'))
     ):
-        raise error.Abort(_(b'at least one of -n/-c is required for -l'))
+        raise error.InputError(_(b'at least one of -n/-c is required for -l'))
 
     rev = opts.get(b'rev')
     if rev:
@@ -650,18 +652,20 @@
         repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
     ctx = scmutil.revsingle(repo, rev)
     if not ctx:
-        raise error.Abort(_(b'no working directory: please specify a revision'))
+        raise error.InputError(
+            _(b'no working directory: please specify a revision')
+        )
     node = ctx.node()
     dest = cmdutil.makefilename(ctx, dest)
     if os.path.realpath(dest) == repo.root:
-        raise error.Abort(_(b'repository root cannot be destination'))
+        raise error.InputError(_(b'repository root cannot be destination'))
 
     kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
     prefix = opts.get(b'prefix')
 
     if dest == b'-':
         if kind == b'files':
-            raise error.Abort(_(b'cannot archive plain files to stdout'))
+            raise error.InputError(_(b'cannot archive plain files to stdout'))
         dest = cmdutil.makefileobj(ctx, dest)
         if not prefix:
             prefix = os.path.basename(repo.root) + b'-%h'
@@ -774,13 +778,13 @@
     opts = pycompat.byteskwargs(opts)
 
     if rev and node:
-        raise error.Abort(_(b"please specify just one revision"))
+        raise error.InputError(_(b"please specify just one revision"))
 
     if not rev:
         rev = node
 
     if not rev:
-        raise error.Abort(_(b"please specify a revision to backout"))
+        raise error.InputError(_(b"please specify a revision to backout"))
 
     date = opts.get(b'date')
     if date:
@@ -793,23 +797,27 @@
 
     op1, op2 = repo.dirstate.parents()
     if not repo.changelog.isancestor(node, op1):
-        raise error.Abort(_(b'cannot backout change that is not an ancestor'))
+        raise error.InputError(
+            _(b'cannot backout change that is not an ancestor')
+        )
 
     p1, p2 = repo.changelog.parents(node)
     if p1 == nullid:
-        raise error.Abort(_(b'cannot backout a change with no parents'))
+        raise error.InputError(_(b'cannot backout a change with no parents'))
     if p2 != nullid:
         if not opts.get(b'parent'):
-            raise error.Abort(_(b'cannot backout a merge changeset'))
+            raise error.InputError(_(b'cannot backout a merge changeset'))
         p = repo.lookup(opts[b'parent'])
         if p not in (p1, p2):
-            raise error.Abort(
+            raise error.InputError(
                 _(b'%s is not a parent of %s') % (short(p), short(node))
             )
         parent = p
     else:
         if opts.get(b'parent'):
-            raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
+            raise error.InputError(
+                _(b'cannot use --parent on non-merge changeset')
+            )
         parent = p1
 
     # the backout should appear on the same branch
@@ -1001,7 +1009,7 @@
         else:
             reset = True
     elif extra:
-        raise error.Abort(_(b'incompatible arguments'))
+        raise error.InputError(_(b'incompatible arguments'))
 
     incompatibles = {
         b'--bad': bad,
@@ -1015,7 +1023,7 @@
     enabled = [x for x in incompatibles if incompatibles[x]]
 
     if len(enabled) > 1:
-        raise error.Abort(
+        raise error.InputError(
             _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
         )
 
@@ -1236,7 +1244,7 @@
         opts, b'inactive', [b'delete', b'list']
     )
     if not names and action in {b'add', b'delete'}:
-        raise error.Abort(_(b"bookmark name required"))
+        raise error.InputError(_(b"bookmark name required"))
 
     if action in {b'add', b'delete', b'rename', b'inactive'}:
         with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
@@ -1245,9 +1253,11 @@
                 bookmarks.delete(repo, tr, names)
             elif action == b'rename':
                 if not names:
-                    raise error.Abort(_(b"new bookmark name required"))
+                    raise error.InputError(_(b"new bookmark name required"))
                 elif len(names) > 1:
-                    raise error.Abort(_(b"only one new bookmark name allowed"))
+                    raise error.InputError(
+                        _(b"only one new bookmark name allowed")
+                    )
                 oldname = repo._bookmarks.expandname(opts[b'rename'])
                 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
             elif action == b'add':
@@ -1323,7 +1333,9 @@
 
     if not opts.get(b'clean') and not label:
         if revs:
-            raise error.Abort(_(b"no branch name specified for the revisions"))
+            raise error.InputError(
+                _(b"no branch name specified for the revisions")
+            )
         ui.write(b"%s\n" % repo.dirstate.branch())
         return
 
@@ -1340,7 +1352,7 @@
 
             if not opts.get(b'force') and label in repo.branchmap():
                 if label not in [p.branch() for p in repo[None].parents()]:
-                    raise error.Abort(
+                    raise error.InputError(
                         _(b'a branch of the same name already exists'),
                         # i18n: "it" refers to an existing branch
                         hint=_(b"use 'hg update' to switch to it"),
@@ -1542,7 +1554,7 @@
         revstrings = opts[b'rev']
         revs = scmutil.revrange(repo, revstrings)
         if revstrings and not revs:
-            raise error.Abort(_(b'no commits to bundle'))
+            raise error.InputError(_(b'no commits to bundle'))
 
     bundletype = opts.get(b'type', b'bzip2').lower()
     try:
@@ -1550,7 +1562,7 @@
             repo, bundletype, strict=False
         )
     except error.UnsupportedBundleSpecification as e:
-        raise error.Abort(
+        raise error.InputError(
             pycompat.bytestr(e),
             hint=_(b"see 'hg help bundlespec' for supported values for --type"),
         )
@@ -1558,14 +1570,14 @@
 
     # Packed bundles are a pseudo bundle format for now.
     if cgversion == b's1':
-        raise error.Abort(
+        raise error.InputError(
             _(b'packed bundles cannot be produced by "hg bundle"'),
             hint=_(b"use 'hg debugcreatestreamclonebundle'"),
         )
 
     if opts.get(b'all'):
         if dest:
-            raise error.Abort(
+            raise error.InputError(
                 _(b"--all is incompatible with specifying a destination")
             )
         if opts.get(b'base'):
@@ -1580,7 +1592,7 @@
 
     if base:
         if dest:
-            raise error.Abort(
+            raise error.InputError(
                 _(b"--base is incompatible with specifying a destination")
             )
         common = [repo[rev].node() for rev in base]
@@ -2034,11 +2046,13 @@
         extra[b'close'] = b'1'
 
         if repo[b'.'].closesbranch():
-            raise error.Abort(
+            raise error.InputError(
                 _(b'current revision is already a branch closing head')
             )
         elif not bheads:
-            raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
+            raise error.InputError(
+                _(b'branch "%s" has no heads to close') % branch
+            )
         elif (
             branch == repo[b'.'].branch()
             and repo[b'.'].node() not in bheads
@@ -2048,17 +2062,19 @@
                 b'use --force-close-branch to close branch from a non-head'
                 b' changeset'
             )
-            raise error.Abort(_(b'can only close branch heads'), hint=hint)
+            raise error.InputError(_(b'can only close branch heads'), hint=hint)
         elif opts.get(b'amend'):
             if (
                 repo[b'.'].p1().branch() != branch
                 and repo[b'.'].p2().branch() != branch
             ):
-                raise error.Abort(_(b'can only close branch heads'))
+                raise error.InputError(_(b'can only close branch heads'))
 
     if opts.get(b'amend'):
         if ui.configbool(b'ui', b'commitsubrepos'):
-            raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
+            raise error.InputError(
+                _(b'cannot amend with ui.commitsubrepos enabled')
+            )
 
         old = repo[b'.']
         rewriteutil.precheck(repo, [old.rev()], b'amend')
@@ -2200,17 +2216,19 @@
         cmdutil.check_at_most_one_arg(opts, *editopts[1:])
         if opts.get(b'local'):
             if not repo:
-                raise error.Abort(_(b"can't use --local outside a repository"))
+                raise error.InputError(
+                    _(b"can't use --local outside a repository")
+                )
             paths = [repo.vfs.join(b'hgrc')]
         elif opts.get(b'global'):
             paths = rcutil.systemrcpath()
         elif opts.get(b'shared'):
             if not repo.shared():
-                raise error.Abort(
+                raise error.InputError(
                     _(b"repository is not shared; can't use --shared")
                 )
                 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
-                    raise error.Abort(
+                    raise error.InputError(
                         _(
                             b"share safe feature not unabled; "
                             b"unable to edit shared source repository config"
@@ -2241,7 +2259,7 @@
         editor = ui.geteditor()
         ui.system(
             b"%s \"%s\"" % (editor, f),
-            onerr=error.Abort,
+            onerr=error.InputError,
             errprefix=_(b"edit failed"),
             blockedtag=b'config_edit',
         )
@@ -2649,7 +2667,7 @@
 
     if bookmark:
         if bookmark not in repo._bookmarks:
-            raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
+            raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
 
         revs = scmutil.bookmarkrevs(repo, bookmark)
     else:
@@ -2660,7 +2678,7 @@
         revs = scmutil.revrange(repo, changesets)
 
     if not revs:
-        raise error.Abort(_(b"export requires at least one changeset"))
+        raise error.InputError(_(b"export requires at least one changeset"))
     if len(revs) > 1:
         ui.note(_(b'exporting patches:\n'))
     else:
@@ -2825,7 +2843,7 @@
 
     opts = pycompat.byteskwargs(opts)
     if not pats:
-        raise error.Abort(_(b'no files specified'))
+        raise error.InputError(_(b'no files specified'))
 
     m = scmutil.match(repo[None], pats, opts)
     dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
@@ -3052,7 +3070,7 @@
     elif opts.get(b'continue'):
         cont = True
         if revs:
-            raise error.Abort(_(b"can't specify --continue and revisions"))
+            raise error.InputError(_(b"can't specify --continue and revisions"))
         # read in unfinished revisions
         if graftstate.exists():
             statedata = cmdutil.readgraftstate(repo, graftstate)
@@ -3072,7 +3090,7 @@
             cmdutil.wrongtooltocontinue(repo, _(b'graft'))
     else:
         if not revs:
-            raise error.Abort(_(b'no revisions specified'))
+            raise error.InputError(_(b'no revisions specified'))
         cmdutil.checkunfinished(repo)
         cmdutil.bailifchanged(repo)
         revs = scmutil.revrange(repo, revs)
@@ -3090,7 +3108,7 @@
     if not revs:
         return -1
     if basectx is not None and len(revs) != 1:
-        raise error.Abort(_(b'only one revision allowed with --base '))
+        raise error.InputError(_(b'only one revision allowed with --base '))
 
     # Don't check in the --continue case, in effect retaining --force across
     # --continues. That's because without --force, any revisions we decided to
@@ -3765,7 +3783,7 @@
 
     opts = pycompat.byteskwargs(opts)
     if not repo and not source:
-        raise error.Abort(
+        raise error.InputError(
             _(b"there is no Mercurial repository here (.hg not found)")
         )
 
@@ -3784,7 +3802,7 @@
 
     if not repo:
         if num or branch or tags:
-            raise error.Abort(
+            raise error.InputError(
                 _(b"can't query remote revision number, branch, or tags")
             )
         if not rev and revs:
@@ -4056,7 +4074,7 @@
     cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
     opts = pycompat.byteskwargs(opts)
     if not patch1:
-        raise error.Abort(_(b'need at least one patch to import'))
+        raise error.InputError(_(b'need at least one patch to import'))
 
     patches = (patch1,) + patches
 
@@ -4069,11 +4087,11 @@
     try:
         sim = float(opts.get(b'similarity') or 0)
     except ValueError:
-        raise error.Abort(_(b'similarity must be a number'))
+        raise error.InputError(_(b'similarity must be a number'))
     if sim < 0 or sim > 100:
-        raise error.Abort(_(b'similarity must be between 0 and 100'))
+        raise error.InputError(_(b'similarity must be between 0 and 100'))
     if sim and not update:
-        raise error.Abort(_(b'cannot use --similarity with --bypass'))
+        raise error.InputError(_(b'cannot use --similarity with --bypass'))
 
     base = opts[b"base"]
     msgs = []
@@ -4130,7 +4148,7 @@
                         break
 
                 if not haspatch:
-                    raise error.Abort(_(b'%s: no diffs found') % patchurl)
+                    raise error.InputError(_(b'%s: no diffs found') % patchurl)
 
             if msgs:
                 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
@@ -4586,11 +4604,11 @@
     linerange = opts.get(b'line_range')
 
     if linerange and not opts.get(b'follow'):
-        raise error.Abort(_(b'--line-range requires --follow'))
+        raise error.InputError(_(b'--line-range requires --follow'))
 
     if linerange and pats:
         # TODO: take pats as patterns with no line-range filter
-        raise error.Abort(
+        raise error.InputError(
             _(b'FILE arguments are not compatible with --line-range option')
         )
 
@@ -4652,7 +4670,7 @@
 
     if opts.get(b'all'):
         if rev or node:
-            raise error.Abort(_(b"can't specify a revision with --all"))
+            raise error.InputError(_(b"can't specify a revision with --all"))
 
         res = set()
         for rev in repo:
@@ -4667,7 +4685,7 @@
         return
 
     if rev and node:
-        raise error.Abort(_(b"please specify just one revision"))
+        raise error.InputError(_(b"please specify just one revision"))
 
     if not node:
         node = rev
@@ -4754,11 +4772,11 @@
                 hint=state.hint(),
             )
         if node:
-            raise error.Abort(_(b"cannot specify a node with --abort"))
+            raise error.InputError(_(b"cannot specify a node with --abort"))
         return hg.abortmerge(repo.ui, repo)
 
     if opts.get(b'rev') and node:
-        raise error.Abort(_(b"please specify just one revision"))
+        raise error.InputError(_(b"please specify just one revision"))
     if not node:
         node = opts.get(b'rev')
 
@@ -4766,7 +4784,7 @@
         ctx = scmutil.revsingle(repo, node)
     else:
         if ui.configbool(b'commands', b'merge.require-rev'):
-            raise error.Abort(
+            raise error.InputError(
                 _(
                     b'configuration requires specifying revision to merge '
                     b'with'
@@ -4775,7 +4793,9 @@
         ctx = repo[destutil.destmerge(repo)]
 
     if ctx.node() is None:
-        raise error.Abort(_(b'merging with the working copy has no effect'))
+        raise error.InputError(
+            _(b'merging with the working copy has no effect')
+        )
 
     if opts.get(b'preview'):
         # find nodes that are ancestors of p2 but not of p1
@@ -4968,7 +4988,7 @@
     if file_:
         m = scmutil.match(ctx, (file_,), opts)
         if m.anypats() or len(m.files()) != 1:
-            raise error.Abort(_(b'can only specify an explicit filename'))
+            raise error.InputError(_(b'can only specify an explicit filename'))
         file_ = m.files()[0]
         filenodes = []
         for cp in ctx.parents():
@@ -4979,7 +4999,7 @@
             except error.LookupError:
                 pass
         if not filenodes:
-            raise error.Abort(_(b"'%s' not found in manifest!") % file_)
+            raise error.InputError(_(b"'%s' not found in manifest!") % file_)
         p = []
         for fn in filenodes:
             fctx = repo.filectx(file_, fileid=fn)
@@ -5121,7 +5141,7 @@
     for idx, name in enumerate(phases.cmdphasenames):
         if opts[name]:
             if targetphase is not None:
-                raise error.Abort(_(b'only one phase can be specified'))
+                raise error.InputError(_(b'only one phase can be specified'))
             targetphase = idx
 
     # look for specified revision
@@ -5144,7 +5164,7 @@
         with repo.lock(), repo.transaction(b"phase") as tr:
             # set phase
             if not revs:
-                raise error.Abort(_(b'empty revision set'))
+                raise error.InputError(_(b'empty revision set'))
             nodes = [repo[r].node() for r in revs]
             # moving revision from public to draft may hide them
             # We have to check result on an unfiltered repository
@@ -5287,7 +5307,7 @@
     ):
         msg = _(b'update destination required by configuration')
         hint = _(b'use hg pull followed by hg update DEST')
-        raise error.Abort(msg, hint=hint)
+        raise error.InputError(msg, hint=hint)
 
     source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
     ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
@@ -5326,7 +5346,9 @@
             for b in opts.get(b'bookmark', []):
                 b = repo._bookmarks.expandname(b)
                 if b not in remotebookmarks:
-                    raise error.Abort(_(b'remote bookmark %s not found!') % b)
+                    raise error.InputError(
+                        _(b'remote bookmark %s not found!') % b
+                    )
                 nodes.append(remotebookmarks[b])
             for i, rev in enumerate(revs):
                 node = fnodes[i].result()
@@ -5515,7 +5537,7 @@
     if revs:
         revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
         if not revs:
-            raise error.Abort(
+            raise error.InputError(
                 _(b"specified revisions evaluate to an empty set"),
                 hint=_(b"use different revision arguments"),
             )
@@ -5526,11 +5548,11 @@
         revs = scmutil.revrange(repo, [expr])
         revs = [repo[rev].node() for rev in revs]
         if not revs:
-            raise error.Abort(
+            raise error.InputError(
                 _(b'default push revset for path evaluates to an empty set')
             )
     elif ui.configbool(b'commands', b'push.require-revs'):
-        raise error.Abort(
+        raise error.InputError(
             _(b'no revisions specified to push'),
             hint=_(b'did you mean "hg push -r ."?'),
         )
@@ -5659,7 +5681,7 @@
     after, force = opts.get(b'after'), opts.get(b'force')
     dryrun = opts.get(b'dry_run')
     if not pats and not after:
-        raise error.Abort(_(b'no files specified'))
+        raise error.InputError(_(b'no files specified'))
 
     m = scmutil.match(repo[None], pats, opts)
     subrepos = opts.get(b'subrepos')
@@ -5789,16 +5811,16 @@
 
     actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
     if actioncount > 1:
-        raise error.Abort(_(b"too many actions specified"))
+        raise error.InputError(_(b"too many actions specified"))
     elif actioncount == 0 and ui.configbool(
         b'commands', b'resolve.explicit-re-merge'
     ):
         hint = _(b'use --mark, --unmark, --list or --re-merge')
-        raise error.Abort(_(b'no action specified'), hint=hint)
+        raise error.InputError(_(b'no action specified'), hint=hint)
     if pats and all:
-        raise error.Abort(_(b"can't specify --all and patterns"))
+        raise error.InputError(_(b"can't specify --all and patterns"))
     if not (all or pats or show or mark or unmark):
-        raise error.Abort(
+        raise error.InputError(
             _(b'no files or directories specified'),
             hint=b'use --all to re-merge all unresolved files',
         )
@@ -6082,7 +6104,7 @@
     parent, p2 = repo.dirstate.parents()
     if not opts.get(b'rev') and p2 != nullid:
         # revert after merge is a trap for new users (issue2915)
-        raise error.Abort(
+        raise error.InputError(
             _(b'uncommitted merge with no revision specified'),
             hint=_(b"use 'hg update' or see 'hg help revert'"),
         )
@@ -6105,7 +6127,7 @@
                 b"uncommitted merge, use --all to discard all changes,"
                 b" or 'hg update -C .' to abort the merge"
             )
-            raise error.Abort(msg, hint=hint)
+            raise error.InputError(msg, hint=hint)
         dirty = any(repo.status())
         node = ctx.node()
         if node != parent:
@@ -6129,7 +6151,7 @@
             hint = _(b"uncommitted changes, use --all to discard all changes")
         else:
             hint = _(b"use --all to revert all files")
-        raise error.Abort(msg, hint=hint)
+        raise error.InputError(msg, hint=hint)
 
     return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
 
@@ -6339,7 +6361,7 @@
     cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
     opts = pycompat.byteskwargs(opts)
     if opts[b"print_url"] and ui.verbose:
-        raise error.Abort(_(b"cannot use --print-url with --verbose"))
+        raise error.InputError(_(b"cannot use --print-url with --verbose"))
 
     if opts[b"stdio"]:
         if repo is None:
@@ -6466,7 +6488,7 @@
         if opts.get(opt):
             for i, allowable in allowables:
                 if opts[i] and opt not in allowable:
-                    raise error.Abort(
+                    raise error.InputError(
                         _(
                             b"options '--%s' and '--%s' may not be "
                             b"used together"
@@ -6477,7 +6499,9 @@
 
     if checkopt(b'cleanup'):
         if pats:
-            raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
+            raise error.InputError(
+                _(b"cannot specify names when using '--cleanup'")
+            )
         return shelvemod.cleanupcmd(ui, repo)
     elif checkopt(b'delete'):
         return shelvemod.deletecmd(ui, repo, pats)
@@ -6643,7 +6667,7 @@
 
     if revs and terse:
         msg = _(b'cannot use --terse with --rev')
-        raise error.Abort(msg)
+        raise error.InputError(msg)
     elif change:
         repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
         ctx2 = scmutil.revsingle(repo, change, None)
@@ -7114,11 +7138,11 @@
         rev_ = b"."
         names = [t.strip() for t in (name1,) + names]
         if len(names) != len(set(names)):
-            raise error.Abort(_(b'tag names must be unique'))
+            raise error.InputError(_(b'tag names must be unique'))
         for n in names:
             scmutil.checknewlabel(repo, n, b'tag')
             if not n:
-                raise error.Abort(
+                raise error.InputError(
                     _(b'tag names cannot consist entirely of whitespace')
                 )
         if opts.get(b'rev'):
@@ -7134,16 +7158,20 @@
                 if repo.tagtype(n) == b'global':
                     alltags = tagsmod.findglobaltags(ui, repo)
                     if alltags[n][0] == nullid:
-                        raise error.Abort(_(b"tag '%s' is already removed") % n)
+                        raise error.InputError(
+                            _(b"tag '%s' is already removed") % n
+                        )
                 if not repo.tagtype(n):
-                    raise error.Abort(_(b"tag '%s' does not exist") % n)
+                    raise error.InputError(_(b"tag '%s' does not exist") % n)
                 if repo.tagtype(n) != expectedtype:
                     if expectedtype == b'global':
-                        raise error.Abort(
+                        raise error.InputError(
                             _(b"tag '%s' is not a global tag") % n
                         )
                     else:
-                        raise error.Abort(_(b"tag '%s' is not a local tag") % n)
+                        raise error.InputError(
+                            _(b"tag '%s' is not a local tag") % n
+                        )
             rev_ = b'null'
             if not message:
                 # we don't translate commit messages
@@ -7151,7 +7179,7 @@
         elif not opts.get(b'force'):
             for n in names:
                 if n in repo.tags():
-                    raise error.Abort(
+                    raise error.InputError(
                         _(b"tag '%s' already exists (use -f to force)") % n
                     )
         if not opts.get(b'local'):
@@ -7160,7 +7188,7 @@
                 raise error.Abort(_(b'uncommitted merge'))
             bheads = repo.branchheads()
             if not opts.get(b'force') and bheads and p1 not in bheads:
-                raise error.Abort(
+                raise error.InputError(
                     _(
                         b'working directory is not at a branch head '
                         b'(use -f to force)'
@@ -7192,7 +7220,7 @@
             not opts.get(b'remove')
             and scmutil.revsingle(repo, rev_).rev() == nullrev
         ):
-            raise error.Abort(_(b"cannot tag null revision"))
+            raise error.InputError(_(b"cannot tag null revision"))
 
         tagsmod.tag(
             repo,
@@ -7324,7 +7352,7 @@
             f = hg.openpath(ui, fname)
             gen = exchange.readbundle(ui, f, fname)
             if isinstance(gen, streamclone.streamcloneapplier):
-                raise error.Abort(
+                raise error.InputError(
                     _(
                         b'packed bundles cannot be applied with '
                         b'"hg unbundle"'
@@ -7519,11 +7547,11 @@
     check = opts.get('check')
     merge = opts.get('merge')
     if rev and node:
-        raise error.Abort(_(b"please specify just one revision"))
+        raise error.InputError(_(b"please specify just one revision"))
 
     if ui.configbool(b'commands', b'update.requiredest'):
         if not node and not rev and not date:
-            raise error.Abort(
+            raise error.InputError(
                 _(b'you must specify a destination'),
                 hint=_(b'for example: hg update ".::"'),
             )
@@ -7532,7 +7560,7 @@
         rev = node
 
     if date and rev is not None:
-        raise error.Abort(_(b"you can't specify a revision and a date"))
+        raise error.InputError(_(b"you can't specify a revision and a date"))
 
     updatecheck = None
     if check:
--- a/mercurial/error.py	Wed Oct 21 19:00:16 2020 -0700
+++ b/mercurial/error.py	Tue Oct 06 22:36:15 2020 -0700
@@ -181,6 +181,13 @@
             return pycompat.sysstr(self.__bytes__())
 
 
+class InputError(Abort):
+    """Indicates that the user made an error in their input.
+
+    Examples: Invalid command, invalid flags, invalid revision.
+    """
+
+
 class HookLoadError(Abort):
     """raised when loading a hook fails, aborting an operation
 
--- a/mercurial/scmutil.py	Wed Oct 21 19:00:16 2020 -0700
+++ b/mercurial/scmutil.py	Tue Oct 06 22:36:15 2020 -0700
@@ -219,6 +219,8 @@
     except error.WdirUnsupported:
         ui.error(_(b"abort: working directory revision cannot be specified\n"))
     except error.Abort as inst:
+        if isinstance(inst, error.InputError):
+            detailed_exit_code = 10
         ui.error(_(b"abort: %s\n") % inst.message)
         if inst.hint:
             ui.error(_(b"(%s)\n") % inst.hint)
--- a/tests/test-add.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-add.t	Tue Oct 06 22:36:15 2020 -0700
@@ -286,7 +286,7 @@
   $ hg commit -qAm "bar"
   $ hg forget foo --dry-run -i
   abort: cannot specify both --dry-run and --interactive
-  [255]
+  [10]
 
   $ hg forget foo --config ui.interactive=True -i << EOF
   > ?
--- a/tests/test-amend.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-amend.t	Tue Oct 06 22:36:15 2020 -0700
@@ -153,7 +153,7 @@
   $ echo FOO > $TESTTMP/msg
   $ hg amend -l $TESTTMP/msg -m BAR
   abort: cannot specify both --message and --logfile
-  [255]
+  [10]
   $ hg amend -l $TESTTMP/msg
   saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/974f07f28537-edb6470a-amend.hg (obsstore-off !)
   $ hg log -r . -T '{node|short} {desc}\n'
@@ -226,7 +226,7 @@
   $ hg add bar
   $ hg amend --note 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
   abort: cannot store a note of more than 255 bytes
-  [255]
+  [10]
   $ hg amend --note "adding bar"
   $ hg debugobsolete -r .
   112478962961147124edd43549aedd1a335e44bf be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
@@ -471,7 +471,7 @@
 
   $ hg amend -D --date '0 0'
   abort: cannot specify both --date and --currentdate
-  [255]
+  [10]
 
 Close branch
 
--- a/tests/test-archive.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-archive.t	Tue Oct 06 22:36:15 2020 -0700
@@ -560,7 +560,7 @@
   $ cd ../empty
   $ hg archive ../test-empty
   abort: no working directory: please specify a revision
-  [255]
+  [10]
 
 old file -- date clamped to 1980
 
--- a/tests/test-backout.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-backout.t	Tue Oct 06 22:36:15 2020 -0700
@@ -5,10 +5,10 @@
 
   $ hg backout
   abort: please specify a revision to backout
-  [255]
+  [10]
   $ hg backout -r 0 0
   abort: please specify just one revision
-  [255]
+  [10]
 
 basic operation
 (this also tests that editor is invoked if the commit message is not
@@ -210,7 +210,7 @@
 
   $ hg backout 1
   abort: cannot backout change that is not an ancestor
-  [255]
+  [10]
   $ echo c > c
   $ hg ci -Am2
   adding c
@@ -227,7 +227,7 @@
 
   $ hg backout 1
   abort: cannot backout change that is not an ancestor
-  [255]
+  [10]
   $ hg summary
   parent: 2:db815d6d32e6 tip
    2
@@ -464,19 +464,19 @@
 
   $ hg backout 4
   abort: cannot backout a merge changeset
-  [255]
+  [10]
 
 backout of merge with bad parent should fail
 
   $ hg backout --parent 0 4
   abort: cb9a9f314b8b is not a parent of b2f3bb92043e
-  [255]
+  [10]
 
 backout of non-merge with parent should fail
 
   $ hg backout --parent 0 3
   abort: cannot use --parent on non-merge changeset
-  [255]
+  [10]
 
 backout with valid parent should be ok
 
@@ -805,7 +805,7 @@
 
   $ hg backout --merge --no-commit 2
   abort: cannot specify both --no-commit and --merge
-  [255]
+  [10]
 
 Ensure that backout out the same changeset twice performs correctly:
 
--- a/tests/test-bisect.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bisect.t	Tue Oct 06 22:36:15 2020 -0700
@@ -751,46 +751,46 @@
   $ hg bisect -r
   $ hg bisect -b -c false
   abort: --bad and --command are incompatible
-  [255]
+  [10]
   $ hg bisect -b -e
   abort: --bad and --extend are incompatible
-  [255]
+  [10]
   $ hg bisect -b -g
   abort: --bad and --good are incompatible
-  [255]
+  [10]
   $ hg bisect -b -r
   abort: --bad and --reset are incompatible
-  [255]
+  [10]
   $ hg bisect -b -s
   abort: --bad and --skip are incompatible
-  [255]
+  [10]
   $ hg bisect -c false -e
   abort: --command and --extend are incompatible
-  [255]
+  [10]
   $ hg bisect -c false -g
   abort: --command and --good are incompatible
-  [255]
+  [10]
   $ hg bisect -c false -r
   abort: --command and --reset are incompatible
-  [255]
+  [10]
   $ hg bisect -c false -s
   abort: --command and --skip are incompatible
-  [255]
+  [10]
   $ hg bisect -e -g
   abort: --extend and --good are incompatible
-  [255]
+  [10]
   $ hg bisect -e -r
   abort: --extend and --reset are incompatible
-  [255]
+  [10]
   $ hg bisect -e -s
   abort: --extend and --skip are incompatible
-  [255]
+  [10]
   $ hg bisect -g -r
   abort: --good and --reset are incompatible
-  [255]
+  [10]
   $ hg bisect -g -s
   abort: --good and --skip are incompatible
-  [255]
+  [10]
   $ hg bisect -r -s
   abort: --reset and --skip are incompatible
-  [255]
+  [10]
--- a/tests/test-bookmarks-pushpull.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bookmarks-pushpull.t	Tue Oct 06 22:36:15 2020 -0700
@@ -386,7 +386,7 @@
   $ hg pull -B anotherbadname ../a
   pulling from ../a
   abort: remote bookmark anotherbadname not found!
-  [255]
+  [10]
 
 divergent bookmarks
 
@@ -1382,10 +1382,10 @@
   [1]
   $ hg push --all-bookmarks -r 1 ../ab2
   abort: cannot specify both --all-bookmarks and --rev
-  [255]
+  [10]
   $ hg push --all-bookmarks -B A ../ab2
   abort: cannot specify both --all-bookmarks and --bookmark
-  [255]
+  [10]
   $ hg push --all-bookmarks ../ab2
   pushing to ../ab2
   searching for changes
--- a/tests/test-bookmarks.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bookmarks.t	Tue Oct 06 22:36:15 2020 -0700
@@ -82,10 +82,10 @@
   [255]
   $ hg bookmarks -l -r0
   abort: cannot specify both --list and --rev
-  [255]
+  [10]
   $ hg bookmarks -l --inactive
   abort: cannot specify both --inactive and --list
-  [255]
+  [10]
 
   $ hg log -T '{bookmarks % "{rev} {bookmark}\n"}'
   0 X
@@ -327,16 +327,16 @@
 
   $ hg bookmark -m Y
   abort: new bookmark name required
-  [255]
+  [10]
   $ hg bookmark -m Y Y2 Y3
   abort: only one new bookmark name allowed
-  [255]
+  [10]
 
 delete without name
 
   $ hg bookmark -d
   abort: bookmark name required
-  [255]
+  [10]
 
 delete nonexistent bookmark
 
@@ -348,7 +348,7 @@
 
   $ hg bookmark -d --inactive Y
   abort: cannot specify both --inactive and --delete
-  [255]
+  [10]
 
 bookmark name with spaces should be stripped
 
@@ -476,15 +476,15 @@
 
   $ hg bookmark -m Y -d Z
   abort: cannot specify both --delete and --rename
-  [255]
+  [10]
 
   $ hg bookmark -r 1 -d Z
   abort: cannot specify both --delete and --rev
-  [255]
+  [10]
 
   $ hg bookmark -r 1 -m Z Y
   abort: cannot specify both --rename and --rev
-  [255]
+  [10]
 
 force bookmark with existing name
 
@@ -522,7 +522,7 @@
 
   $ hg bookmark -r .
   abort: bookmark name required
-  [255]
+  [10]
 
 bookmark name with whitespace only
 
@@ -793,7 +793,7 @@
 
   $ hg -R ../cloned-bookmarks-manual-update update -d 1986
   abort: revision matching date not found
-  [255]
+  [10]
   $ hg -R ../cloned-bookmarks-manual-update update
   updating to active bookmark Y
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-branch-change.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-branch-change.t	Tue Oct 06 22:36:15 2020 -0700
@@ -34,7 +34,7 @@
 
   $ hg branch -r .
   abort: no branch name specified for the revisions
-  [255]
+  [10]
 
 Setting an invalid branch name
 
@@ -52,7 +52,7 @@
 
   $ hg branch -r 2 -r 4 foo
   abort: cannot change branch of non-linear revisions
-  [255]
+  [10]
 
 Change in middle of the stack (linear commits)
 
@@ -74,7 +74,7 @@
 
   $ hg branch -r 'draft() - all()' foo
   abort: empty revision set
-  [255]
+  [10]
 
 Changing branch on linear set of commits from head
 
@@ -123,7 +123,7 @@
 
   $ hg branch -r . default
   abort: a branch of the same name already exists
-  [255]
+  [10]
 
 Changing on a branch head which is not topological head
 
@@ -149,7 +149,7 @@
 
   $ hg branch -r 4 --hidden foobar
   abort: cannot change branch of a obsolete changeset
-  [255]
+  [10]
 
 Make sure bookmark movement is correct
 
@@ -353,7 +353,7 @@
   changed branch on 1 changesets
   $ hg branch -r . stable
   abort: a branch of the same name already exists
-  [255]
+  [10]
 
   $ hg branch -r . stable --force
   changed branch on 1 changesets
--- a/tests/test-branches.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-branches.t	Tue Oct 06 22:36:15 2020 -0700
@@ -75,12 +75,12 @@
   $ hg branch 'b '
   abort: a branch of the same name already exists
   (use 'hg update' to switch to it)
-  [255]
+  [10]
 
   $ hg branch ' b'
   abort: a branch of the same name already exists
   (use 'hg update' to switch to it)
-  [255]
+  [10]
 
 verify update will accept invalid legacy branch names
 
@@ -281,7 +281,7 @@
   $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
   $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
   abort: current revision is already a branch closing head
-  [255]
+  [10]
 
   $ hg log -r tip --debug
   changeset:   12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
@@ -959,7 +959,7 @@
   $ hg ci -m "closing branch" --close-branch
   abort: can only close branch heads
   (use --force-close-branch to close branch from a non-head changeset)
-  [255]
+  [10]
 
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -984,7 +984,7 @@
   $ hg ci -m "branch closed" --close-branch
   abort: can only close branch heads
   (use --force-close-branch to close branch from a non-head changeset)
-  [255]
+  [10]
 
   $ hg ci -m "branch closed" --force-close-branch
   created new head
--- a/tests/test-bundle-r.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bundle-r.t	Tue Oct 06 22:36:15 2020 -0700
@@ -172,10 +172,10 @@
 
   $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3
   abort: --base is incompatible with specifying a destination
-  [255]
+  [10]
   $ hg -R test bundle -a -r tip test-bundle-branch1.hg test-3
   abort: --all is incompatible with specifying a destination
-  [255]
+  [10]
   $ hg -R test bundle -r tip test-bundle-branch1.hg
   abort: repository default-push not found!
   [255]
--- a/tests/test-bundle-type.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bundle-type.t	Tue Oct 06 22:36:15 2020 -0700
@@ -34,12 +34,12 @@
   $ hg bundle -a -t unknown out.hg
   abort: unknown is not a recognized bundle specification
   (see 'hg help bundlespec' for supported values for --type)
-  [255]
+  [10]
 
   $ hg bundle -a -t unknown-v2 out.hg
   abort: unknown compression is not supported
   (see 'hg help bundlespec' for supported values for --type)
-  [255]
+  [10]
 
   $ cd ..
 
@@ -199,7 +199,7 @@
   $ hg -R tzstd bundle -a -t zstd-v1 zstd-v1
   abort: compression engine zstd is not supported on v1 bundles
   (see 'hg help bundlespec' for supported values for --type)
-  [255]
+  [10]
 
 #else
 
@@ -228,5 +228,5 @@
   $ hg bundle -a -t garbage ../bgarbage
   abort: garbage is not a recognized bundle specification
   (see 'hg help bundlespec' for supported values for --type)
-  [255]
+  [10]
   $ cd ..
--- a/tests/test-bundle.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-bundle.t	Tue Oct 06 22:36:15 2020 -0700
@@ -288,7 +288,7 @@
   $ hg -R test bundle -t packed1 packed.hg
   abort: packed bundles cannot be produced by "hg bundle"
   (use 'hg debugcreatestreamclonebundle')
-  [255]
+  [10]
 
 packed1 is produced properly
 
@@ -349,7 +349,7 @@
   $ hg -R packed unbundle packed.hg
   abort: packed bundles cannot be applied with "hg unbundle"
   (use "hg debugapplystreamclonebundle")
-  [255]
+  [10]
 
 packed1 can be consumed from debug command
 
@@ -844,7 +844,7 @@
 
   $ hg bundle -r 'public()' no-output.hg
   abort: no commits to bundle
-  [255]
+  [10]
 
   $ cd ..
 
--- a/tests/test-clone-update-order.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-clone-update-order.t	Tue Oct 06 22:36:15 2020 -0700
@@ -22,7 +22,7 @@
 
   $ hg clone -U -u . .#other ../b -r 0 -r 1 -r 2 -b other
   abort: cannot specify both --noupdate and --updaterev
-  [255]
+  [10]
 
   $ hg clone -U .#other ../b -r 0 -r 1 -r 2 -b other
   adding changesets
--- a/tests/test-clone.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-clone.t	Tue Oct 06 22:36:15 2020 -0700
@@ -254,7 +254,7 @@
 
   $ hg clone --noupdate --updaterev 1 a ua
   abort: cannot specify both --noupdate and --updaterev
-  [255]
+  [10]
 
 
 Testing clone -u:
--- a/tests/test-commandserver.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-commandserver.t	Tue Oct 06 22:36:15 2020 -0700
@@ -714,7 +714,7 @@
   o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
   *** runcommand id
   abort: there is no Mercurial repository here (.hg not found)
-   [255]
+   [10]
 
   >>> from hgclient import check, readchannel, runcommand
   >>> @check
--- a/tests/test-commit-amend.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-commit-amend.t	Tue Oct 06 22:36:15 2020 -0700
@@ -83,7 +83,7 @@
   phases: 2 draft
   $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
   abort: empty commit message
-  [255]
+  [10]
   $ hg summary
   parent: 1:43f1ba15f28a tip
    amend base1
@@ -350,7 +350,7 @@
   $ echo a >> a
   $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
   abort: empty commit message
-  [255]
+  [10]
   $ hg book
      book1                     1:a3b65065808c
    * book2                     1:a3b65065808c
@@ -884,7 +884,7 @@
   $ hg ci -m..
   $ hg ci --amend --close-branch -m 'closing'
   abort: can only close branch heads
-  [255]
+  [10]
 
 This silliness fails:
 
@@ -893,7 +893,7 @@
   $ echo b >> b
   $ hg ci --close-branch -m'open and close'
   abort: branch "silliness" has no heads to close
-  [255]
+  [10]
 
 Test that amend with --secret creates new secret changeset forcibly
 ---------------------------------------------------------------------
--- a/tests/test-commit-interactive.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-commit-interactive.t	Tue Oct 06 22:36:15 2020 -0700
@@ -20,14 +20,14 @@
   [255]
   $ hg commit -i --config ui.interactive=false
   abort: running non-interactively
-  [255]
+  [10]
   $ hg commit -i empty-rw<<EOF
   > n
   > EOF
   diff --git a/empty-rw b/empty-rw
   new file mode 100644
   abort: empty commit message
-  [255]
+  [10]
 
   $ hg tip -p
   changeset:   -1:000000000000
@@ -46,7 +46,7 @@
   diff --git a/empty-rw b/empty-rw
   new file mode 100644
   abort: empty commit message
-  [255]
+  [10]
 
   $ hg tip -p
   changeset:   -1:000000000000
@@ -1350,7 +1350,7 @@
 
   $ hg commit -i -m'will abort'
   abort: cannot partially commit a merge (use "hg commit" instead)
-  [255]
+  [10]
 
   $ hg up -C
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -1494,7 +1494,7 @@
   Hunk #1 FAILED at 0
   1 out of 1 hunks FAILED -- saving rejects to file editedfile.rej
   abort: patch failed to apply
-  [255]
+  [10]
   $ cat editedfile
   This change will not be committed
   This is the second line
@@ -1540,7 +1540,7 @@
   (enter ? for help) [Ynesfdaq?] e
   
   abort: error parsing patch: unhandled transition: range -> range
-  [255]
+  [10]
 
 Exiting editor with status 1, ignores the edit but does not stop the recording
 session
@@ -1600,7 +1600,7 @@
   (enter ? for help) [Ynesfdaq?] e
   
   abort: error parsing patch: unhandled transition: file -> other
-  [255]
+  [10]
 
   $ hg up -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-commit-unresolved.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-commit-unresolved.t	Tue Oct 06 22:36:15 2020 -0700
@@ -58,10 +58,10 @@
 
   $ hg merge --abort e4501
   abort: cannot specify a node with --abort
-  [255]
+  [10]
   $ hg merge --abort --rev e4501
   abort: cannot specify both --abort and --rev
-  [255]
+  [10]
 
 #if abortcommand
 when in dry-run mode
@@ -145,7 +145,7 @@
 
   $ hg merge --preview --abort
   abort: cannot specify both --abort and --preview
-  [255]
+  [10]
 
   $ hg abort
   aborting the merge, updating back to 68352a18a7c4
--- a/tests/test-commit.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-commit.t	Tue Oct 06 22:36:15 2020 -0700
@@ -11,7 +11,7 @@
   $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg commit -m ""
   HGEDITFORM=commit.normal.normal
   abort: empty commit message
-  [255]
+  [10]
   $ hg commit -d '0 0' -m commit-1
   $ echo foo >> foo
   $ hg commit -d '1 4444444' -m commit-3
@@ -370,7 +370,7 @@
   HG: changed changed
   HG: removed removed
   abort: empty commit message
-  [255]
+  [10]
 
 test saving last-message.txt
 
@@ -456,7 +456,7 @@
   HG: subrepo 'sub' is changed
   HG: subrepo 'sub2' is changed
   abort: empty commit message
-  [255]
+  [10]
 
   $ cat >> .hg/hgrc <<EOF
   > [committemplate]
@@ -471,7 +471,7 @@
   HG: Leave message empty to abort commit.
   HG: no bookmark is activated
   abort: empty commit message
-  [255]
+  [10]
 
   $ cat >> .hg/hgrc <<EOF
   > [committemplate]
@@ -484,7 +484,7 @@
   HG: Leave message empty to abort commit.
   HG: no bookmark is activated
   abort: empty commit message
-  [255]
+  [10]
 
   $ cat >> .hg/hgrc <<EOF
   > [committemplate]
@@ -734,7 +734,7 @@
   $ hg add foo2
   $ HGEDITOR="sh $TESTTMP/notouching.sh" hg commit
   abort: commit message unchanged
-  [255]
+  [10]
 
   $ cd ..
 
@@ -762,7 +762,7 @@
   $ hg add foo2
   $ HGEDITOR="sh $TESTTMP/notouching.sh" hg ci
   abort: commit message unchanged
-  [255]
+  [10]
   $ HGEDITOR="sh $TESTTMP/lowercaseline.sh" hg ci
   first line
   HG: this is customized commit template
--- a/tests/test-config.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-config.t	Tue Oct 06 22:36:15 2020 -0700
@@ -331,7 +331,7 @@
 
   $ HGEDITOR=false hg config --edit
   abort: edit failed: false exited with status 1
-  [255]
+  [10]
 
 config affected by environment variables
 
--- a/tests/test-confused-revert.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-confused-revert.t	Tue Oct 06 22:36:15 2020 -0700
@@ -61,7 +61,7 @@
   $ hg revert
   abort: uncommitted merge with no revision specified
   (use 'hg update' or see 'hg help revert')
-  [255]
+  [10]
 
 Revert should be ok now:
 
--- a/tests/test-copy.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-copy.t	Tue Oct 06 22:36:15 2020 -0700
@@ -115,7 +115,7 @@
   $ hg mv foo bar
   foo: not copying - file is not managed
   abort: no files to copy
-  [255]
+  [10]
   $ hg st -A
   ? foo
 respects ui.relative-paths
@@ -124,15 +124,15 @@
   $ hg mv ../foo ../bar
   ../foo: not copying - file is not managed
   abort: no files to copy
-  [255]
+  [10]
   $ hg mv ../foo ../bar --config ui.relative-paths=yes
   ../foo: not copying - file is not managed
   abort: no files to copy
-  [255]
+  [10]
   $ hg mv ../foo ../bar --config ui.relative-paths=no
   foo: not copying - file is not managed
   abort: no files to copy
-  [255]
+  [10]
   $ cd ..
   $ rmdir dir
   $ hg add foo
--- a/tests/test-dirstate-backup.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-dirstate-backup.t	Tue Oct 06 22:36:15 2020 -0700
@@ -9,7 +9,7 @@
   > EOF
   applying patch from stdin
   abort: stdin: no diffs found
-  [255]
+  [10]
 
 No dirstate backups are left behind
 
--- a/tests/test-export.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-export.t	Tue Oct 06 22:36:15 2020 -0700
@@ -373,7 +373,7 @@
   [255]
   $ hg export "not all()"
   abort: export requires at least one changeset
-  [255]
+  [10]
 
 Check for color output
   $ cat <<EOF >> $HGRCPATH
--- a/tests/test-fix-topology.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-fix-topology.t	Tue Oct 06 22:36:15 2020 -0700
@@ -411,7 +411,7 @@
   $ cd fixall
   $ hg fix --all --working-dir
   abort: cannot specify both --working-dir and --all
-  [255]
+  [10]
 
 #if obsstore-on
   $ printf "one\n" > foo.whole
--- a/tests/test-graft-interrupted.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-graft-interrupted.t	Tue Oct 06 22:36:15 2020 -0700
@@ -250,17 +250,17 @@
 
   $ hg graft --stop --continue
   abort: cannot specify both --stop and --continue
-  [255]
+  [10]
 
   $ hg graft --stop -U
   abort: cannot specify both --stop and --user
-  [255]
+  [10]
   $ hg graft --stop --rev 4
   abort: cannot specify both --stop and --rev
-  [255]
+  [10]
   $ hg graft --stop --log
   abort: cannot specify both --stop and --log
-  [255]
+  [10]
 
   $ hg graft --stop
   stopped the interrupted graft
@@ -356,19 +356,19 @@
 
   $ hg graft --continue --abort
   abort: cannot specify both --abort and --continue
-  [255]
+  [10]
 
   $ hg graft --abort --stop
   abort: cannot specify both --abort and --stop
-  [255]
+  [10]
 
   $ hg graft --abort --currentuser
   abort: cannot specify both --abort and --user
-  [255]
+  [10]
 
   $ hg graft --abort --edit
   abort: cannot specify both --abort and --edit
-  [255]
+  [10]
 
 #if abortcommand
 when in dry-run mode
@@ -554,15 +554,15 @@
 
   $ hg graft 1 --no-commit -e
   abort: cannot specify both --no-commit and --edit
-  [255]
+  [10]
 
   $ hg graft 1 --no-commit --log
   abort: cannot specify both --no-commit and --log
-  [255]
+  [10]
 
   $ hg graft 1 --no-commit -D
   abort: cannot specify both --no-commit and --currentdate
-  [255]
+  [10]
 
 Test --no-commit is working:
   $ hg graft 1 --no-commit
--- a/tests/test-graft.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-graft.t	Tue Oct 06 22:36:15 2020 -0700
@@ -92,7 +92,7 @@
 
   $ hg graft
   abort: no revisions specified
-  [255]
+  [10]
 
 Can't graft ancestor:
 
@@ -119,10 +119,10 @@
   $ hg up -q 0
   $ hg graft -U --user foo 2
   abort: cannot specify both --user and --currentuser
-  [255]
+  [10]
   $ hg graft -D --date '0 0' 2
   abort: cannot specify both --date and --currentdate
-  [255]
+  [10]
 
 Can't graft with dirty wd:
 
@@ -337,11 +337,11 @@
 
   $ hg graft -c 6
   abort: can't specify --continue and revisions
-  [255]
+  [10]
 
   $ hg graft -c -r 6
   abort: can't specify --continue and revisions
-  [255]
+  [10]
 
 Continue for real, clobber usernames
 
--- a/tests/test-identify.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-identify.t	Tue Oct 06 22:36:15 2020 -0700
@@ -6,7 +6,7 @@
 
   $ hg id
   abort: there is no Mercurial repository here (.hg not found)
-  [255]
+  [10]
 
 #endif
 
@@ -115,19 +115,19 @@
 
   $ hg id -n http://localhost:$HGPORT1/
   abort: can't query remote revision number, branch, or tags
-  [255]
+  [10]
 
 remote with tags?
 
   $ hg id -t http://localhost:$HGPORT1/
   abort: can't query remote revision number, branch, or tags
-  [255]
+  [10]
 
 remote with branch?
 
   $ hg id -b http://localhost:$HGPORT1/
   abort: can't query remote revision number, branch, or tags
-  [255]
+  [10]
 
 test bookmark support
 
--- a/tests/test-import-bypass.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-import-bypass.t	Tue Oct 06 22:36:15 2020 -0700
@@ -27,7 +27,7 @@
 
   $ hg import --bypass --exact --edit ../test.diff
   abort: cannot specify both --exact and --edit
-  [255]
+  [10]
   $ hg import --bypass --exact ../test.diff
   applying ../test.diff
   $ shortlog
@@ -189,13 +189,13 @@
 
   $ hg import --bypass --no-commit ../test.diff
   abort: cannot specify both --no-commit and --bypass
-  [255]
+  [10]
   $ hg import --bypass --similarity 50 ../test.diff
   abort: cannot use --similarity with --bypass
-  [255]
+  [10]
   $ hg import --exact --prefix dir/ ../test.diff
   abort: cannot specify both --exact and --prefix
-  [255]
+  [10]
 
 Test commit editor
 (this also tests that editor is invoked, if the patch doesn't contain
@@ -221,7 +221,7 @@
   HG: branch 'default'
   HG: changed a
   abort: empty commit message
-  [255]
+  [10]
 
 Test patch.eol is handled
 (this also tests that editor is not invoked for '--bypass', if the
--- a/tests/test-import.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-import.t	Tue Oct 06 22:36:15 2020 -0700
@@ -14,7 +14,7 @@
 
   $ hg --cwd a import
   abort: need at least one patch to import
-  [255]
+  [10]
 
 generate patches for the test
 
@@ -127,7 +127,7 @@
   HG: branch 'default'
   HG: changed a
   abort: empty commit message
-  [255]
+  [10]
 
 Test avoiding editor invocation at applying the patch with --exact,
 even if commit message is empty
@@ -374,7 +374,7 @@
   $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
   applying patch from stdin
   abort: empty commit message
-  [255]
+  [10]
   $ rm -r b
 
 
@@ -445,7 +445,7 @@
   $ hg clone -r0 a b -q
   $ hg --cwd b import --no-commit --secret ../exported-tip.patch
   abort: cannot specify both --no-commit and --secret
-  [255]
+  [10]
   $ hg --cwd b import --secret ../exported-tip.patch
   applying ../exported-tip.patch
   $ hg --cwd b diff -c . --nodates
@@ -1172,7 +1172,7 @@
   transaction abort!
   rollback completed
   abort: empty.patch: no diffs found
-  [255]
+  [10]
   $ hg tip --template '{rev}  {desc|firstline}\n'
   0  commit
   $ hg -q status
--- a/tests/test-keyword.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-keyword.t	Tue Oct 06 22:36:15 2020 -0700
@@ -167,7 +167,7 @@
 
   $ hg --debug commit
   abort: empty commit message
-  [255]
+  [10]
   $ hg status
   A a
   A b
@@ -816,7 +816,7 @@
 
   $ hg commit
   abort: empty commit message
-  [255]
+  [10]
   $ hg status
   M a
   ? c
--- a/tests/test-largefiles.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-largefiles.t	Tue Oct 06 22:36:15 2020 -0700
@@ -1077,7 +1077,7 @@
 
   $ hg clone -U -u 0 a a-clone-failure
   abort: cannot specify both --noupdate and --updaterev
-  [255]
+  [10]
 
   $ hg clone --all-largefiles a ssh://localhost/a
   abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
--- a/tests/test-log-linerange.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-log-linerange.t	Tue Oct 06 22:36:15 2020 -0700
@@ -363,7 +363,7 @@
 
   $ hg log -f -L foo,5:7 -p bar
   abort: FILE arguments are not compatible with --line-range option
-  [255]
+  [10]
 
 Option --rev acts as a restriction.
 
@@ -1135,7 +1135,7 @@
 
   $ hg log -L foo,5:7
   abort: --line-range requires --follow
-  [255]
+  [10]
 
 Non-exact pattern kinds are not allowed.
 
--- a/tests/test-manifest.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-manifest.t	Tue Oct 06 22:36:15 2020 -0700
@@ -92,7 +92,7 @@
 
   $ hg manifest -r tip tip
   abort: please specify just one revision
-  [255]
+  [10]
 
 Testing the manifest full text cache utility
 --------------------------------------------
--- a/tests/test-merge-default.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-merge-default.t	Tue Oct 06 22:36:15 2020 -0700
@@ -69,7 +69,7 @@
 
   $ hg merge --config commands.merge.require-rev=True
   abort: configuration requires specifying revision to merge with
-  [255]
+  [10]
 
 Should succeed - 2 heads:
 
@@ -101,7 +101,7 @@
 
   $ hg merge --config commands.merge.require-rev=True
   abort: configuration requires specifying revision to merge with
-  [255]
+  [10]
 
 Should fail because at tip:
 
--- a/tests/test-merge2.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-merge2.t	Tue Oct 06 22:36:15 2020 -0700
@@ -52,6 +52,6 @@
 
   $ hg merge 'wdir()'
   abort: merging with the working copy has no effect
-  [255]
+  [10]
 
   $ cd ..
--- a/tests/test-merge9.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-merge9.t	Tue Oct 06 22:36:15 2020 -0700
@@ -78,7 +78,7 @@
   $ hg resolve
   abort: no files or directories specified
   (use --all to re-merge all unresolved files)
-  [255]
+  [10]
 
 resolve all
   $ hg resolve -a
--- a/tests/test-missing-capability.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-missing-capability.t	Tue Oct 06 22:36:15 2020 -0700
@@ -43,4 +43,4 @@
   $ hg pull ssh://user@dummy/repo1 -r tip -B a
   pulling from ssh://user@dummy/repo1
   abort: remote bookmark a not found!
-  [255]
+  [10]
--- a/tests/test-mq-qrefresh-interactive.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-mq-qrefresh-interactive.t	Tue Oct 06 22:36:15 2020 -0700
@@ -125,10 +125,10 @@
   $ hg commit -m aaa
   $ hg qrecord --config ui.interactive=false patch
   abort: running non-interactively, use qnew instead
-  [255]
+  [10]
   $ hg qnew -i --config ui.interactive=false patch
   abort: running non-interactively
-  [255]
+  [10]
   $ hg qnew -d '0 0' patch
 
 Changing files
@@ -179,7 +179,7 @@
 
   $ hg qrefresh -i --config ui.interactive=false
   abort: running non-interactively
-  [255]
+  [10]
   $ hg qrefresh -i -d '0 0' <<EOF
   > y
   > y
--- a/tests/test-newbranch.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-newbranch.t	Tue Oct 06 22:36:15 2020 -0700
@@ -32,7 +32,7 @@
   $ hg branch default
   abort: a branch of the same name already exists
   (use 'hg update' to switch to it)
-  [255]
+  [10]
 
   $ hg branch -f default
   marked working directory as branch default
@@ -61,7 +61,7 @@
   $ hg branch bar
   abort: a branch of the same name already exists
   (use 'hg update' to switch to it)
-  [255]
+  [10]
 
   $ hg branch -f bar
   marked working directory as branch bar
@@ -84,7 +84,7 @@
   $ hg branch bar
   abort: a branch of the same name already exists
   (use 'hg update' to switch to it)
-  [255]
+  [10]
 
  set (other) parent branch as branch name
 
--- a/tests/test-parents.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-parents.t	Tue Oct 06 22:36:15 2020 -0700
@@ -54,7 +54,7 @@
 
   $ hg parents -r 3 c
   abort: 'c' not found in manifest!
-  [255]
+  [10]
 
   $ hg parents -r 2
   changeset:   1:d786049f033a
@@ -95,7 +95,7 @@
 
   $ hg parents -r 2 glob:a
   abort: can only specify an explicit filename
-  [255]
+  [10]
 
 
 merge working dir with 2 parents, hg parents c
--- a/tests/test-push-warn.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-push-warn.t	Tue Oct 06 22:36:15 2020 -0700
@@ -25,7 +25,7 @@
   pushing to ../a
   abort: specified revisions evaluate to an empty set
   (use different revision arguments)
-  [255]
+  [10]
 
   $ hg push ../a
   pushing to ../a
--- a/tests/test-push.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-push.t	Tue Oct 06 22:36:15 2020 -0700
@@ -365,7 +365,7 @@
   pushing to $TESTTMP/test-require-revs-dest
   abort: no revisions specified to push
   (did you mean "hg push -r ."?)
-  [255]
+  [10]
   $ hg push -r 0
   pushing to $TESTTMP/test-require-revs-dest
   searching for changes
@@ -394,7 +394,7 @@
   pushing to $TESTTMP/test-require-revs-dest
   abort: no revisions specified to push
   (did you mean "hg push -r ."?)
-  [255]
+  [10]
   $ hg push --config paths.default:pushrev=0
   pushing to $TESTTMP/test-require-revs-dest
   searching for changes
--- a/tests/test-rebase-inmemory.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rebase-inmemory.t	Tue Oct 06 22:36:15 2020 -0700
@@ -333,10 +333,10 @@
 Make sure it throws error while passing --continue or --abort with --dry-run
   $ hg rebase -s 2 -d 6 -n --continue
   abort: cannot specify both --continue and --dry-run
-  [255]
+  [10]
   $ hg rebase -s 2 -d 6 -n --abort
   abort: cannot specify both --abort and --dry-run
-  [255]
+  [10]
 
 Check dryrun gives correct results when there is no conflict in rebasing
   $ hg rebase -s 2 -d 6 -n
@@ -539,13 +539,13 @@
 Check it gives error when both --dryrun and --confirm is used:
   $ hg rebase -s 2 -d . --confirm --dry-run
   abort: cannot specify both --confirm and --dry-run
-  [255]
+  [10]
   $ hg rebase -s 2 -d . --confirm --abort
   abort: cannot specify both --abort and --confirm
-  [255]
+  [10]
   $ hg rebase -s 2 -d . --confirm --continue
   abort: cannot specify both --continue and --confirm
-  [255]
+  [10]
 
 Test --confirm option when there are no conflicts:
   $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
--- a/tests/test-rebase-obsolete.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rebase-obsolete.t	Tue Oct 06 22:36:15 2020 -0700
@@ -488,7 +488,7 @@
   $ cd stabilize
   $ hg rebase --auto-orphans '0::' -d 10
   abort: cannot specify both --auto-orphans and --dest
-  [255]
+  [10]
   $ hg rebase --auto-orphans '0::'
   rebasing 9:cf44d2f5a9f4 "D"
   $ hg log -G
@@ -2053,7 +2053,7 @@
   [240]
   $ hg rebase --stop --dry-run
   abort: cannot specify both --stop and --dry-run
-  [255]
+  [10]
 
   $ hg rebase -s 3 -d 5
   abort: rebase in progress
@@ -2061,7 +2061,7 @@
   [255]
   $ hg rebase --stop --continue
   abort: cannot specify both --stop and --continue
-  [255]
+  [10]
 
 Test --stop moves bookmarks of original revisions to new rebased nodes:
 ======================================================================
--- a/tests/test-rebase-parameters.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rebase-parameters.t	Tue Oct 06 22:36:15 2020 -0700
@@ -62,7 +62,7 @@
 
   $ hg rebase --continue --abort
   abort: cannot specify both --abort and --continue
-  [255]
+  [10]
 
   $ hg rebase --continue --collapse
   abort: cannot use collapse with continue or abort
@@ -70,18 +70,18 @@
 
   $ hg rebase --continue --dest 4
   abort: cannot specify both --continue and --dest
-  [255]
+  [10]
 
   $ hg rebase --base 5 --source 4
   abort: cannot specify both --source and --base
-  [255]
+  [10]
 
   $ hg rebase --rev 5 --source 4
   abort: cannot specify both --rev and --source
-  [255]
+  [10]
   $ hg rebase --base 5 --rev 4
   abort: cannot specify both --rev and --base
-  [255]
+  [10]
 
   $ hg rebase --base 6
   abort: branch 'default' has 3 heads - please rebase to an explicit rev
--- a/tests/test-record.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-record.t	Tue Oct 06 22:36:15 2020 -0700
@@ -77,7 +77,7 @@
   diff --git a/empty-rw b/empty-rw
   new file mode 100644
   abort: empty commit message
-  [255]
+  [10]
 
   $ hg tip -p
   changeset:   -1:000000000000
--- a/tests/test-remotefilelog-prefetch.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-remotefilelog-prefetch.t	Tue Oct 06 22:36:15 2020 -0700
@@ -232,7 +232,7 @@
   $ hg mv z2 z3
   z2: not copying - file is not managed
   abort: no files to copy
-  [255]
+  [10]
   $ find $CACHEDIR -type f | sort
 .. The following output line about files fetches is globed because it is
 .. flaky, the core the test is checked when checking the cache dir, so
--- a/tests/test-rename-after-merge.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rename-after-merge.t	Tue Oct 06 22:36:15 2020 -0700
@@ -124,10 +124,10 @@
 
   $ hg copy --forget --at-rev . b2
   abort: cannot mark/unmark copy in merge commit
-  [255]
+  [10]
 
   $ hg copy --after --at-rev . b1 b2
   abort: cannot mark/unmark copy in merge commit
-  [255]
+  [10]
 
   $ cd ..
--- a/tests/test-rename-rev.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rename-rev.t	Tue Oct 06 22:36:15 2020 -0700
@@ -23,16 +23,16 @@
 # Errors out without --after for now
   $ hg cp --at-rev . d1/b d1/d
   abort: --at-rev requires --after
-  [255]
+  [10]
 # Errors out with non-existent source
   $ hg cp -A --at-rev . d1/non-existent d1/d
   d1/non-existent: no such file in rev 55d1fd85ef0a
   abort: no files to copy
-  [255]
+  [10]
 # Errors out with non-existent destination
   $ hg cp -A --at-rev . d1/b d1/non-existent
   abort: d1/non-existent: copy destination does not exist in 8a9d70fa20c9
-  [255]
+  [10]
 # Successful invocation
   $ hg cp -A --at-rev . d1/b d1/d
   saved backup bundle to $TESTTMP/.hg/strip-backup/8a9d70fa20c9-973ae357-copy.hg
@@ -103,5 +103,5 @@
   created new head
   $ hg cp -A --at-rev . d1 d3
   abort: d3: --at-rev does not support a directory as destination
-  [255]
+  [10]
 
--- a/tests/test-rename.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-rename.t	Tue Oct 06 22:36:15 2020 -0700
@@ -295,7 +295,7 @@
 
   $ hg rename d1/a dx/
   abort: destination dx/ is not a directory
-  [255]
+  [10]
   $ hg status -C
   $ hg update -C
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -304,7 +304,7 @@
 
   $ hg rename 'glob:d1/**' dx
   abort: with multiple sources, destination must be an existing directory
-  [255]
+  [10]
 
 move every file under d1 to d2/d21
 
--- a/tests/test-resolve.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-resolve.t	Tue Oct 06 22:36:15 2020 -0700
@@ -191,7 +191,7 @@
   $ hg resolve
   abort: no files or directories specified
   (use --all to re-merge all unresolved files)
-  [255]
+  [10]
 
 resolve --all should re-merge all unresolved files
   $ hg resolve --all
@@ -406,7 +406,7 @@
   R file2
   $ hg resolve --mark --re-merge
   abort: too many actions specified
-  [255]
+  [10]
   $ hg resolve --re-merge --all
   merging file1
   warning: conflicts while merging file1! (edit, then use 'hg resolve --mark')
@@ -416,7 +416,7 @@
   $ hg resolve --config commands.resolve.explicit-re-merge=1 --all
   abort: no action specified
   (use --mark, --unmark, --list or --re-merge)
-  [255]
+  [10]
   $ hg resolve --config commands.resolve.explicit-re-merge=1 --re-merge --all
   merging file1
   warning: conflicts while merging file1! (edit, then use 'hg resolve --mark')
@@ -489,7 +489,7 @@
   $ hg resolve
   abort: no files or directories specified
   (use --all to re-merge all unresolved files)
-  [255]
+  [10]
   $ hg resolve --all << EOF
   > n
   > EOF
--- a/tests/test-revert.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-revert.t	Tue Oct 06 22:36:15 2020 -0700
@@ -11,7 +11,7 @@
   $ hg revert
   abort: no files or directories specified
   (use --all to revert all files)
-  [255]
+  [10]
   $ hg revert --all
 
 Introduce some changes and revert them
@@ -250,7 +250,7 @@
   $ hg revert -rtip
   abort: no files or directories specified
   (use --all to revert all files, or 'hg update 1' to update)
-  [255]
+  [10]
 
 call `hg revert` with -I
 ---------------------------
--- a/tests/test-share-safe.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-share-safe.t	Tue Oct 06 22:36:15 2020 -0700
@@ -36,7 +36,7 @@
 
   $ HGEDITOR=cat hg config --shared
   abort: repository is not shared; can't use --shared
-  [255]
+  [10]
   $ cd ..
 
 Create a shared repo and check the requirements are shared and read correctly
--- a/tests/test-shelve.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-shelve.t	Tue Oct 06 22:36:15 2020 -0700
@@ -209,7 +209,7 @@
 
   $ hg shelve --list --addremove
   abort: options '--list' and '--addremove' may not be used together
-  [255]
+  [10]
 
 delete our older shelved change
 
@@ -648,13 +648,13 @@
 
   $ hg shelve --cleanup --delete
   abort: options '--cleanup' and '--delete' may not be used together
-  [255]
+  [10]
   $ hg shelve --cleanup --patch
   abort: options '--cleanup' and '--patch' may not be used together
-  [255]
+  [10]
   $ hg shelve --cleanup --message MESSAGE
   abort: options '--cleanup' and '--message' may not be used together
-  [255]
+  [10]
 
 test bookmarks
 
@@ -737,10 +737,10 @@
 
   $ hg shelve --delete --stat
   abort: options '--delete' and '--stat' may not be used together
-  [255]
+  [10]
   $ hg shelve --delete --name NAME
   abort: options '--delete' and '--name' may not be used together
-  [255]
+  [10]
 
 Test interactive shelve
   $ cat <<EOF >> $HGRCPATH
@@ -767,7 +767,7 @@
   a
   $ hg shelve --interactive --config ui.interactive=false
   abort: running non-interactively
-  [255]
+  [10]
   $ hg shelve --interactive << EOF
   > y
   > y
@@ -954,13 +954,13 @@
   unshelving change 'default'
   $ hg shelve --keep --list
   abort: options '--list' and '--keep' may not be used together
-  [255]
+  [10]
   $ hg shelve --keep --patch
   abort: options '--patch' and '--keep' may not be used together
-  [255]
+  [10]
   $ hg shelve --keep --delete
   abort: options '--delete' and '--keep' may not be used together
-  [255]
+  [10]
   $ hg shelve --keep
   shelved as default
   $ hg diff
--- a/tests/test-simple-update.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-simple-update.t	Tue Oct 06 22:36:15 2020 -0700
@@ -55,7 +55,7 @@
 
   $ hg upd -d foo 0
   abort: you can't specify a revision and a date
-  [255]
+  [10]
 
 update by date
 
@@ -71,7 +71,7 @@
 
   $ hg update -d '>1970-01-01 00:00:02 +0000'
   abort: revision matching date not found
-  [255]
+  [10]
   $ hg update -d '>1970-01-01 00:00:01 +0000'
   found revision 1 from Thu Jan 01 00:00:01 1970 +0000
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-status-terse.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-status-terse.t	Tue Oct 06 22:36:15 2020 -0700
@@ -24,7 +24,7 @@
   ? x/bb.o
   $ hg status --terse f
   abort: 'f' not recognized
-  [255]
+  [10]
 
 Add a .hgignore so that we can also have ignored files
 
@@ -224,7 +224,7 @@
 
   $ hg status --terse marduic --rev 0 --rev 1
   abort: cannot use --terse with --rev
-  [255]
+  [10]
 
 Config item to set the default terseness
   $ cat <<EOF >> $HGRCPATH
--- a/tests/test-subrepo-recursion.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-subrepo-recursion.t	Tue Oct 06 22:36:15 2020 -0700
@@ -682,7 +682,7 @@
 
   $ hg incoming -S --bundle incoming.hg
   abort: cannot specify both --subrepos and --bundle
-  [255]
+  [10]
 
 Test missing subrepo:
 
--- a/tests/test-tag.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-tag.t	Tue Oct 06 22:36:15 2020 -0700
@@ -30,7 +30,7 @@
 
   $ hg tag ' '
   abort: tag names cannot consist entirely of whitespace
-  [255]
+  [10]
 
 (this tests also that editor is not invoked, if '--edit' is not
 specified)
@@ -61,7 +61,7 @@
   $ hg revert .hgtags
   $ hg tag -r 0 x y z y y z
   abort: tag names must be unique
-  [255]
+  [10]
   $ hg tag tap nada dot tip
   abort: the name 'tip' is reserved
   [255]
@@ -73,17 +73,17 @@
   [255]
   $ hg tag "bleah"
   abort: tag 'bleah' already exists (use -f to force)
-  [255]
+  [10]
   $ hg tag "blecch" "bleah"
   abort: tag 'bleah' already exists (use -f to force)
-  [255]
+  [10]
 
   $ hg tag --remove "blecch"
   abort: tag 'blecch' does not exist
-  [255]
+  [10]
   $ hg tag --remove "bleah" "blecch" "blough"
   abort: tag 'blecch' does not exist
-  [255]
+  [10]
 
   $ hg tag -r 0 "bleah0"
   hook: tag changes detected
@@ -105,13 +105,13 @@
 
   $ hg tag "bleah "
   abort: tag 'bleah' already exists (use -f to force)
-  [255]
+  [10]
   $ hg tag " bleah"
   abort: tag 'bleah' already exists (use -f to force)
-  [255]
+  [10]
   $ hg tag " bleah"
   abort: tag 'bleah' already exists (use -f to force)
-  [255]
+  [10]
   $ hg tag -r 0 "  bleahbleah  "
   hook: tag changes detected
   hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
@@ -144,7 +144,7 @@
   $ hg tag -l localblah
   $ hg tag "foobar"
   abort: working directory is not at a branch head (use -f to force)
-  [255]
+  [10]
   $ hg tag -f "foobar"
   hook: tag changes detected
   hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
@@ -401,16 +401,16 @@
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg tag nullrev
   abort: working directory is not at a branch head (use -f to force)
-  [255]
+  [10]
 
   $ hg init empty
   $ hg tag -R empty nullrev
   abort: cannot tag null revision
-  [255]
+  [10]
 
   $ hg tag -R empty -r 00000000000 -f nulltag
   abort: cannot tag null revision
-  [255]
+  [10]
 
 issue5539: pruned tags do not appear in .hgtags
 
--- a/tests/test-tags.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-tags.t	Tue Oct 06 22:36:15 2020 -0700
@@ -505,7 +505,7 @@
 
   $ hg tag --remove foobar
   abort: tag 'foobar' does not exist
-  [255]
+  [10]
   $ hg tip
   changeset:   5:5f6e8655b1c7
   tag:         tip
@@ -555,7 +555,7 @@
 
   $ hg tag -r 3 bar
   abort: tag 'bar' already exists (use -f to force)
-  [255]
+  [10]
   $ hg tags
   tip                                6:735c3ca72986
   bar                                0:bbd179dfa0a7
@@ -622,12 +622,12 @@
   $ hg tag -r 0 -l localtag
   $ hg tag --remove localtag
   abort: tag 'localtag' is not a global tag
-  [255]
+  [10]
   $ 
   $ hg tag -r 0 globaltag
   $ hg tag --remove -l globaltag
   abort: tag 'globaltag' is not a local tag
-  [255]
+  [10]
   $ hg tags -v
   tip                                1:a0b6fe111088
   localtag                           0:bbd179dfa0a7 local
@@ -824,7 +824,7 @@
   
   $ hg tag --remove a
   abort: tag 'a' is already removed
-  [255]
+  [10]
   $ hg log
   changeset:   2:e7feacc7ec9e
   tag:         tip
--- a/tests/test-transplant.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-transplant.t	Tue Oct 06 22:36:15 2020 -0700
@@ -19,10 +19,10 @@
   [255]
   $ hg transplant --continue --all
   abort: cannot specify both --continue and --all
-  [255]
+  [10]
   $ hg transplant --stop --all
   abort: cannot specify both --stop and --all
-  [255]
+  [10]
   $ hg transplant --all tip
   abort: --all requires a branch revision
   [255]
--- a/tests/test-uncommit.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-uncommit.t	Tue Oct 06 22:36:15 2020 -0700
@@ -556,10 +556,10 @@
   $ hg rollback -q --config ui.rollback=True
   $ hg uncommit -U --user 'user'
   abort: cannot specify both --user and --currentuser
-  [255]
+  [10]
   $ hg uncommit -D --date today
   abort: cannot specify both --date and --currentdate
-  [255]
+  [10]
 
 `uncommit <dir>` and `cd <dir> && uncommit .` behave the same...
 
--- a/tests/test-update-dest.t	Wed Oct 21 19:00:16 2020 -0700
+++ b/tests/test-update-dest.t	Tue Oct 06 22:36:15 2020 -0700
@@ -11,7 +11,7 @@
   $ hg up
   abort: you must specify a destination
   (for example: hg update ".::")
-  [255]
+  [10]
   $ hg up .
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ HGPLAIN=1 hg up
@@ -32,7 +32,7 @@
   $ hg pull --update
   abort: update destination required by configuration
   (use hg pull followed by hg update DEST)
-  [255]
+  [10]
 
   $ cd ..