error.py
336 lines
| 10.6 KiB
| text/x-python
|
PythonLexer
/ mercurial / error.py
Martin Geisler
|
r8226 | # error.py - Mercurial exceptions | ||
# | ||||
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Matt Mackall
|
r7633 | |||
Martin Geisler
|
r8227 | """Mercurial exceptions. | ||
This allows us to catch exceptions at higher levels without forcing | ||||
imports. | ||||
""" | ||||
Gregory Szorc
|
r25945 | from __future__ import absolute_import | ||
Yuya Nishihara
|
r32616 | # Do not import anything but pycompat here, please | ||
from . import pycompat | ||||
def _tobytes(exc): | ||||
"""Byte-stringify exception in the same way as BaseException_str()""" | ||||
if not exc.args: | ||||
return b'' | ||||
if len(exc.args) == 1: | ||||
return pycompat.bytestr(exc.args[0]) | ||||
return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) | ||||
Matt Mackall
|
r7633 | |||
Yuya Nishihara
|
r29509 | class Hint(object): | ||
"""Mix-in to provide a hint of an error | ||||
Yuya Nishihara
|
r29510 | This should come first in the inheritance list to consume a hint and | ||
pass remaining arguments to the exception class. | ||||
Yuya Nishihara
|
r29509 | """ | ||
Jordi Gutiérrez Hermoso
|
r25248 | def __init__(self, *args, **kw): | ||
Augie Fackler
|
r31503 | self.hint = kw.pop(r'hint', None) | ||
Yuya Nishihara
|
r29510 | super(Hint, self).__init__(*args, **kw) | ||
Jordi Gutiérrez Hermoso
|
r25248 | |||
Gregory Szorc
|
r39812 | class StorageError(Hint, Exception): | ||
"""Raised when an error occurs in a storage layer. | ||||
Usually subclassed by a storage-specific exception. | ||||
""" | ||||
__bytes__ = _tobytes | ||||
class RevlogError(StorageError): | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7633 | |||
Pierre-Yves David
|
r23014 | class FilteredIndexError(IndexError): | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pierre-Yves David
|
r23014 | |||
Matt Mackall
|
r7633 | class LookupError(RevlogError, KeyError): | ||
def __init__(self, name, index, message): | ||||
self.name = name | ||||
Martin von Zweigbergk
|
r24038 | self.index = index | ||
Siddharth Agarwal
|
r24137 | # this can't be called 'message' because at least some installs of | ||
# Python 2.6+ complain about the 'message' property being deprecated | ||||
self.lookupmessage = message | ||||
Augie Fackler
|
r36559 | if isinstance(name, bytes) and len(name) == 20: | ||
Gregory Szorc
|
r25945 | from .node import short | ||
Matt Mackall
|
r7633 | name = short(name) | ||
RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) | ||||
Yuya Nishihara
|
r32616 | def __bytes__(self): | ||
return RevlogError.__bytes__(self) | ||||
Matt Mackall
|
r7633 | def __str__(self): | ||
return RevlogError.__str__(self) | ||||
Matt Mackall
|
r7636 | |||
Martin von Zweigbergk
|
r38877 | class AmbiguousPrefixLookupError(LookupError): | ||
pass | ||||
Pierre-Yves David
|
r23015 | class FilteredLookupError(LookupError): | ||
pass | ||||
Takumi IINO
|
r18855 | class ManifestLookupError(LookupError): | ||
pass | ||||
Matt Mackall
|
r11287 | class CommandError(Exception): | ||
Matt Mackall
|
r7636 | """Exception raised on errors in parsing the command line.""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7637 | |||
Yuya Nishihara
|
r29509 | class InterventionRequired(Hint, Exception): | ||
Augie Fackler
|
r18931 | """Exception raised when a command requires human intervention.""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Augie Fackler
|
r18931 | |||
Yuya Nishihara
|
r29509 | class Abort(Hint, Exception): | ||
Matt Mackall
|
r11288 | """Raised if a command needs to print an error and exit.""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r11288 | |||
Siddharth Agarwal
|
r26692 | class HookLoadError(Abort): | ||
"""raised when loading a hook fails, aborting an operation | ||||
Exists to allow more specialized catching.""" | ||||
Pierre-Yves David
|
r23415 | class HookAbort(Abort): | ||
"""raised when a validation hook fails, aborting an operation | ||||
Exists to allow more specialized catching.""" | ||||
Matt Mackall
|
r11288 | class ConfigError(Abort): | ||
Mike Edgar
|
r22359 | """Exception raised when parsing config files""" | ||
Matt Mackall
|
r8144 | |||
Pierre-Yves David
|
r26683 | class UpdateAbort(Abort): | ||
"""Raised when an update is aborted for destination issue""" | ||||
Pierre-Yves David
|
r28141 | class MergeDestAbort(Abort): | ||
"""Raised when an update is aborted for destination issues""" | ||||
class NoMergeDestAbort(MergeDestAbort): | ||||
"""Raised when an update is aborted because there is nothing to merge""" | ||||
class ManyMergeDestAbort(MergeDestAbort): | ||||
Mads Kiilerich
|
r30332 | """Raised when an update is aborted because destination is ambiguous""" | ||
Pierre-Yves David
|
r28141 | |||
Siddharth Agarwal
|
r26896 | class ResponseExpected(Abort): | ||
"""Raised when an EOF is received for a prompt""" | ||||
def __init__(self): | ||||
from .i18n import _ | ||||
Abort.__init__(self, _('response expected')) | ||||
Yuya Nishihara
|
r29509 | class OutOfBandError(Hint, Exception): | ||
Mike Edgar
|
r22359 | """Exception raised when a remote repo reports failure""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Andrew Pritchard
|
r15017 | |||
Yuya Nishihara
|
r29509 | class ParseError(Hint, Exception): | ||
Augie Fackler
|
r24040 | """Raised when parsing config files and {rev,file}sets (msg[, pos])""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r11288 | |||
Yuya Nishihara
|
r34252 | class PatchError(Exception): | ||
__bytes__ = _tobytes | ||||
Augie Fackler
|
r24217 | class UnknownIdentifier(ParseError): | ||
"""Exception raised when a {rev,file}set references an unknown identifier""" | ||||
def __init__(self, function, symbols): | ||||
Gregory Szorc
|
r25945 | from .i18n import _ | ||
Augie Fackler
|
r24217 | ParseError.__init__(self, _("unknown identifier: %s") % function) | ||
self.function = function | ||||
self.symbols = symbols | ||||
Yuya Nishihara
|
r29509 | class RepoError(Hint, Exception): | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7637 | |||
Matt Mackall
|
r9423 | class RepoLookupError(RepoError): | ||
pass | ||||
Pierre-Yves David
|
r23016 | class FilteredRepoLookupError(RepoLookupError): | ||
pass | ||||
Matt Mackall
|
r7637 | class CapabilityError(RepoError): | ||
pass | ||||
Matt Mackall
|
r7640 | |||
Adrian Buehlmann
|
r13447 | class RequirementError(RepoError): | ||
"""Exception raised if .hg/requires has an unknown entry.""" | ||||
Bryan O'Sullivan
|
r31959 | class StdioError(IOError): | ||
"""Raised if I/O to stdout or stderr fails""" | ||||
def __init__(self, err): | ||||
IOError.__init__(self, err.errno, err.strerror) | ||||
Yuya Nishihara
|
r32616 | # no __bytes__() because error message is derived from the standard IOError | ||
Siddharth Agarwal
|
r26985 | class UnsupportedMergeRecords(Abort): | ||
def __init__(self, recordtypes): | ||||
from .i18n import _ | ||||
self.recordtypes = sorted(recordtypes) | ||||
s = ' '.join(self.recordtypes) | ||||
Abort.__init__( | ||||
self, _('unsupported merge state records: %s') % s, | ||||
hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for ' | ||||
'more information')) | ||||
r32591 | class UnknownVersion(Abort): | |||
"""generic exception for aborting from an encounter with an unknown version | ||||
""" | ||||
def __init__(self, msg, hint=None, version=None): | ||||
self.version = version | ||||
super(UnknownVersion, self).__init__(msg, hint=hint) | ||||
Matt Mackall
|
r7640 | class LockError(IOError): | ||
def __init__(self, errno, strerror, filename, desc): | ||||
IOError.__init__(self, errno, strerror, filename) | ||||
self.desc = desc | ||||
Yuya Nishihara
|
r32616 | # no __bytes__() because error message is derived from the standard IOError | ||
Matt Mackall
|
r7640 | class LockHeld(LockError): | ||
def __init__(self, errno, filename, desc, locker): | ||||
LockError.__init__(self, errno, 'Lock held', filename, desc) | ||||
self.locker = locker | ||||
class LockUnavailable(LockError): | ||||
pass | ||||
Matt Mackall
|
r7641 | |||
Siddharth Agarwal
|
r26355 | # LockError is for errors while acquiring the lock -- this is unrelated | ||
Siddharth Agarwal
|
r26438 | class LockInheritanceContractViolation(RuntimeError): | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Siddharth Agarwal
|
r26355 | |||
Matt Mackall
|
r7641 | class ResponseError(Exception): | ||
"""Raised to print an error with part of output and exit.""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7641 | |||
Matt Mackall
|
r7643 | class UnknownCommand(Exception): | ||
"""Exception raised if command is not in the command table.""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7643 | |||
class AmbiguousCommand(Exception): | ||||
"""Exception raised if command shortcut matches more than one command.""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Matt Mackall
|
r7643 | |||
Matt Mackall
|
r7644 | # derived from KeyboardInterrupt to simplify some breakout code | ||
class SignalInterrupt(KeyboardInterrupt): | ||||
"""Exception raised on SIGTERM and SIGHUP.""" | ||||
Matt Mackall
|
r7646 | |||
class SignatureError(Exception): | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pierre-Yves David
|
r21184 | |||
class PushRaced(RuntimeError): | ||||
"""An exception raised during unbundling that indicate a push race""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pierre-Yves David
|
r21184 | |||
Yuya Nishihara
|
r32340 | class ProgrammingError(Hint, RuntimeError): | ||
Jun Wu
|
r30585 | """Raised if a mercurial (core or extension) developer made a mistake""" | ||
Augie Fackler
|
r39615 | |||
def __init__(self, msg, *args, **kwargs): | ||||
Yuya Nishihara
|
r39632 | # On Python 3, turn the message back into a string since this is | ||
# an internal-only error that won't be printed except in a | ||||
# stack traces. | ||||
msg = pycompat.sysstr(msg) | ||||
Augie Fackler
|
r39615 | super(ProgrammingError, self).__init__(msg, *args, **kwargs) | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Jun Wu
|
r30573 | |||
Pulkit Goyal
|
r32401 | class WdirUnsupported(Exception): | ||
"""An exception which is raised when 'wdir()' is not supported""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pulkit Goyal
|
r32401 | |||
Pierre-Yves David
|
r21618 | # bundle2 related errors | ||
class BundleValueError(ValueError): | ||||
Pierre-Yves David
|
r21621 | """error raised when bundle2 cannot be processed""" | ||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pierre-Yves David
|
r21620 | |||
Pierre-Yves David
|
r26393 | class BundleUnknownFeatureError(BundleValueError): | ||
Pierre-Yves David
|
r26394 | def __init__(self, parttype=None, params=(), values=()): | ||
Pierre-Yves David
|
r21620 | self.parttype = parttype | ||
Pierre-Yves David
|
r21621 | self.params = params | ||
Pierre-Yves David
|
r26394 | self.values = values | ||
Pierre-Yves David
|
r21627 | if self.parttype is None: | ||
msg = 'Stream Parameter' | ||||
else: | ||||
msg = parttype | ||||
Pierre-Yves David
|
r26394 | entries = self.params | ||
if self.params and self.values: | ||||
assert len(self.params) == len(self.values) | ||||
entries = [] | ||||
for idx, par in enumerate(self.params): | ||||
val = self.values[idx] | ||||
if val is None: | ||||
entries.append(val) | ||||
else: | ||||
Yuya Nishihara
|
r38626 | entries.append("%s=%r" % (par, pycompat.maybebytestr(val))) | ||
Pierre-Yves David
|
r26394 | if entries: | ||
msg = '%s - %s' % (msg, ', '.join(entries)) | ||||
Brendan Cully
|
r21747 | ValueError.__init__(self, msg) | ||
Pierre-Yves David
|
r21618 | |||
class ReadOnlyPartError(RuntimeError): | ||||
"""error raised when code tries to alter a part being generated""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Pierre-Yves David
|
r21618 | |||
Pierre-Yves David
|
r25484 | class PushkeyFailed(Abort): | ||
"""error raised when a pushkey part failed to update a value""" | ||||
def __init__(self, partid, namespace=None, key=None, new=None, old=None, | ||||
ret=None): | ||||
self.partid = partid | ||||
self.namespace = namespace | ||||
self.key = key | ||||
self.new = new | ||||
self.old = old | ||||
self.ret = ret | ||||
# no i18n expected to be processed into a better message | ||||
Abort.__init__(self, 'failed to update value for "%s/%s"' | ||||
% (namespace, key)) | ||||
Gregory Szorc
|
r39813 | class CensoredNodeError(StorageError): | ||
Mike Edgar
|
r24190 | """error raised when content verification fails on a censored node | ||
Mike Edgar
|
r22595 | |||
Mike Edgar
|
r24190 | Also contains the tombstone data substituted for the uncensored data. | ||
""" | ||||
def __init__(self, filename, node, tombstone): | ||||
Gregory Szorc
|
r25945 | from .node import short | ||
Gregory Szorc
|
r39813 | StorageError.__init__(self, '%s:%s' % (filename, short(node))) | ||
Mike Edgar
|
r24190 | self.tombstone = tombstone | ||
Mike Edgar
|
r24120 | |||
Gregory Szorc
|
r39813 | class CensoredBaseError(StorageError): | ||
Mike Edgar
|
r24120 | """error raised when a delta is rejected because its base is censored | ||
A delta based on a censored revision must be formed as single patch | ||||
operation which replaces the entire base with new content. This ensures | ||||
the delta may be applied by clones which have not censored the base. | ||||
""" | ||||
Gregory Szorc
|
r26640 | |||
class InvalidBundleSpecification(Exception): | ||||
"""error raised when a bundle specification is invalid. | ||||
This is used for syntax errors as opposed to support errors. | ||||
""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Gregory Szorc
|
r26640 | |||
class UnsupportedBundleSpecification(Exception): | ||||
"""error raised when a bundle specification is not supported.""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Kostia Balytskyi
|
r29536 | |||
class CorruptedState(Exception): | ||||
"""error raised when a command is not able to read its state from file""" | ||||
Yuya Nishihara
|
r32616 | __bytes__ = _tobytes | ||
Gregory Szorc
|
r32002 | |||
Gregory Szorc
|
r32023 | class PeerTransportError(Abort): | ||
"""Transport-level I/O error when communicating with a peer repo.""" | ||||
Phil Cohen
|
r35104 | |||
class InMemoryMergeConflictsError(Exception): | ||||
"""Exception raised when merge conflicts arose during an in-memory merge.""" | ||||
__bytes__ = _tobytes | ||||
Gregory Szorc
|
r39595 | |||
class WireprotoCommandError(Exception): | ||||
"""Represents an error during execution of a wire protocol command. | ||||
Should only be thrown by wire protocol version 2 commands. | ||||
The error is a formatter string and an optional iterable of arguments. | ||||
""" | ||||
def __init__(self, message, args=None): | ||||
self.message = message | ||||
self.messageargs = args | ||||