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