This instance will be upgraded to Heptapod 0.21.0rc2 on 2021-04-16 at 14:00 UTC+2 (a few minutes of down time)

error.py 13.5 KB
Newer Older
1 2 3 4 5
# 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's avatar
Matt Mackall committed
6
# GNU General Public License version 2 or any later version.
Matt Mackall's avatar
Matt Mackall committed
7

8 9 10 11 12 13
"""Mercurial exceptions.

This allows us to catch exceptions at higher levels without forcing
imports.
"""

Gregory Szorc's avatar
Gregory Szorc committed
14 15
from __future__ import absolute_import

16 17 18
# Do not import anything but pycompat here, please
from . import pycompat

19

20 21 22 23 24 25 26
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's avatar
Matt Mackall committed
27

28

29 30 31
class Hint(object):
    """Mix-in to provide a hint of an error

32 33
    This should come first in the inheritance list to consume a hint and
    pass remaining arguments to the exception class.
34
    """
35

36
    def __init__(self, *args, **kw):
37
        self.hint = kw.pop('hint', None)
38
        super(Hint, self).__init__(*args, **kw)
39

40

Gregory Szorc's avatar
Gregory Szorc committed
41 42 43 44 45
class StorageError(Hint, Exception):
    """Raised when an error occurs in a storage layer.

    Usually subclassed by a storage-specific exception.
    """
46

Gregory Szorc's avatar
Gregory Szorc committed
47 48
    __bytes__ = _tobytes

49

Gregory Szorc's avatar
Gregory Szorc committed
50
class RevlogError(StorageError):
51
    pass
Matt Mackall's avatar
Matt Mackall committed
52

53

54
class SidedataHashError(RevlogError):
55 56 57 58 59
    def __init__(self, key, expected, got):
        self.sidedatakey = key
        self.expecteddigest = expected
        self.actualdigest = got

60

61
class FilteredIndexError(IndexError):
62
    __bytes__ = _tobytes
63

64

Matt Mackall's avatar
Matt Mackall committed
65 66 67
class LookupError(RevlogError, KeyError):
    def __init__(self, name, index, message):
        self.name = name
68
        self.index = index
69 70 71
        # 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
72
        if isinstance(name, bytes) and len(name) == 20:
Gregory Szorc's avatar
Gregory Szorc committed
73
            from .node import short
74

Matt Mackall's avatar
Matt Mackall committed
75
            name = short(name)
76 77 78 79
        # if name is a binary node, it can be None
        RevlogError.__init__(
            self, b'%s@%s: %s' % (index, pycompat.bytestr(name), message)
        )
Matt Mackall's avatar
Matt Mackall committed
80

81 82 83
    def __bytes__(self):
        return RevlogError.__bytes__(self)

Matt Mackall's avatar
Matt Mackall committed
84 85
    def __str__(self):
        return RevlogError.__str__(self)
Matt Mackall's avatar
Matt Mackall committed
86

87

88 89 90
class AmbiguousPrefixLookupError(LookupError):
    pass

91

92 93 94
class FilteredLookupError(LookupError):
    pass

95

96 97 98
class ManifestLookupError(LookupError):
    pass

99

100
class CommandError(Exception):
Matt Mackall's avatar
Matt Mackall committed
101
    """Exception raised on errors in parsing the command line."""
102

103 104 105 106 107
    def __init__(self, command, message):
        self.command = command
        self.message = message
        super(CommandError, self).__init__()

108
    __bytes__ = _tobytes
Matt Mackall's avatar
Matt Mackall committed
109

110

111 112 113
class UnknownCommand(Exception):
    """Exception raised if command is not in the command table."""

114 115 116 117 118
    def __init__(self, command, all_commands=None):
        self.command = command
        self.all_commands = all_commands
        super(UnknownCommand, self).__init__()

119 120 121 122 123 124
    __bytes__ = _tobytes


class AmbiguousCommand(Exception):
    """Exception raised if command shortcut matches more than one command."""

125 126 127 128 129
    def __init__(self, prefix, matches):
        self.prefix = prefix
        self.matches = matches
        super(AmbiguousCommand, self).__init__()

130 131 132
    __bytes__ = _tobytes


133 134 135 136 137 138 139
class WorkerError(Exception):
    """Exception raised when a worker process dies."""

    def __init__(self, status_code):
        self.status_code = status_code


140
class InterventionRequired(Hint, Exception):
141
    """Exception raised when a command requires human intervention."""
142

143
    __bytes__ = _tobytes
144

145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
class ConflictResolutionRequired(InterventionRequired):
    """Exception raised when a continuable command required merge conflict resolution."""

    def __init__(self, opname):
        from .i18n import _

        self.opname = opname
        InterventionRequired.__init__(
            self,
            _(
                b"unresolved conflicts (see 'hg resolve', then 'hg %s --continue')"
            )
            % opname,
        )


