##// END OF EJS Templates
errors: remove unnecessary varargs handling from OutOfBandError...
Martin von Zweigbergk -
r47743:abd18d63 default
parent child Browse files
Show More
@@ -1,632 +1,631 b''
1 # error.py - Mercurial exceptions
1 # error.py - Mercurial exceptions
2 #
2 #
3 # Copyright 2005-2008 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2008 Olivia Mackall <olivia@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """Mercurial exceptions.
8 """Mercurial exceptions.
9
9
10 This allows us to catch exceptions at higher levels without forcing
10 This allows us to catch exceptions at higher levels without forcing
11 imports.
11 imports.
12 """
12 """
13
13
14 from __future__ import absolute_import
14 from __future__ import absolute_import
15
15
16 import difflib
16 import difflib
17
17
18 # Do not import anything but pycompat here, please
18 # Do not import anything but pycompat here, please
19 from . import pycompat
19 from . import pycompat
20
20
21 if pycompat.TYPE_CHECKING:
21 if pycompat.TYPE_CHECKING:
22 from typing import (
22 from typing import (
23 Any,
23 Any,
24 AnyStr,
24 AnyStr,
25 Iterable,
25 Iterable,
26 List,
26 List,
27 Optional,
27 Optional,
28 Sequence,
28 Sequence,
29 Union,
29 Union,
30 )
30 )
31
31
32
32
33 def _tobytes(exc):
33 def _tobytes(exc):
34 """Byte-stringify exception in the same way as BaseException_str()"""
34 """Byte-stringify exception in the same way as BaseException_str()"""
35 if not exc.args:
35 if not exc.args:
36 return b''
36 return b''
37 if len(exc.args) == 1:
37 if len(exc.args) == 1:
38 return pycompat.bytestr(exc.args[0])
38 return pycompat.bytestr(exc.args[0])
39 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
39 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
40
40
41
41
42 class Hint(object):
42 class Hint(object):
43 """Mix-in to provide a hint of an error
43 """Mix-in to provide a hint of an error
44
44
45 This should come first in the inheritance list to consume a hint and
45 This should come first in the inheritance list to consume a hint and
46 pass remaining arguments to the exception class.
46 pass remaining arguments to the exception class.
47 """
47 """
48
48
49 def __init__(self, *args, **kw):
49 def __init__(self, *args, **kw):
50 self.hint = kw.pop('hint', None)
50 self.hint = kw.pop('hint', None)
51 super(Hint, self).__init__(*args, **kw)
51 super(Hint, self).__init__(*args, **kw)
52
52
53
53
54 class StorageError(Hint, Exception):
54 class StorageError(Hint, Exception):
55 """Raised when an error occurs in a storage layer.
55 """Raised when an error occurs in a storage layer.
56
56
57 Usually subclassed by a storage-specific exception.
57 Usually subclassed by a storage-specific exception.
58 """
58 """
59
59
60 __bytes__ = _tobytes
60 __bytes__ = _tobytes
61
61
62
62
63 class RevlogError(StorageError):
63 class RevlogError(StorageError):
64 pass
64 pass
65
65
66
66
67 class SidedataHashError(RevlogError):
67 class SidedataHashError(RevlogError):
68 def __init__(self, key, expected, got):
68 def __init__(self, key, expected, got):
69 self.hint = None
69 self.hint = None
70 self.sidedatakey = key
70 self.sidedatakey = key
71 self.expecteddigest = expected
71 self.expecteddigest = expected
72 self.actualdigest = got
72 self.actualdigest = got
73
73
74
74
75 class FilteredIndexError(IndexError):
75 class FilteredIndexError(IndexError):
76 __bytes__ = _tobytes
76 __bytes__ = _tobytes
77
77
78
78
79 class LookupError(RevlogError, KeyError):
79 class LookupError(RevlogError, KeyError):
80 def __init__(self, name, index, message):
80 def __init__(self, name, index, message):
81 self.name = name
81 self.name = name
82 self.index = index
82 self.index = index
83 # this can't be called 'message' because at least some installs of
83 # this can't be called 'message' because at least some installs of
84 # Python 2.6+ complain about the 'message' property being deprecated
84 # Python 2.6+ complain about the 'message' property being deprecated
85 self.lookupmessage = message
85 self.lookupmessage = message
86 if isinstance(name, bytes) and len(name) == 20:
86 if isinstance(name, bytes) and len(name) == 20:
87 from .node import hex
87 from .node import hex
88
88
89 name = hex(name)
89 name = hex(name)
90 # if name is a binary node, it can be None
90 # if name is a binary node, it can be None
91 RevlogError.__init__(
91 RevlogError.__init__(
92 self, b'%s@%s: %s' % (index, pycompat.bytestr(name), message)
92 self, b'%s@%s: %s' % (index, pycompat.bytestr(name), message)
93 )
93 )
94
94
95 def __bytes__(self):
95 def __bytes__(self):
96 return RevlogError.__bytes__(self)
96 return RevlogError.__bytes__(self)
97
97
98 def __str__(self):
98 def __str__(self):
99 return RevlogError.__str__(self)
99 return RevlogError.__str__(self)
100
100
101
101
102 class AmbiguousPrefixLookupError(LookupError):
102 class AmbiguousPrefixLookupError(LookupError):
103 pass
103 pass
104
104
105
105
106 class FilteredLookupError(LookupError):
106 class FilteredLookupError(LookupError):
107 pass
107 pass
108
108
109
109
110 class ManifestLookupError(LookupError):
110 class ManifestLookupError(LookupError):
111 pass
111 pass
112
112
113
113
114 class CommandError(Exception):
114 class CommandError(Exception):
115 """Exception raised on errors in parsing the command line."""
115 """Exception raised on errors in parsing the command line."""
116
116
117 def __init__(self, command, message):
117 def __init__(self, command, message):
118 # type: (bytes, bytes) -> None
118 # type: (bytes, bytes) -> None
119 self.command = command
119 self.command = command
120 self.message = message
120 self.message = message
121 super(CommandError, self).__init__()
121 super(CommandError, self).__init__()
122
122
123 __bytes__ = _tobytes
123 __bytes__ = _tobytes
124
124
125
125
126 class UnknownCommand(Exception):
126 class UnknownCommand(Exception):
127 """Exception raised if command is not in the command table."""
127 """Exception raised if command is not in the command table."""
128
128
129 def __init__(self, command, all_commands=None):
129 def __init__(self, command, all_commands=None):
130 # type: (bytes, Optional[List[bytes]]) -> None
130 # type: (bytes, Optional[List[bytes]]) -> None
131 self.command = command
131 self.command = command
132 self.all_commands = all_commands
132 self.all_commands = all_commands
133 super(UnknownCommand, self).__init__()
133 super(UnknownCommand, self).__init__()
134
134
135 __bytes__ = _tobytes
135 __bytes__ = _tobytes
136
136
137
137
138 class AmbiguousCommand(Exception):
138 class AmbiguousCommand(Exception):
139 """Exception raised if command shortcut matches more than one command."""
139 """Exception raised if command shortcut matches more than one command."""
140
140
141 def __init__(self, prefix, matches):
141 def __init__(self, prefix, matches):
142 # type: (bytes, List[bytes]) -> None
142 # type: (bytes, List[bytes]) -> None
143 self.prefix = prefix
143 self.prefix = prefix
144 self.matches = matches
144 self.matches = matches
145 super(AmbiguousCommand, self).__init__()
145 super(AmbiguousCommand, self).__init__()
146
146
147 __bytes__ = _tobytes
147 __bytes__ = _tobytes
148
148
149
149
150 class WorkerError(Exception):
150 class WorkerError(Exception):
151 """Exception raised when a worker process dies."""
151 """Exception raised when a worker process dies."""
152
152
153 def __init__(self, status_code):
153 def __init__(self, status_code):
154 # type: (int) -> None
154 # type: (int) -> None
155 self.status_code = status_code
155 self.status_code = status_code
156 # Pass status code to superclass just so it becomes part of __bytes__
156 # Pass status code to superclass just so it becomes part of __bytes__
157 super(WorkerError, self).__init__(status_code)
157 super(WorkerError, self).__init__(status_code)
158
158
159 __bytes__ = _tobytes
159 __bytes__ = _tobytes
160
160
161
161
162 class InterventionRequired(Hint, Exception):
162 class InterventionRequired(Hint, Exception):
163 """Exception raised when a command requires human intervention."""
163 """Exception raised when a command requires human intervention."""
164
164
165 __bytes__ = _tobytes
165 __bytes__ = _tobytes
166
166
167
167
168 class ConflictResolutionRequired(InterventionRequired):
168 class ConflictResolutionRequired(InterventionRequired):
169 """Exception raised when a continuable command required merge conflict resolution."""
169 """Exception raised when a continuable command required merge conflict resolution."""
170
170
171 def __init__(self, opname):
171 def __init__(self, opname):
172 # type: (bytes) -> None
172 # type: (bytes) -> None
173 from .i18n import _
173 from .i18n import _
174
174
175 self.opname = opname
175 self.opname = opname
176 InterventionRequired.__init__(
176 InterventionRequired.__init__(
177 self,
177 self,
178 _(
178 _(
179 b"unresolved conflicts (see 'hg resolve', then 'hg %s --continue')"
179 b"unresolved conflicts (see 'hg resolve', then 'hg %s --continue')"
180 )
180 )
181 % opname,
181 % opname,
182 )
182 )
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):
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 # Pass the message into the Exception constructor to help extensions
192 # Pass the message into the Exception constructor to help extensions
193 # that look for exc.args[0].
193 # that look for exc.args[0].
194 Exception.__init__(self, message)
194 Exception.__init__(self, message)
195
195
196 def __bytes__(self):
196 def __bytes__(self):
197 return self.message
197 return self.message
198
198
199 if pycompat.ispy3:
199 if pycompat.ispy3:
200
200
201 def __str__(self):
201 def __str__(self):
202 # the output would be unreadable if the message was translated,
202 # the output would be unreadable if the message was translated,
203 # but do not replace it with encoding.strfromlocal(), which
203 # but do not replace it with encoding.strfromlocal(), which
204 # may raise another exception.
204 # may raise another exception.
205 return pycompat.sysstr(self.__bytes__())
205 return pycompat.sysstr(self.__bytes__())
206
206
207 def format(self):
207 def format(self):
208 # type: () -> bytes
208 # type: () -> bytes
209 from .i18n import _
209 from .i18n import _
210
210
211 message = _(b"abort: %s\n") % self.message
211 message = _(b"abort: %s\n") % self.message
212 if self.hint:
212 if self.hint:
213 message += _(b"(%s)\n") % self.hint
213 message += _(b"(%s)\n") % self.hint
214 return message
214 return message
215
215
216
216
217 class InputError(Abort):
217 class InputError(Abort):
218 """Indicates that the user made an error in their input.
218 """Indicates that the user made an error in their input.
219
219
220 Examples: Invalid command, invalid flags, invalid revision.
220 Examples: Invalid command, invalid flags, invalid revision.
221 """
221 """
222
222
223
223
224 class StateError(Abort):
224 class StateError(Abort):
225 """Indicates that the operation might work if retried in a different state.
225 """Indicates that the operation might work if retried in a different state.
226
226
227 Examples: Unresolved merge conflicts, unfinished operations.
227 Examples: Unresolved merge conflicts, unfinished operations.
228 """
228 """
229
229
230
230
231 class CanceledError(Abort):
231 class CanceledError(Abort):
232 """Indicates that the user canceled the operation.
232 """Indicates that the user canceled the operation.
233
233
234 Examples: Close commit editor with error status, quit chistedit.
234 Examples: Close commit editor with error status, quit chistedit.
235 """
235 """
236
236
237
237
238 class SecurityError(Abort):
238 class SecurityError(Abort):
239 """Indicates that some aspect of security failed.
239 """Indicates that some aspect of security failed.
240
240
241 Examples: Bad server credentials, expired local credentials for network
241 Examples: Bad server credentials, expired local credentials for network
242 filesystem, mismatched GPG signature, DoS protection.
242 filesystem, mismatched GPG signature, DoS protection.
243 """
243 """
244
244
245
245
246 class HookLoadError(Abort):
246 class HookLoadError(Abort):
247 """raised when loading a hook fails, aborting an operation
247 """raised when loading a hook fails, aborting an operation
248
248
249 Exists to allow more specialized catching."""
249 Exists to allow more specialized catching."""
250
250
251
251
252 class HookAbort(Abort):
252 class HookAbort(Abort):
253 """raised when a validation hook fails, aborting an operation
253 """raised when a validation hook fails, aborting an operation
254
254
255 Exists to allow more specialized catching."""
255 Exists to allow more specialized catching."""
256
256
257
257
258 class ConfigError(Abort):
258 class ConfigError(Abort):
259 """Exception raised when parsing config files"""
259 """Exception raised when parsing config files"""
260
260
261 def __init__(self, message, location=None, hint=None):
261 def __init__(self, message, location=None, hint=None):
262 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
262 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
263 super(ConfigError, self).__init__(message, hint=hint)
263 super(ConfigError, self).__init__(message, hint=hint)
264 self.location = location
264 self.location = location
265
265
266 def format(self):
266 def format(self):
267 # type: () -> bytes
267 # type: () -> bytes
268 from .i18n import _
268 from .i18n import _
269
269
270 if self.location is not None:
270 if self.location is not None:
271 message = _(b"config error at %s: %s\n") % (
271 message = _(b"config error at %s: %s\n") % (
272 pycompat.bytestr(self.location),
272 pycompat.bytestr(self.location),
273 self.message,
273 self.message,
274 )
274 )
275 else:
275 else:
276 message = _(b"config error: %s\n") % self.message
276 message = _(b"config error: %s\n") % self.message
277 if self.hint:
277 if self.hint:
278 message += _(b"(%s)\n") % self.hint
278 message += _(b"(%s)\n") % self.hint
279 return message
279 return message
280
280
281
281
282 class UpdateAbort(Abort):
282 class UpdateAbort(Abort):
283 """Raised when an update is aborted for destination issue"""
283 """Raised when an update is aborted for destination issue"""
284
284
285
285
286 class MergeDestAbort(Abort):
286 class MergeDestAbort(Abort):
287 """Raised when an update is aborted for destination issues"""
287 """Raised when an update is aborted for destination issues"""
288
288
289
289
290 class NoMergeDestAbort(MergeDestAbort):
290 class NoMergeDestAbort(MergeDestAbort):
291 """Raised when an update is aborted because there is nothing to merge"""
291 """Raised when an update is aborted because there is nothing to merge"""
292
292
293
293
294 class ManyMergeDestAbort(MergeDestAbort):
294 class ManyMergeDestAbort(MergeDestAbort):
295 """Raised when an update is aborted because destination is ambiguous"""
295 """Raised when an update is aborted because destination is ambiguous"""
296
296
297
297
298 class ResponseExpected(Abort):
298 class ResponseExpected(Abort):
299 """Raised when an EOF is received for a prompt"""
299 """Raised when an EOF is received for a prompt"""
300
300
301 def __init__(self):
301 def __init__(self):
302 from .i18n import _
302 from .i18n import _
303
303
304 Abort.__init__(self, _(b'response expected'))
304 Abort.__init__(self, _(b'response expected'))
305
305
306
306
307 class RemoteError(Abort):
307 class RemoteError(Abort):
308 """Exception raised when interacting with a remote repo fails"""
308 """Exception raised when interacting with a remote repo fails"""
309
309
310
310
311 class OutOfBandError(RemoteError):
311 class OutOfBandError(RemoteError):
312 """Exception raised when a remote repo reports failure"""
312 """Exception raised when a remote repo reports failure"""
313
313
314 def __init__(self, *messages, **kwargs):
314 def __init__(self, message=None, hint=None):
315 from .i18n import _
315 from .i18n import _
316
316
317 if messages:
317 if message:
318 message = _(b"remote error:\n%s") % b''.join(messages)
319 # Abort.format() adds a trailing newline
318 # Abort.format() adds a trailing newline
320 message = message.rstrip(b'\n')
319 message = _(b"remote error:\n%s") % message.rstrip(b'\n')
321 else:
320 else:
322 message = _(b"remote error")
321 message = _(b"remote error")
323 super(OutOfBandError, self).__init__(message, **kwargs)
322 super(OutOfBandError, self).__init__(message, hint=hint)
324
323
325
324
326 class ParseError(Abort):
325 class ParseError(Abort):
327 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
326 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
328
327
329 def __init__(self, message, location=None, hint=None):
328 def __init__(self, message, location=None, hint=None):
330 # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None
329 # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None
331 super(ParseError, self).__init__(message, hint=hint)
330 super(ParseError, self).__init__(message, hint=hint)
332 self.location = location
331 self.location = location
333
332
334 def format(self):
333 def format(self):
335 # type: () -> bytes
334 # type: () -> bytes
336 from .i18n import _
335 from .i18n import _
337
336
338 if self.location is not None:
337 if self.location is not None:
339 message = _(b"hg: parse error at %s: %s\n") % (
338 message = _(b"hg: parse error at %s: %s\n") % (
340 pycompat.bytestr(self.location),
339 pycompat.bytestr(self.location),
341 self.message,
340 self.message,
342 )
341 )
343 else:
342 else:
344 message = _(b"hg: parse error: %s\n") % self.message
343 message = _(b"hg: parse error: %s\n") % self.message
345 if self.hint:
344 if self.hint:
346 message += _(b"(%s)\n") % self.hint
345 message += _(b"(%s)\n") % self.hint
347 return message
346 return message
348
347
349
348
350 class PatchError(Exception):
349 class PatchError(Exception):
351 __bytes__ = _tobytes
350 __bytes__ = _tobytes
352
351
353
352
354 def getsimilar(symbols, value):
353 def getsimilar(symbols, value):
355 # type: (Iterable[bytes], bytes) -> List[bytes]
354 # type: (Iterable[bytes], bytes) -> List[bytes]
356 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
355 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
357 # The cutoff for similarity here is pretty arbitrary. It should
356 # The cutoff for similarity here is pretty arbitrary. It should
358 # probably be investigated and tweaked.
357 # probably be investigated and tweaked.
359 return [s for s in symbols if sim(s) > 0.6]
358 return [s for s in symbols if sim(s) > 0.6]
360
359
361
360
362 def similarity_hint(similar):
361 def similarity_hint(similar):
363 # type: (List[bytes]) -> Optional[bytes]
362 # type: (List[bytes]) -> Optional[bytes]
364 from .i18n import _
363 from .i18n import _
365
364
366 if len(similar) == 1:
365 if len(similar) == 1:
367 return _(b"did you mean %s?") % similar[0]
366 return _(b"did you mean %s?") % similar[0]
368 elif similar:
367 elif similar:
369 ss = b", ".join(sorted(similar))
368 ss = b", ".join(sorted(similar))
370 return _(b"did you mean one of %s?") % ss
369 return _(b"did you mean one of %s?") % ss
371 else:
370 else:
372 return None
371 return None
373
372
374
373
375 class UnknownIdentifier(ParseError):
374 class UnknownIdentifier(ParseError):
376 """Exception raised when a {rev,file}set references an unknown identifier"""
375 """Exception raised when a {rev,file}set references an unknown identifier"""
377
376
378 def __init__(self, function, symbols):
377 def __init__(self, function, symbols):
379 # type: (bytes, Iterable[bytes]) -> None
378 # type: (bytes, Iterable[bytes]) -> None
380 from .i18n import _
379 from .i18n import _
381
380
382 similar = getsimilar(symbols, function)
381 similar = getsimilar(symbols, function)
383 hint = similarity_hint(similar)
382 hint = similarity_hint(similar)
384
383
385 ParseError.__init__(
384 ParseError.__init__(
386 self, _(b"unknown identifier: %s") % function, hint=hint
385 self, _(b"unknown identifier: %s") % function, hint=hint
387 )
386 )
388
387
389
388
390 class RepoError(Hint, Exception):
389 class RepoError(Hint, Exception):
391 __bytes__ = _tobytes
390 __bytes__ = _tobytes
392
391
393
392
394 class RepoLookupError(RepoError):
393 class RepoLookupError(RepoError):
395 pass
394 pass
396
395
397
396
398 class FilteredRepoLookupError(RepoLookupError):
397 class FilteredRepoLookupError(RepoLookupError):
399 pass
398 pass
400
399
401
400
402 class CapabilityError(RepoError):
401 class CapabilityError(RepoError):
403 pass
402 pass
404
403
405
404
406 class RequirementError(RepoError):
405 class RequirementError(RepoError):
407 """Exception raised if .hg/requires has an unknown entry."""
406 """Exception raised if .hg/requires has an unknown entry."""
408
407
409
408
410 class StdioError(IOError):
409 class StdioError(IOError):
411 """Raised if I/O to stdout or stderr fails"""
410 """Raised if I/O to stdout or stderr fails"""
412
411
413 def __init__(self, err):
412 def __init__(self, err):
414 # type: (IOError) -> None
413 # type: (IOError) -> None
415 IOError.__init__(self, err.errno, err.strerror)
414 IOError.__init__(self, err.errno, err.strerror)
416
415
417 # no __bytes__() because error message is derived from the standard IOError
416 # no __bytes__() because error message is derived from the standard IOError
418
417
419
418
420 class UnsupportedMergeRecords(Abort):
419 class UnsupportedMergeRecords(Abort):
421 def __init__(self, recordtypes):
420 def __init__(self, recordtypes):
422 # type: (Iterable[bytes]) -> None
421 # type: (Iterable[bytes]) -> None
423 from .i18n import _
422 from .i18n import _
424
423
425 self.recordtypes = sorted(recordtypes)
424 self.recordtypes = sorted(recordtypes)
426 s = b' '.join(self.recordtypes)
425 s = b' '.join(self.recordtypes)
427 Abort.__init__(
426 Abort.__init__(
428 self,
427 self,
429 _(b'unsupported merge state records: %s') % s,
428 _(b'unsupported merge state records: %s') % s,
430 hint=_(
429 hint=_(
431 b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
430 b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
432 b'more information'
431 b'more information'
433 ),
432 ),
434 )
433 )
435
434
436
435
437 class UnknownVersion(Abort):
436 class UnknownVersion(Abort):
438 """generic exception for aborting from an encounter with an unknown version"""
437 """generic exception for aborting from an encounter with an unknown version"""
439
438
440 def __init__(self, msg, hint=None, version=None):
439 def __init__(self, msg, hint=None, version=None):
441 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
440 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
442 self.version = version
441 self.version = version
443 super(UnknownVersion, self).__init__(msg, hint=hint)
442 super(UnknownVersion, self).__init__(msg, hint=hint)
444
443
445
444
446 class LockError(IOError):
445 class LockError(IOError):
447 def __init__(self, errno, strerror, filename, desc):
446 def __init__(self, errno, strerror, filename, desc):
448 # TODO: figure out if this should be bytes or str
447 # TODO: figure out if this should be bytes or str
449 # _type: (int, str, str, bytes) -> None
448 # _type: (int, str, str, bytes) -> None
450 IOError.__init__(self, errno, strerror, filename)
449 IOError.__init__(self, errno, strerror, filename)
451 self.desc = desc
450 self.desc = desc
452
451
453 # no __bytes__() because error message is derived from the standard IOError
452 # no __bytes__() because error message is derived from the standard IOError
454
453
455
454
456 class LockHeld(LockError):
455 class LockHeld(LockError):
457 def __init__(self, errno, filename, desc, locker):
456 def __init__(self, errno, filename, desc, locker):
458 LockError.__init__(self, errno, b'Lock held', filename, desc)
457 LockError.__init__(self, errno, b'Lock held', filename, desc)
459 self.locker = locker
458 self.locker = locker
460
459
461
460
462 class LockUnavailable(LockError):
461 class LockUnavailable(LockError):
463 pass
462 pass
464
463
465
464
466 # LockError is for errors while acquiring the lock -- this is unrelated
465 # LockError is for errors while acquiring the lock -- this is unrelated
467 class LockInheritanceContractViolation(RuntimeError):
466 class LockInheritanceContractViolation(RuntimeError):
468 __bytes__ = _tobytes
467 __bytes__ = _tobytes
469
468
470
469
471 class ResponseError(Exception):
470 class ResponseError(Exception):
472 """Raised to print an error with part of output and exit."""
471 """Raised to print an error with part of output and exit."""
473
472
474 __bytes__ = _tobytes
473 __bytes__ = _tobytes
475
474
476
475
477 # derived from KeyboardInterrupt to simplify some breakout code
476 # derived from KeyboardInterrupt to simplify some breakout code
478 class SignalInterrupt(KeyboardInterrupt):
477 class SignalInterrupt(KeyboardInterrupt):
479 """Exception raised on SIGTERM and SIGHUP."""
478 """Exception raised on SIGTERM and SIGHUP."""
480
479
481
480
482 class SignatureError(Exception):
481 class SignatureError(Exception):
483 __bytes__ = _tobytes
482 __bytes__ = _tobytes
484
483
485
484
486 class PushRaced(RuntimeError):
485 class PushRaced(RuntimeError):
487 """An exception raised during unbundling that indicate a push race"""
486 """An exception raised during unbundling that indicate a push race"""
488
487
489 __bytes__ = _tobytes
488 __bytes__ = _tobytes
490
489
491
490
492 class ProgrammingError(Hint, RuntimeError):
491 class ProgrammingError(Hint, RuntimeError):
493 """Raised if a mercurial (core or extension) developer made a mistake"""
492 """Raised if a mercurial (core or extension) developer made a mistake"""
494
493
495 def __init__(self, msg, *args, **kwargs):
494 def __init__(self, msg, *args, **kwargs):
496 # type: (AnyStr, Any, Any) -> None
495 # type: (AnyStr, Any, Any) -> None
497 # On Python 3, turn the message back into a string since this is
496 # On Python 3, turn the message back into a string since this is
498 # an internal-only error that won't be printed except in a
497 # an internal-only error that won't be printed except in a
499 # stack traces.
498 # stack traces.
500 msg = pycompat.sysstr(msg)
499 msg = pycompat.sysstr(msg)
501 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
500 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
502
501
503 __bytes__ = _tobytes
502 __bytes__ = _tobytes
504
503
505
504
506 class WdirUnsupported(Exception):
505 class WdirUnsupported(Exception):
507 """An exception which is raised when 'wdir()' is not supported"""
506 """An exception which is raised when 'wdir()' is not supported"""
508
507
509 __bytes__ = _tobytes
508 __bytes__ = _tobytes
510
509
511
510
512 # bundle2 related errors
511 # bundle2 related errors
513 class BundleValueError(ValueError):
512 class BundleValueError(ValueError):
514 """error raised when bundle2 cannot be processed"""
513 """error raised when bundle2 cannot be processed"""
515
514
516 __bytes__ = _tobytes
515 __bytes__ = _tobytes
517
516
518
517
519 class BundleUnknownFeatureError(BundleValueError):
518 class BundleUnknownFeatureError(BundleValueError):
520 def __init__(self, parttype=None, params=(), values=()):
519 def __init__(self, parttype=None, params=(), values=()):
521 self.parttype = parttype
520 self.parttype = parttype
522 self.params = params
521 self.params = params
523 self.values = values
522 self.values = values
524 if self.parttype is None:
523 if self.parttype is None:
525 msg = b'Stream Parameter'
524 msg = b'Stream Parameter'
526 else:
525 else:
527 msg = parttype
526 msg = parttype
528 entries = self.params
527 entries = self.params
529 if self.params and self.values:
528 if self.params and self.values:
530 assert len(self.params) == len(self.values)
529 assert len(self.params) == len(self.values)
531 entries = []
530 entries = []
532 for idx, par in enumerate(self.params):
531 for idx, par in enumerate(self.params):
533 val = self.values[idx]
532 val = self.values[idx]
534 if val is None:
533 if val is None:
535 entries.append(val)
534 entries.append(val)
536 else:
535 else:
537 entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
536 entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
538 if entries:
537 if entries:
539 msg = b'%s - %s' % (msg, b', '.join(entries))
538 msg = b'%s - %s' % (msg, b', '.join(entries))
540 ValueError.__init__(self, msg) # TODO: convert to str?
539 ValueError.__init__(self, msg) # TODO: convert to str?
541
540
542
541
543 class ReadOnlyPartError(RuntimeError):
542 class ReadOnlyPartError(RuntimeError):
544 """error raised when code tries to alter a part being generated"""
543 """error raised when code tries to alter a part being generated"""
545
544
546 __bytes__ = _tobytes
545 __bytes__ = _tobytes
547
546
548
547
549 class PushkeyFailed(Abort):
548 class PushkeyFailed(Abort):
550 """error raised when a pushkey part failed to update a value"""
549 """error raised when a pushkey part failed to update a value"""
551
550
552 def __init__(
551 def __init__(
553 self, partid, namespace=None, key=None, new=None, old=None, ret=None
552 self, partid, namespace=None, key=None, new=None, old=None, ret=None
554 ):
553 ):
555 self.partid = partid
554 self.partid = partid
556 self.namespace = namespace
555 self.namespace = namespace
557 self.key = key
556 self.key = key
558 self.new = new
557 self.new = new
559 self.old = old
558 self.old = old
560 self.ret = ret
559 self.ret = ret
561 # no i18n expected to be processed into a better message
560 # no i18n expected to be processed into a better message
562 Abort.__init__(
561 Abort.__init__(
563 self, b'failed to update value for "%s/%s"' % (namespace, key)
562 self, b'failed to update value for "%s/%s"' % (namespace, key)
564 )
563 )
565
564
566
565
567 class CensoredNodeError(StorageError):
566 class CensoredNodeError(StorageError):
568 """error raised when content verification fails on a censored node
567 """error raised when content verification fails on a censored node
569
568
570 Also contains the tombstone data substituted for the uncensored data.
569 Also contains the tombstone data substituted for the uncensored data.
571 """
570 """
572
571
573 def __init__(self, filename, node, tombstone):
572 def __init__(self, filename, node, tombstone):
574 # type: (bytes, bytes, bytes) -> None
573 # type: (bytes, bytes, bytes) -> None
575 from .node import short
574 from .node import short
576
575
577 StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
576 StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
578 self.tombstone = tombstone
577 self.tombstone = tombstone
579
578
580
579
581 class CensoredBaseError(StorageError):
580 class CensoredBaseError(StorageError):
582 """error raised when a delta is rejected because its base is censored
581 """error raised when a delta is rejected because its base is censored
583
582
584 A delta based on a censored revision must be formed as single patch
583 A delta based on a censored revision must be formed as single patch
585 operation which replaces the entire base with new content. This ensures
584 operation which replaces the entire base with new content. This ensures
586 the delta may be applied by clones which have not censored the base.
585 the delta may be applied by clones which have not censored the base.
587 """
586 """
588
587
589
588
590 class InvalidBundleSpecification(Exception):
589 class InvalidBundleSpecification(Exception):
591 """error raised when a bundle specification is invalid.
590 """error raised when a bundle specification is invalid.
592
591
593 This is used for syntax errors as opposed to support errors.
592 This is used for syntax errors as opposed to support errors.
594 """
593 """
595
594
596 __bytes__ = _tobytes
595 __bytes__ = _tobytes
597
596
598
597
599 class UnsupportedBundleSpecification(Exception):
598 class UnsupportedBundleSpecification(Exception):
600 """error raised when a bundle specification is not supported."""
599 """error raised when a bundle specification is not supported."""
601
600
602 __bytes__ = _tobytes
601 __bytes__ = _tobytes
603
602
604
603
605 class CorruptedState(Exception):
604 class CorruptedState(Exception):
606 """error raised when a command is not able to read its state from file"""
605 """error raised when a command is not able to read its state from file"""
607
606
608 __bytes__ = _tobytes
607 __bytes__ = _tobytes
609
608
610
609
611 class PeerTransportError(Abort):
610 class PeerTransportError(Abort):
612 """Transport-level I/O error when communicating with a peer repo."""
611 """Transport-level I/O error when communicating with a peer repo."""
613
612
614
613
615 class InMemoryMergeConflictsError(Exception):
614 class InMemoryMergeConflictsError(Exception):
616 """Exception raised when merge conflicts arose during an in-memory merge."""
615 """Exception raised when merge conflicts arose during an in-memory merge."""
617
616
618 __bytes__ = _tobytes
617 __bytes__ = _tobytes
619
618
620
619
621 class WireprotoCommandError(Exception):
620 class WireprotoCommandError(Exception):
622 """Represents an error during execution of a wire protocol command.
621 """Represents an error during execution of a wire protocol command.
623
622
624 Should only be thrown by wire protocol version 2 commands.
623 Should only be thrown by wire protocol version 2 commands.
625
624
626 The error is a formatter string and an optional iterable of arguments.
625 The error is a formatter string and an optional iterable of arguments.
627 """
626 """
628
627
629 def __init__(self, message, args=None):
628 def __init__(self, message, args=None):
630 # type: (bytes, Optional[Sequence[bytes]]) -> None
629 # type: (bytes, Optional[Sequence[bytes]]) -> None
631 self.message = message
630 self.message = message
632 self.messageargs = args
631 self.messageargs = args
General Comments 0
You need to be logged in to leave comments. Login now