Mercurial > public > mercurial-scm > hg
comparison mercurial/error.py @ 47289:33c0c25d0b0f
errors: let each Abort subclass define its error code
It's more flexible to have the error codes defined on the error types
themselves. That way extensions can easily set their own exit code. It
also means that we can reduce a bit of duplication betwen
`scmutil.callcatch()` and `chgserver.chgcmdserver.validate()`.
Differential Revision: https://phab.mercurial-scm.org/D10735
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Tue, 18 May 2021 17:15:49 -0700 |
parents | abd18d6306f1 |
children | 5e736d2e9703 |
comparison
equal
deleted
inserted
replaced
47288:16b48ebf656e | 47289:33c0c25d0b0f |
---|---|
183 | 183 |
184 | 184 |
185 class Abort(Hint, Exception): | 185 class Abort(Hint, Exception): |
186 """Raised if a command needs to print an error and exit.""" | 186 """Raised if a command needs to print an error and exit.""" |
187 | 187 |
188 def __init__(self, message, hint=None): | 188 def __init__(self, message, hint=None, detailed_exit_code=None): |
189 # type: (bytes, Optional[bytes]) -> None | 189 # type: (bytes, Optional[bytes]) -> None |
190 self.message = message | 190 self.message = message |
191 self.hint = hint | 191 self.hint = hint |
192 self.detailed_exit_code = detailed_exit_code | |
192 # Pass the message into the Exception constructor to help extensions | 193 # Pass the message into the Exception constructor to help extensions |
193 # that look for exc.args[0]. | 194 # that look for exc.args[0]. |
194 Exception.__init__(self, message) | 195 Exception.__init__(self, message) |
195 | 196 |
196 def __bytes__(self): | 197 def __bytes__(self): |
218 """Indicates that the user made an error in their input. | 219 """Indicates that the user made an error in their input. |
219 | 220 |
220 Examples: Invalid command, invalid flags, invalid revision. | 221 Examples: Invalid command, invalid flags, invalid revision. |
221 """ | 222 """ |
222 | 223 |
224 def __init__(self, message, hint=None): | |
225 super(InputError, self).__init__( | |
226 message, hint=hint, detailed_exit_code=10 | |
227 ) | |
228 | |
223 | 229 |
224 class StateError(Abort): | 230 class StateError(Abort): |
225 """Indicates that the operation might work if retried in a different state. | 231 """Indicates that the operation might work if retried in a different state. |
226 | 232 |
227 Examples: Unresolved merge conflicts, unfinished operations. | 233 Examples: Unresolved merge conflicts, unfinished operations. |
228 """ | 234 """ |
229 | 235 |
236 def __init__(self, message, hint=None): | |
237 super(StateError, self).__init__( | |
238 message, hint=hint, detailed_exit_code=20 | |
239 ) | |
240 | |
230 | 241 |
231 class CanceledError(Abort): | 242 class CanceledError(Abort): |
232 """Indicates that the user canceled the operation. | 243 """Indicates that the user canceled the operation. |
233 | 244 |
234 Examples: Close commit editor with error status, quit chistedit. | 245 Examples: Close commit editor with error status, quit chistedit. |
235 """ | 246 """ |
236 | 247 |
248 def __init__(self, message, hint=None): | |
249 super(CanceledError, self).__init__( | |
250 message, hint=hint, detailed_exit_code=250 | |
251 ) | |
252 | |
237 | 253 |
238 class SecurityError(Abort): | 254 class SecurityError(Abort): |
239 """Indicates that some aspect of security failed. | 255 """Indicates that some aspect of security failed. |
240 | 256 |
241 Examples: Bad server credentials, expired local credentials for network | 257 Examples: Bad server credentials, expired local credentials for network |
242 filesystem, mismatched GPG signature, DoS protection. | 258 filesystem, mismatched GPG signature, DoS protection. |
243 """ | 259 """ |
244 | 260 |
261 def __init__(self, message, hint=None): | |
262 super(SecurityError, self).__init__( | |
263 message, hint=hint, detailed_exit_code=150 | |
264 ) | |
265 | |
245 | 266 |
246 class HookLoadError(Abort): | 267 class HookLoadError(Abort): |
247 """raised when loading a hook fails, aborting an operation | 268 """raised when loading a hook fails, aborting an operation |
248 | 269 |
249 Exists to allow more specialized catching.""" | 270 Exists to allow more specialized catching.""" |
252 class HookAbort(Abort): | 273 class HookAbort(Abort): |
253 """raised when a validation hook fails, aborting an operation | 274 """raised when a validation hook fails, aborting an operation |
254 | 275 |
255 Exists to allow more specialized catching.""" | 276 Exists to allow more specialized catching.""" |
256 | 277 |
278 def __init__(self, message, hint=None): | |
279 super(HookAbort, self).__init__( | |
280 message, hint=hint, detailed_exit_code=40 | |
281 ) | |
282 | |
257 | 283 |
258 class ConfigError(Abort): | 284 class ConfigError(Abort): |
259 """Exception raised when parsing config files""" | 285 """Exception raised when parsing config files""" |
260 | 286 |
261 def __init__(self, message, location=None, hint=None): | 287 def __init__(self, message, location=None, hint=None): |
262 # type: (bytes, Optional[bytes], Optional[bytes]) -> None | 288 # type: (bytes, Optional[bytes], Optional[bytes]) -> None |
263 super(ConfigError, self).__init__(message, hint=hint) | 289 super(ConfigError, self).__init__( |
290 message, hint=hint, detailed_exit_code=30 | |
291 ) | |
264 self.location = location | 292 self.location = location |
265 | 293 |
266 def format(self): | 294 def format(self): |
267 # type: () -> bytes | 295 # type: () -> bytes |
268 from .i18n import _ | 296 from .i18n import _ |
305 | 333 |
306 | 334 |
307 class RemoteError(Abort): | 335 class RemoteError(Abort): |
308 """Exception raised when interacting with a remote repo fails""" | 336 """Exception raised when interacting with a remote repo fails""" |
309 | 337 |
338 def __init__(self, message, hint=None): | |
339 super(RemoteError, self).__init__( | |
340 message, hint=hint, detailed_exit_code=100 | |
341 ) | |
342 | |
310 | 343 |
311 class OutOfBandError(RemoteError): | 344 class OutOfBandError(RemoteError): |
312 """Exception raised when a remote repo reports failure""" | 345 """Exception raised when a remote repo reports failure""" |
313 | 346 |
314 def __init__(self, message=None, hint=None): | 347 def __init__(self, message=None, hint=None): |
325 class ParseError(Abort): | 358 class ParseError(Abort): |
326 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" | 359 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" |
327 | 360 |
328 def __init__(self, message, location=None, hint=None): | 361 def __init__(self, message, location=None, hint=None): |
329 # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None | 362 # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None |
330 super(ParseError, self).__init__(message, hint=hint) | 363 super(ParseError, self).__init__( |
364 message, hint=hint, detailed_exit_code=10 | |
365 ) | |
331 self.location = location | 366 self.location = location |
332 | 367 |
333 def format(self): | 368 def format(self): |
334 # type: () -> bytes | 369 # type: () -> bytes |
335 from .i18n import _ | 370 from .i18n import _ |