162
class Abort(Hint, Exception):
163
    """Raised if a command needs to print an error and exit."""
164

165 166 167 168 169 170 171 172 173
    def __init__(self, message, hint=None):
        self.message = message
        self.hint = hint
        # Pass the message into the Exception constructor to help extensions
        # that look for exc.args[0].
        Exception.__init__(self, message)

    def __bytes__(self):
        return self.message
174

175 176 177
    if pycompat.ispy3:

        def __str__(self):
178 179 180
            # the output would be unreadable if the message was translated,
            # but do not replace it with encoding.strfromlocal(), which
            # may raise another exception.
181
            return pycompat.sysstr(self.__bytes__())
182

183

184 185 186 187 188 189 190
class InputError(Abort):
    """Indicates that the user made an error in their input.

    Examples: Invalid command, invalid flags, invalid revision.
    """


191 192 193 194 195 196 197
class StateError(Abort):
    """Indicates that the operation might work if retried in a different state.

    Examples: Unresolved merge conflicts, unfinished operations.
    """


198 199 200 201 202 203 204
class CanceledError(Abort):
    """Indicates that the user canceled the operation.

    Examples: Close commit editor with error status, quit chistedit.
    """


205 206 207 208 209
class HookLoadError(Abort):
    """raised when loading a hook fails, aborting an operation

    Exists to allow more specialized catching."""

210

211 212 213 214 215
class HookAbort(Abort):
    """raised when a validation hook fails, aborting an operation

    Exists to allow more specialized catching."""

216

217
class ConfigError(Abort):
218
    """Exception raised when parsing config files"""
Matt Mackall's avatar
Matt Mackall committed
219

220

221 222 223
class UpdateAbort(Abort):
    """Raised when an update is aborted for destination issue"""

224

225 226 227
class MergeDestAbort(Abort):
    """Raised when an update is aborted for destination issues"""

228

229 230 231
class NoMergeDestAbort(MergeDestAbort):
    """Raised when an update is aborted because there is nothing to merge"""

232

233
class ManyMergeDestAbort(MergeDestAbort):
234
    """Raised when an update is aborted because destination is ambiguous"""
235

236

237 238
class ResponseExpected(Abort):
    """Raised when an EOF is received for a prompt"""
239

240 241
    def __init__(self):
        from .i18n import _
242

243
        Abort.__init__(self, _(b'response expected'))
244

245

246
class OutOfBandError(Hint, Exception):
247
    """Exception raised when a remote repo reports failure"""
248

249
    __bytes__ = _tobytes
250

251

