diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -516,10 +516,8 @@ self.ui.error(_(b"(%s)\n") % inst.hint) errorraised = True except error.Abort as inst: - if isinstance(inst, error.InputError): - detailed_exit_code = 10 - elif isinstance(inst, error.ConfigError): - detailed_exit_code = 30 + if inst.detailed_exit_code is not None: + detailed_exit_code = inst.detailed_exit_code self.ui.error(inst.format()) errorraised = True diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -185,10 +185,11 @@ class Abort(Hint, Exception): """Raised if a command needs to print an error and exit.""" - def __init__(self, message, hint=None): + def __init__(self, message, hint=None, detailed_exit_code=None): # type: (bytes, Optional[bytes]) -> None self.message = message self.hint = hint + self.detailed_exit_code = detailed_exit_code # Pass the message into the Exception constructor to help extensions # that look for exc.args[0]. Exception.__init__(self, message) @@ -220,6 +221,11 @@ Examples: Invalid command, invalid flags, invalid revision. """ + def __init__(self, message, hint=None): + super(InputError, self).__init__( + message, hint=hint, detailed_exit_code=10 + ) + class StateError(Abort): """Indicates that the operation might work if retried in a different state. @@ -227,6 +233,11 @@ Examples: Unresolved merge conflicts, unfinished operations. """ + def __init__(self, message, hint=None): + super(StateError, self).__init__( + message, hint=hint, detailed_exit_code=20 + ) + class CanceledError(Abort): """Indicates that the user canceled the operation. @@ -234,6 +245,11 @@ Examples: Close commit editor with error status, quit chistedit. """ + def __init__(self, message, hint=None): + super(CanceledError, self).__init__( + message, hint=hint, detailed_exit_code=250 + ) + class SecurityError(Abort): """Indicates that some aspect of security failed. @@ -242,6 +258,11 @@ filesystem, mismatched GPG signature, DoS protection. """ + def __init__(self, message, hint=None): + super(SecurityError, self).__init__( + message, hint=hint, detailed_exit_code=150 + ) + class HookLoadError(Abort): """raised when loading a hook fails, aborting an operation @@ -254,13 +275,20 @@ Exists to allow more specialized catching.""" + def __init__(self, message, hint=None): + super(HookAbort, self).__init__( + message, hint=hint, detailed_exit_code=40 + ) + class ConfigError(Abort): """Exception raised when parsing config files""" def __init__(self, message, location=None, hint=None): # type: (bytes, Optional[bytes], Optional[bytes]) -> None - super(ConfigError, self).__init__(message, hint=hint) + super(ConfigError, self).__init__( + message, hint=hint, detailed_exit_code=30 + ) self.location = location def format(self): @@ -307,6 +335,11 @@ class RemoteError(Abort): """Exception raised when interacting with a remote repo fails""" + def __init__(self, message, hint=None): + super(RemoteError, self).__init__( + message, hint=hint, detailed_exit_code=100 + ) + class OutOfBandError(RemoteError): """Exception raised when a remote repo reports failure""" @@ -327,7 +360,9 @@ def __init__(self, message, location=None, hint=None): # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None - super(ParseError, self).__init__(message, hint=hint) + super(ParseError, self).__init__( + message, hint=hint, detailed_exit_code=10 + ) self.location = location def format(self): diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -212,20 +212,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, error.ParseError)): - detailed_exit_code = 10 - elif isinstance(inst, error.StateError): - detailed_exit_code = 20 - elif isinstance(inst, error.ConfigError): - detailed_exit_code = 30 - elif isinstance(inst, error.HookAbort): - detailed_exit_code = 40 - elif isinstance(inst, error.RemoteError): - detailed_exit_code = 100 - elif isinstance(inst, error.SecurityError): - detailed_exit_code = 150 - elif isinstance(inst, error.CanceledError): - detailed_exit_code = 250 + if inst.detailed_exit_code is not None: + detailed_exit_code = inst.detailed_exit_code ui.error(inst.format()) except error.WorkerError as inst: # Don't print a message -- the worker already should have