[Request] [++-- ] D9167: errors: introduce UserError and use it from commands and cmdutil
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Wed Oct 7 06:12:46 UTC 2020
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
This patch introduces a `UserError` 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 a user 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).
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D9167
AFFECTED FILES
hgext/largefiles/overrides.py
mercurial/cmdutil.py
mercurial/commands.py
mercurial/dispatch.py
mercurial/error.py
mercurial/scmutil.py
mercurial/subrepo.py
CHANGE DETAILS
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -81,7 +81,7 @@
except SubrepoAbort as ex:
# This exception has already been handled
raise ex
- except error.Abort as ex:
+ except (error.Abort, error.UserError) as ex:
subrepo = subrelpath(self)
errormsg = (
stringutil.forcebytestr(ex)
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -219,6 +219,10 @@
ui.error(_(b"abort: %s\n") % inst)
if inst.hint:
ui.error(_(b"(%s)\n") % inst.hint)
+ except error.UserError as inst:
+ ui.error(_(b"abort: %s\n") % inst.message)
+ if inst.hint:
+ ui.error(_(b"(%s)\n") % inst.hint)
except ImportError as inst:
ui.error(_(b"abort: %s!\n") % stringutil.forcebytestr(inst))
m = stringutil.forcebytestr(inst).split()[-1]
diff --git a/mercurial/error.py b/mercurial/error.py
--- a/mercurial/error.py
+++ b/mercurial/error.py
@@ -38,6 +38,19 @@
super(Hint, self).__init__(*args, **kw)
+class UserError(Hint, Exception):
+ """Indicates that the user made an error.
+
+ Examples: Invalid command, invalid flags, invalid revision.
+ """
+
+ def __init__(self, message, hint=None):
+ self.message = message
+ super(UserError, self).__init__(hint=hint)
+
+ __bytes__ = _tobytes
+
+
class StorageError(Hint, Exception):
"""Raised when an error occurs in a storage layer.
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -288,7 +288,12 @@
if req.fmsg:
req.ui.fmsg = req.fmsg
except error.Abort as inst:
- ferr.write(_(b"abort: %s\n") % inst)
+ ferr.write(_(b"abort from dispatch: %s\n") % inst)
+ if inst.hint:
+ ferr.write(_(b"(%s)\n") % inst.hint)
+ return -1
+ except error.UserError as inst:
+ ferr.write(_(b"abort: %s\n") % inst.message)
if inst.hint:
ferr.write(_(b"(%s)\n") % inst.hint)
return -1
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2034,11 +2034,13 @@
extra[b'close'] = b'1'
if repo[b'.'].closesbranch():
- raise error.Abort(
+ raise error.UserError(
_(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.UserError(
+ _(b'branch "%s" has no heads to close') % branch
+ )
elif (
branch == repo[b'.'].branch()
and repo[b'.'].node() not in bheads
@@ -2048,17 +2050,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.UserError(_(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.UserError(_(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.UserError(
+ _(b'cannot amend with ui.commitsubrepos enabled')
+ )
old = repo[b'.']
rewriteutil.precheck(repo, [old.rev()], b'amend')
@@ -2196,17 +2200,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.UserError(
+ _(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.UserError(
_(b"repository is not shared; can't use --shared")
)
if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
- raise error.Abort(
+ raise error.UserError(
_(
b"share safe feature not unabled; "
b"unable to edit shared source repository config"
@@ -2235,7 +2241,7 @@
editor = ui.geteditor()
ui.system(
b"%s \"%s\"" % (editor, f),
- onerr=error.Abort,
+ onerr=error.UserError,
errprefix=_(b"edit failed"),
blockedtag=b'config_edit',
)
@@ -2643,7 +2649,7 @@
if bookmark:
if bookmark not in repo._bookmarks:
- raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
+ raise error.UserError(_(b"bookmark '%s' not found") % bookmark)
revs = scmutil.bookmarkrevs(repo, bookmark)
else:
@@ -2654,7 +2660,7 @@
revs = scmutil.revrange(repo, changesets)
if not revs:
- raise error.Abort(_(b"export requires at least one changeset"))
+ raise error.UserError(_(b"export requires at least one changeset"))
if len(revs) > 1:
ui.note(_(b'exporting patches:\n'))
else:
@@ -2819,7 +2825,7 @@
opts = pycompat.byteskwargs(opts)
if not pats:
- raise error.Abort(_(b'no files specified'))
+ raise error.UserError(_(b'no files specified'))
m = scmutil.match(repo[None], pats, opts)
dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
@@ -3046,7 +3052,7 @@
elif opts.get(b'continue'):
cont = True
if revs:
- raise error.Abort(_(b"can't specify --continue and revisions"))
+ raise error.UserError(_(b"can't specify --continue and revisions"))
# read in unfinished revisions
if graftstate.exists():
statedata = cmdutil.readgraftstate(repo, graftstate)
@@ -3066,7 +3072,7 @@
cmdutil.wrongtooltocontinue(repo, _(b'graft'))
else:
if not revs:
- raise error.Abort(_(b'no revisions specified'))
+ raise error.UserError(_(b'no revisions specified'))
cmdutil.checkunfinished(repo)
cmdutil.bailifchanged(repo)
revs = scmutil.revrange(repo, revs)
@@ -3084,7 +3090,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.UserError(_(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
@@ -3372,7 +3378,9 @@
opts = pycompat.byteskwargs(opts)
diff = opts.get(b'all') or opts.get(b'diff')
if diff and opts.get(b'all_files'):
- raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
+ raise error.UserError(
+ _(b'--diff and --all-files are mutually exclusive')
+ )
if opts.get(b'all_files') is None and not diff:
opts[b'all_files'] = True
plaingrep = (
@@ -3916,7 +3924,7 @@
opts = pycompat.byteskwargs(opts)
if not repo and not source:
- raise error.Abort(
+ raise error.UserError(
_(b"there is no Mercurial repository here (.hg not found)")
)
@@ -3935,7 +3943,7 @@
if not repo:
if num or branch or tags:
- raise error.Abort(
+ raise error.UserError(
_(b"can't query remote revision number, branch, or tags")
)
if not rev and revs:
@@ -4203,7 +4211,7 @@
opts = pycompat.byteskwargs(opts)
if not patch1:
- raise error.Abort(_(b'need at least one patch to import'))
+ raise error.UserError(_(b'need at least one patch to import'))
patches = (patch1,) + patches
@@ -4214,22 +4222,22 @@
exact = opts.get(b'exact')
update = not opts.get(b'bypass')
if not update and opts.get(b'no_commit'):
- raise error.Abort(_(b'cannot use --no-commit with --bypass'))
+ raise error.UserError(_(b'cannot use --no-commit with --bypass'))
if opts.get(b'secret') and opts.get(b'no_commit'):
- raise error.Abort(_(b'cannot use --no-commit with --secret'))
+ raise error.UserError(_(b'cannot use --no-commit with --secret'))
try:
sim = float(opts.get(b'similarity') or 0)
except ValueError:
- raise error.Abort(_(b'similarity must be a number'))
+ raise error.UserError(_(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.UserError(_(b'similarity must be between 0 and 100'))
if sim and not update:
- raise error.Abort(_(b'cannot use --similarity with --bypass'))
+ raise error.UserError(_(b'cannot use --similarity with --bypass'))
if exact:
if opts.get(b'edit'):
- raise error.Abort(_(b'cannot use --exact with --edit'))
+ raise error.UserError(_(b'cannot use --exact with --edit'))
if opts.get(b'prefix'):
- raise error.Abort(_(b'cannot use --exact with --prefix'))
+ raise error.UserError(_(b'cannot use --exact with --prefix'))
base = opts[b"base"]
msgs = []
@@ -4743,11 +4751,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.UserError(_(b'--line-range requires --follow'))
if linerange and pats:
# TODO: take pats as patterns with no line-range filter
- raise error.Abort(
+ raise error.UserError(
_(b'FILE arguments are not compatible with --line-range option')
)
@@ -4809,7 +4817,7 @@
if opts.get(b'all'):
if rev or node:
- raise error.Abort(_(b"can't specify a revision with --all"))
+ raise error.UserError(_(b"can't specify a revision with --all"))
res = set()
for rev in repo:
@@ -4824,7 +4832,7 @@
return
if rev and node:
- raise error.Abort(_(b"please specify just one revision"))
+ raise error.UserError(_(b"please specify just one revision"))
if not node:
node = rev
@@ -4911,11 +4919,11 @@
hint=state.hint(),
)
if node:
- raise error.Abort(_(b"cannot specify a node with --abort"))
+ raise error.UserError(_(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.UserError(_(b"please specify just one revision"))
if not node:
node = opts.get(b'rev')
@@ -4923,7 +4931,7 @@
ctx = scmutil.revsingle(repo, node)
else:
if ui.configbool(b'commands', b'merge.require-rev'):
- raise error.Abort(
+ raise error.UserError(
_(
b'configuration requires specifying revision to merge '
b'with'
@@ -4932,7 +4940,7 @@
ctx = repo[destutil.destmerge(repo)]
if ctx.node() is None:
- raise error.Abort(_(b'merging with the working copy has no effect'))
+ raise error.UserError(_(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
@@ -5125,7 +5133,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.UserError(_(b'can only specify an explicit filename'))
file_ = m.files()[0]
filenodes = []
for cp in ctx.parents():
@@ -5136,7 +5144,7 @@
except error.LookupError:
pass
if not filenodes:
- raise error.Abort(_(b"'%s' not found in manifest!") % file_)
+ raise error.UserError(_(b"'%s' not found in manifest!") % file_)
p = []
for fn in filenodes:
fctx = repo.filectx(file_, fileid=fn)
@@ -5278,7 +5286,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.UserError(_(b'only one phase can be specified'))
targetphase = idx
# look for specified revision
@@ -5301,7 +5309,7 @@
with repo.lock(), repo.transaction(b"phase") as tr:
# set phase
if not revs:
- raise error.Abort(_(b'empty revision set'))
+ raise error.UserError(_(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
@@ -5444,7 +5452,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.UserError(msg, hint=hint)
source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
@@ -5483,7 +5491,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.UserError(
+ _(b'remote bookmark %s not found!') % b
+ )
nodes.append(remotebookmarks[b])
for i, rev in enumerate(revs):
node = fnodes[i].result()
@@ -5663,7 +5673,7 @@
if revs:
revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
if not revs:
- raise error.Abort(
+ raise error.UserError(
_(b"specified revisions evaluate to an empty set"),
hint=_(b"use different revision arguments"),
)
@@ -5674,11 +5684,11 @@
revs = scmutil.revrange(repo, [expr])
revs = [repo[rev].node() for rev in revs]
if not revs:
- raise error.Abort(
+ raise error.UserError(
_(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.UserError(
_(b'no revisions specified to push'),
hint=_(b'did you mean "hg push -r ."?'),
)
@@ -5807,7 +5817,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.UserError(_(b'no files specified'))
m = scmutil.match(repo[None], pats, opts)
subrepos = opts.get(b'subrepos')
@@ -5937,16 +5947,16 @@
actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
if actioncount > 1:
- raise error.Abort(_(b"too many actions specified"))
+ raise error.UserError(_(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.UserError(_(b'no action specified'), hint=hint)
if pats and all:
- raise error.Abort(_(b"can't specify --all and patterns"))
+ raise error.UserError(_(b"can't specify --all and patterns"))
if not (all or pats or show or mark or unmark):
- raise error.Abort(
+ raise error.UserError(
_(b'no files or directories specified'),
hint=b'use --all to re-merge all unresolved files',
)
@@ -5956,7 +5966,7 @@
if ui.promptchoice(
_(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
):
- raise error.Abort(_(b'user quit'))
+ raise error.UserError(_(b'user quit'))
if mark and not pats:
if ui.promptchoice(
_(
@@ -5964,7 +5974,7 @@
b'$$ &Yes $$ &No'
)
):
- raise error.Abort(_(b'user quit'))
+ raise error.UserError(_(b'user quit'))
if unmark and not pats:
if ui.promptchoice(
_(
@@ -5972,7 +5982,7 @@
b'$$ &Yes $$ &No'
)
):
- raise error.Abort(_(b'user quit'))
+ raise error.UserError(_(b'user quit'))
uipathfn = scmutil.getuipathfn(repo)
@@ -6225,13 +6235,13 @@
opts = pycompat.byteskwargs(opts)
if opts.get(b"date"):
if opts.get(b"rev"):
- raise error.Abort(_(b"you can't specify a revision and a date"))
+ raise error.UserError(_(b"you can't specify a revision and a date"))
opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
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.UserError(
_(b'uncommitted merge with no revision specified'),
hint=_(b"use 'hg update' or see 'hg help revert'"),
)
@@ -6254,7 +6264,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.UserError(msg, hint=hint)
dirty = any(repo.status())
node = ctx.node()
if node != parent:
@@ -6278,7 +6288,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.UserError(msg, hint=hint)
return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
@@ -6487,9 +6497,9 @@
opts = pycompat.byteskwargs(opts)
if opts[b"stdio"] and opts[b"cmdserver"]:
- raise error.Abort(_(b"cannot use --stdio with --cmdserver"))
+ raise error.UserError(_(b"cannot use --stdio with --cmdserver"))
if opts[b"print_url"] and ui.verbose:
- raise error.Abort(_(b"cannot use --print-url with --verbose"))
+ raise error.UserError(_(b"cannot use --print-url with --verbose"))
if opts[b"stdio"]:
if repo is None:
@@ -6615,7 +6625,7 @@
if opts.get(opt):
for i, allowable in allowables:
if opts[i] and opt not in allowable:
- raise error.Abort(
+ raise error.UserError(
_(
b"options '--%s' and '--%s' may not be "
b"used together"
@@ -6626,7 +6636,9 @@
if checkopt(b'cleanup'):
if pats:
- raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
+ raise error.UserError(
+ _(b"cannot specify names when using '--cleanup'")
+ )
return shelvemod.cleanupcmd(ui, repo)
elif checkopt(b'delete'):
return shelvemod.deletecmd(ui, repo, pats)
@@ -6792,7 +6804,7 @@
if revs and terse:
msg = _(b'cannot use --terse with --rev')
- raise error.Abort(msg)
+ raise error.UserError(msg)
elif change:
repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
ctx2 = scmutil.revsingle(repo, change, None)
@@ -7262,15 +7274,15 @@
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.UserError(_(b'tag names must be unique'))
for n in names:
scmutil.checknewlabel(repo, n, b'tag')
if not n:
- raise error.Abort(
+ raise error.UserError(
_(b'tag names cannot consist entirely of whitespace')
)
if opts.get(b'rev') and opts.get(b'remove'):
- raise error.Abort(_(b"--rev and --remove are incompatible"))
+ raise error.UserError(_(b"--rev and --remove are incompatible"))
if opts.get(b'rev'):
rev_ = opts[b'rev']
message = opts.get(b'message')
@@ -7284,16 +7296,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.UserError(
+ _(b"tag '%s' is already removed") % n
+ )
if not repo.tagtype(n):
- raise error.Abort(_(b"tag '%s' does not exist") % n)
+ raise error.UserError(_(b"tag '%s' does not exist") % n)
if repo.tagtype(n) != expectedtype:
if expectedtype == b'global':
- raise error.Abort(
+ raise error.UserError(
_(b"tag '%s' is not a global tag") % n
)
else:
- raise error.Abort(_(b"tag '%s' is not a local tag") % n)
+ raise error.UserError(
+ _(b"tag '%s' is not a local tag") % n
+ )
rev_ = b'null'
if not message:
# we don't translate commit messages
@@ -7301,7 +7317,7 @@
elif not opts.get(b'force'):
for n in names:
if n in repo.tags():
- raise error.Abort(
+ raise error.UserError(
_(b"tag '%s' already exists (use -f to force)") % n
)
if not opts.get(b'local'):
@@ -7342,7 +7358,7 @@
not opts.get(b'remove')
and scmutil.revsingle(repo, rev_).rev() == nullrev
):
- raise error.Abort(_(b"cannot tag null revision"))
+ raise error.UserError(_(b"cannot tag null revision"))
tagsmod.tag(
repo,
@@ -7474,7 +7490,7 @@
f = hg.openpath(ui, fname)
gen = exchange.readbundle(ui, f, fname)
if isinstance(gen, streamclone.streamcloneapplier):
- raise error.Abort(
+ raise error.UserError(
_(
b'packed bundles cannot be applied with '
b'"hg unbundle"'
@@ -7669,11 +7685,11 @@
check = opts.get('check')
merge = opts.get('merge')
if rev and node:
- raise error.Abort(_(b"please specify just one revision"))
+ raise error.UserError(_(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.UserError(
_(b'you must specify a destination'),
hint=_(b'for example: hg update ".::"'),
)
@@ -7682,7 +7698,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.UserError(_(b"you can't specify a revision and a date"))
updatecheck = None
if check:
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -279,7 +279,7 @@
for x in args:
if opts.get(x):
if previous:
- raise error.Abort(
+ raise error.UserError(
_(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.UserError(_(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.UserError(_(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.UserError(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.UserError(
_(
b'cannot partially commit a merge '
b'(use "hg commit" instead)'
@@ -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.UserError(_(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.UserError(b"empty revision set")
roots = repo.revs(b'roots(%ld)', revs)
if len(roots) > 1:
- raise error.Abort(
+ raise error.UserError(
_(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.UserError(
+ _(b"a branch of the same name already exists")
+ )
if repo.revs(b'obsolete() and %ld', revs):
- raise error.Abort(
+ raise error.UserError(
_(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.UserError(
+ _(b"cannot change branch in middle of a stack")
+ )
replacements = {}
# avoid import cycle mercurial.cmdutil -> mercurial.context ->
@@ -1349,7 +1353,7 @@
b'without a repository'
)
if msg:
- raise error.Abort(msg)
+ raise error.UserError(msg)
r = None
if repo:
@@ -1357,7 +1361,7 @@
r = repo.unfiltered().changelog
elif dir:
if not scmutil.istreemanifest(repo):
- raise error.Abort(
+ raise error.UserError(
_(
b"--dir can only be used on repos with "
b"treemanifest enabled"
@@ -1383,11 +1387,13 @@
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.UserError(
+ _(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.UserError(_(b'cannot give path to non-revlog'))
if not file_:
raise error.CommandError(cmd, _(b'invalid arguments'))
@@ -1429,10 +1435,10 @@
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.UserError(_(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.UserError(_(b'cannot mark/unmark copy in merge commit'))
else:
ctx = repo[None]
@@ -1445,7 +1451,7 @@
new_ctx = ctx
else:
if len(ctx.parents()) > 1:
- raise error.Abort(_(b'cannot unmark copy in merge commit'))
+ raise error.UserError(_(b'cannot unmark copy in merge commit'))
# avoid cycle context -> subrepo -> cmdutil
from . import context
@@ -1488,9 +1494,9 @@
pats = scmutil.expandpats(pats)
if not pats:
- raise error.Abort(_(b'no source or destination specified'))
+ raise error.UserError(_(b'no source or destination specified'))
if len(pats) == 1:
- raise error.Abort(_(b'no destination specified'))
+ raise error.UserError(_(b'no destination specified'))
dest = pats.pop()
def walkpat(pat):
@@ -1530,12 +1536,12 @@
rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
absdest = pathutil.canonpath(repo.root, cwd, dest)
if ctx.hasdir(absdest):
- raise error.Abort(
+ raise error.UserError(
_(b'%s: --at-rev does not support a directory as destination')
% uipathfn(absdest)
)
if absdest not in ctx:
- raise error.Abort(
+ raise error.UserError(
_(b'%s: copy destination does not exist in %s')
% (uipathfn(absdest), ctx)
)
@@ -1552,12 +1558,12 @@
copylist.append(abs)
if not copylist:
- raise error.Abort(_(b'no files to copy'))
+ raise error.UserError(_(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.UserError(_(b'--at-rev requires a single source'))
new_ctx = context.overlayworkingctx(repo)
new_ctx.setbase(ctx.p1())
@@ -1785,14 +1791,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.UserError(
_(
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.UserError(
+ _(b'destination %s is not a directory') % dest
+ )
tfn = targetpathfn
if after:
@@ -1804,7 +1812,7 @@
continue
copylist.append((tfn(pat, dest, srcs), srcs))
if not copylist:
- raise error.Abort(_(b'no files to copy'))
+ raise error.UserError(_(b'no files to copy'))
errors = 0
for targetpath, srcs in copylist:
@@ -1895,7 +1903,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.UserError(_(b'not a Mercurial patch'))
p1 = repo[p1]
p2 = repo[p2 or nullid]
elif p2:
@@ -2231,7 +2239,7 @@
try:
rev = mrevs.max()
except ValueError:
- raise error.Abort(_(b"revision matching date not found"))
+ raise error.UserError(_(b"revision matching date not found"))
ui.status(
_(b"found revision %d from %s\n")
@@ -2363,7 +2371,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.UserError(
+ _(b"cannot specify both --dry-run and --interactive")
+ )
bad = []
badfn = lambda x, y: bad.append(x) or match.bad(x, y)
wctx = repo[None]
@@ -3075,9 +3085,9 @@
if finishdesc:
text = finishdesc(text)
if not text.strip():
- raise error.Abort(_(b"empty commit message"))
+ raise error.UserError(_(b"empty commit message"))
if unchangedmessagedetection and editortext == templatetext:
- raise error.Abort(_(b"commit message unchanged"))
+ raise error.UserError(_(b"commit message unchanged"))
return text
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -733,8 +733,8 @@
with extensions.wrappedfunction(scmutil, b'match', normalfilesmatchfn):
try:
result = orig(ui, repo, pats, opts, rename)
- except error.Abort as e:
- if pycompat.bytestr(e) != _(b'no files to copy'):
+ except error.UserError as e:
+ if e.message != _(b'no files to copy'):
raise e
else:
nonormalfiles = True
@@ -850,8 +850,8 @@
lfdirstate.add(destlfile)
lfdirstate.write()
- except error.Abort as e:
- if pycompat.bytestr(e) != _(b'no files to copy'):
+ except error.UserError as e:
+ if e.message != _(b'no files to copy'):
raise e
else:
nolfiles = True
@@ -859,7 +859,7 @@
wlock.release()
if nolfiles and nonormalfiles:
- raise error.Abort(_(b'no files to copy'))
+ raise error.UserError(_(b'no files to copy'))
return result
To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mercurial-scm.org/pipermail/mercurial-patches/attachments/20201007/cec09c39/attachment-0001.html>
More information about the Mercurial-patches
mailing list