252
class ParseError(Hint, Exception):
253
    """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
254

255 256 257 258 259 260 261 262 263 264 265
    def __init__(self, message, location=None, hint=None):
        self.message = message
        self.location = location
        self.hint = hint
        # Pass the message and possibly location into the Exception constructor
        # to help code that looks for exc.args.
        if location is not None:
            Exception.__init__(self, message, location)
        else:
            Exception.__init__(self, message)

266
    __bytes__ = _tobytes
267

268

269 270
class PatchError(Exception):
    __bytes__ = _tobytes
271

272

273 274 275 276
class UnknownIdentifier(ParseError):
    """Exception raised when a {rev,file}set references an unknown identifier"""

    def __init__(self, function, symbols):
Gregory Szorc's avatar
Gregory Szorc committed
277
        from .i18n import _
278

279
        ParseError.__init__(self, _(b"unknown identifier: %s") % function)
280 281 282
        self.function = function
        self.symbols = symbols

283

284
class RepoError(Hint, Exception):
285
    __bytes__ = _tobytes
Matt Mackall's avatar
Matt Mackall committed
286

287

288 289 290
class RepoLookupError(RepoError):
    pass

291

292 293 294
class FilteredRepoLookupError(RepoLookupError):
    pass

295

Matt Mackall's avatar
Matt Mackall committed
296 297
class CapabilityError(RepoError):
    pass
Matt Mackall's avatar
Matt Mackall committed
298

299

300 301 302
class RequirementError(RepoError):
    """Exception raised if .hg/requires has an unknown entry."""

303

304 305 306 307 308 309
class StdioError(IOError):
    """Raised if I/O to stdout or stderr fails"""

    def __init__(self, err):
        IOError.__init__(self, err.errno, err.strerror)

310 311
    # no __bytes__() because error message is derived from the standard IOError

312

313 314 315
class UnsupportedMergeRecords(Abort):
    def __init__(self, recordtypes):
        from .i18n import _
316

317
        self.recordtypes = sorted(recordtypes)
318
        s = b' '.join(self.recordtypes)
319
        Abort.__init__(
320
            self,
321
            _(b'unsupported merge state records: %s') % s,
322
            hint=_(
323 324
                b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
                b'more information'
325 326 327
            ),
        )

328

329 330 331 332 333 334 335 336
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)

337

Matt Mackall's avatar
Matt Mackall committed
338 339 340 341 342
class LockError(IOError):
    def __init__(self, errno, strerror, filename, desc):
        IOError.__init__(self, errno, strerror, filename)
        self.desc = desc

343 344
    # no __bytes__() because error message is derived from the standard IOError

345

Matt Mackall's avatar
Matt Mackall committed
346 347
class LockHeld(LockError):
    def __init__(self, errno, filename, desc, locker):
348
        LockError.__init__(self, errno, b'Lock held', filename, desc)
Matt Mackall's avatar
Matt Mackall committed
349 350
        self.locker = locker

351

Matt Mackall's avatar
Matt Mackall committed
352 353
class LockUnavailable(LockError):
    pass
354

355

356
# LockError is for errors while acquiring the lock -- this is unrelated
357
class LockInheritanceContractViolation(RuntimeError):
358
    __bytes__ = _tobytes
359

360

361 362
class ResponseError(Exception):
    """Raised to print an error with part of output and exit."""
363

364
    __bytes__ = _tobytes
365

366

Matt Mackall's avatar
Matt Mackall committed
367 368 369
# derived from KeyboardInterrupt to simplify some breakout code
class SignalInterrupt(KeyboardInterrupt):
    """Exception raised on SIGTERM and SIGHUP."""
Matt Mackall's avatar
Matt Mackall committed
370

371

Matt Mackall's avatar
Matt Mackall committed
372
class SignatureError(Exception):
373
    __bytes__ = _tobytes
374

375

376 377
class PushRaced(RuntimeError):
    """An exception raised during unbundling that indicate a push race"""
378

379
    __bytes__ = _tobytes
380

381

382
class ProgrammingError(Hint, RuntimeError):
383
    """Raised if a mercurial (core or extension) developer made a mistake"""
384 385

    def __init__(self, msg, *args, **kwargs):
386 387 388 389
        # 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)
390 391
        super(ProgrammingError, self).__init__(msg, *args, **kwargs)

392
    __bytes__ = _tobytes
Jun Wu's avatar
Jun Wu committed
393

394

395 396
class WdirUnsupported(Exception):
    """An exception which is raised when 'wdir()' is not supported"""
397

398
    __bytes__ = _tobytes
399

400

401 402
# bundle2 related errors
class BundleValueError(ValueError):
403
    """error raised when bundle2 cannot be processed"""
404

405
    __bytes__ = _tobytes
406

407

408
class BundleUnknownFeatureError(BundleValueError):
409
    def __init__(self, parttype=None, params=(), values=()):
410
        self.parttype = parttype
411
        self.params = params
412
        self.values = values
413
        if self.parttype is None:
414
            msg = b'Stream Parameter'
415 416
        else:
            msg = parttype
417 418 419 420 421 422 423 424 425
        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:
426
                    entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
427
        if entries:
428
            msg = b'%s - %s' % (msg, b', '.join(entries))
429
        ValueError.__init__(self, msg)
430

431

432 433
class ReadOnlyPartError(RuntimeError):
    """error raised when code tries to alter a part being generated"""
434

435
    __bytes__ = _tobytes
436

437

438 439 440
class PushkeyFailed(Abort):
    """error raised when a pushkey part failed to update a value"""

441 442 443
    def __init__(
        self, partid, namespace=None, key=None, new=None, old=None, ret=None
    ):
444 445 446 447 448 449 450
        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
451
        Abort.__init__(
452
            self, b'failed to update value for "%s/%s"' % (namespace, key)
453 454
        )

455

456
class CensoredNodeError(StorageError):
457
    """error raised when content verification fails on a censored node
458

459 460 461 462
    Also contains the tombstone data substituted for the uncensored data.
    """

    def __init__(self, filename, node, tombstone):
Gregory Szorc's avatar
Gregory Szorc committed
463
        from .node import short
464

465
        StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
466
        self.tombstone = tombstone
467

468

469
class CensoredBaseError(StorageError):
470 471 472 473 474 475
    """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.
    """
476

477

478 479 480 481 482
class InvalidBundleSpecification(Exception):
    """error raised when a bundle specification is invalid.

    This is used for syntax errors as opposed to support errors.
    """
483

484
    __bytes__ = _tobytes
485

486

487 488
class UnsupportedBundleSpecification(Exception):
    """error raised when a bundle specification is not supported."""
489

490
    __bytes__ = _tobytes
491

492

493 494
class CorruptedState(Exception):
    """error raised when a command is not able to read its state from file"""
495

496
    __bytes__ = _tobytes
497

498

499 500
class PeerTransportError(Abort):
    """Transport-level I/O error when communicating with a peer repo."""
501

502

503 504
class InMemoryMergeConflictsError(Exception):
    """Exception raised when merge conflicts arose during an in-memory merge."""
505

506
    __bytes__ = _tobytes
507

508

509 510 511 512 513 514 515
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.
    """
516

517 518 519
    def __init__(self, message, args=None):
        self.message = message
        self.messageargs = args