13 |
13 |
14 from __future__ import absolute_import |
14 from __future__ import absolute_import |
15 |
15 |
16 # Do not import anything but pycompat here, please |
16 # Do not import anything but pycompat here, please |
17 from . import pycompat |
17 from . import pycompat |
|
18 |
18 |
19 |
19 def _tobytes(exc): |
20 def _tobytes(exc): |
20 """Byte-stringify exception in the same way as BaseException_str()""" |
21 """Byte-stringify exception in the same way as BaseException_str()""" |
21 if not exc.args: |
22 if not exc.args: |
22 return b'' |
23 return b'' |
23 if len(exc.args) == 1: |
24 if len(exc.args) == 1: |
24 return pycompat.bytestr(exc.args[0]) |
25 return pycompat.bytestr(exc.args[0]) |
25 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) |
26 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) |
26 |
27 |
|
28 |
27 class Hint(object): |
29 class Hint(object): |
28 """Mix-in to provide a hint of an error |
30 """Mix-in to provide a hint of an error |
29 |
31 |
30 This should come first in the inheritance list to consume a hint and |
32 This should come first in the inheritance list to consume a hint and |
31 pass remaining arguments to the exception class. |
33 pass remaining arguments to the exception class. |
32 """ |
34 """ |
|
35 |
33 def __init__(self, *args, **kw): |
36 def __init__(self, *args, **kw): |
34 self.hint = kw.pop(r'hint', None) |
37 self.hint = kw.pop(r'hint', None) |
35 super(Hint, self).__init__(*args, **kw) |
38 super(Hint, self).__init__(*args, **kw) |
36 |
39 |
|
40 |
37 class StorageError(Hint, Exception): |
41 class StorageError(Hint, Exception): |
38 """Raised when an error occurs in a storage layer. |
42 """Raised when an error occurs in a storage layer. |
39 |
43 |
40 Usually subclassed by a storage-specific exception. |
44 Usually subclassed by a storage-specific exception. |
41 """ |
45 """ |
42 __bytes__ = _tobytes |
46 |
|
47 __bytes__ = _tobytes |
|
48 |
43 |
49 |
44 class RevlogError(StorageError): |
50 class RevlogError(StorageError): |
45 __bytes__ = _tobytes |
51 __bytes__ = _tobytes |
46 |
52 |
|
53 |
47 class SidedataHashError(RevlogError): |
54 class SidedataHashError(RevlogError): |
48 |
|
49 def __init__(self, key, expected, got): |
55 def __init__(self, key, expected, got): |
50 self.sidedatakey = key |
56 self.sidedatakey = key |
51 self.expecteddigest = expected |
57 self.expecteddigest = expected |
52 self.actualdigest = got |
58 self.actualdigest = got |
53 |
59 |
|
60 |
54 class FilteredIndexError(IndexError): |
61 class FilteredIndexError(IndexError): |
55 __bytes__ = _tobytes |
62 __bytes__ = _tobytes |
|
63 |
56 |
64 |
57 class LookupError(RevlogError, KeyError): |
65 class LookupError(RevlogError, KeyError): |
58 def __init__(self, name, index, message): |
66 def __init__(self, name, index, message): |
59 self.name = name |
67 self.name = name |
60 self.index = index |
68 self.index = index |
61 # this can't be called 'message' because at least some installs of |
69 # this can't be called 'message' because at least some installs of |
62 # Python 2.6+ complain about the 'message' property being deprecated |
70 # Python 2.6+ complain about the 'message' property being deprecated |
63 self.lookupmessage = message |
71 self.lookupmessage = message |
64 if isinstance(name, bytes) and len(name) == 20: |
72 if isinstance(name, bytes) and len(name) == 20: |
65 from .node import short |
73 from .node import short |
|
74 |
66 name = short(name) |
75 name = short(name) |
67 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) |
76 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) |
68 |
77 |
69 def __bytes__(self): |
78 def __bytes__(self): |
70 return RevlogError.__bytes__(self) |
79 return RevlogError.__bytes__(self) |
71 |
80 |
72 def __str__(self): |
81 def __str__(self): |
73 return RevlogError.__str__(self) |
82 return RevlogError.__str__(self) |
74 |
83 |
|
84 |
75 class AmbiguousPrefixLookupError(LookupError): |
85 class AmbiguousPrefixLookupError(LookupError): |
76 pass |
86 pass |
77 |
87 |
|
88 |
78 class FilteredLookupError(LookupError): |
89 class FilteredLookupError(LookupError): |
79 pass |
90 pass |
80 |
91 |
|
92 |
81 class ManifestLookupError(LookupError): |
93 class ManifestLookupError(LookupError): |
82 pass |
94 pass |
|
95 |
83 |
96 |
84 class CommandError(Exception): |
97 class CommandError(Exception): |
85 """Exception raised on errors in parsing the command line.""" |
98 """Exception raised on errors in parsing the command line.""" |
86 __bytes__ = _tobytes |
99 |
|
100 __bytes__ = _tobytes |
|
101 |
87 |
102 |
88 class InterventionRequired(Hint, Exception): |
103 class InterventionRequired(Hint, Exception): |
89 """Exception raised when a command requires human intervention.""" |
104 """Exception raised when a command requires human intervention.""" |
90 __bytes__ = _tobytes |
105 |
|
106 __bytes__ = _tobytes |
|
107 |
91 |
108 |
92 class Abort(Hint, Exception): |
109 class Abort(Hint, Exception): |
93 """Raised if a command needs to print an error and exit.""" |
110 """Raised if a command needs to print an error and exit.""" |
94 __bytes__ = _tobytes |
111 |
|
112 __bytes__ = _tobytes |
|
113 |
95 |
114 |
96 class HookLoadError(Abort): |
115 class HookLoadError(Abort): |
97 """raised when loading a hook fails, aborting an operation |
116 """raised when loading a hook fails, aborting an operation |
98 |
117 |
99 Exists to allow more specialized catching.""" |
118 Exists to allow more specialized catching.""" |
100 |
119 |
|
120 |
101 class HookAbort(Abort): |
121 class HookAbort(Abort): |
102 """raised when a validation hook fails, aborting an operation |
122 """raised when a validation hook fails, aborting an operation |
103 |
123 |
104 Exists to allow more specialized catching.""" |
124 Exists to allow more specialized catching.""" |
105 |
125 |
|
126 |
106 class ConfigError(Abort): |
127 class ConfigError(Abort): |
107 """Exception raised when parsing config files""" |
128 """Exception raised when parsing config files""" |
108 |
129 |
|
130 |
109 class UpdateAbort(Abort): |
131 class UpdateAbort(Abort): |
110 """Raised when an update is aborted for destination issue""" |
132 """Raised when an update is aborted for destination issue""" |
111 |
133 |
|
134 |
112 class MergeDestAbort(Abort): |
135 class MergeDestAbort(Abort): |
113 """Raised when an update is aborted for destination issues""" |
136 """Raised when an update is aborted for destination issues""" |
114 |
137 |
|
138 |
115 class NoMergeDestAbort(MergeDestAbort): |
139 class NoMergeDestAbort(MergeDestAbort): |
116 """Raised when an update is aborted because there is nothing to merge""" |
140 """Raised when an update is aborted because there is nothing to merge""" |
117 |
141 |
|
142 |
118 class ManyMergeDestAbort(MergeDestAbort): |
143 class ManyMergeDestAbort(MergeDestAbort): |
119 """Raised when an update is aborted because destination is ambiguous""" |
144 """Raised when an update is aborted because destination is ambiguous""" |
120 |
145 |
|
146 |
121 class ResponseExpected(Abort): |
147 class ResponseExpected(Abort): |
122 """Raised when an EOF is received for a prompt""" |
148 """Raised when an EOF is received for a prompt""" |
|
149 |
123 def __init__(self): |
150 def __init__(self): |
124 from .i18n import _ |
151 from .i18n import _ |
|
152 |
125 Abort.__init__(self, _('response expected')) |
153 Abort.__init__(self, _('response expected')) |
|
154 |
126 |
155 |
127 class OutOfBandError(Hint, Exception): |
156 class OutOfBandError(Hint, Exception): |
128 """Exception raised when a remote repo reports failure""" |
157 """Exception raised when a remote repo reports failure""" |
129 __bytes__ = _tobytes |
158 |
|
159 __bytes__ = _tobytes |
|
160 |
130 |
161 |
131 class ParseError(Hint, Exception): |
162 class ParseError(Hint, Exception): |
132 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" |
163 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" |
133 __bytes__ = _tobytes |
164 |
|
165 __bytes__ = _tobytes |
|
166 |
134 |
167 |
135 class PatchError(Exception): |
168 class PatchError(Exception): |
136 __bytes__ = _tobytes |
169 __bytes__ = _tobytes |
|
170 |
137 |
171 |
138 class UnknownIdentifier(ParseError): |
172 class UnknownIdentifier(ParseError): |
139 """Exception raised when a {rev,file}set references an unknown identifier""" |
173 """Exception raised when a {rev,file}set references an unknown identifier""" |
140 |
174 |
141 def __init__(self, function, symbols): |
175 def __init__(self, function, symbols): |
142 from .i18n import _ |
176 from .i18n import _ |
|
177 |
143 ParseError.__init__(self, _("unknown identifier: %s") % function) |
178 ParseError.__init__(self, _("unknown identifier: %s") % function) |
144 self.function = function |
179 self.function = function |
145 self.symbols = symbols |
180 self.symbols = symbols |
146 |
181 |
|
182 |
147 class RepoError(Hint, Exception): |
183 class RepoError(Hint, Exception): |
148 __bytes__ = _tobytes |
184 __bytes__ = _tobytes |
149 |
185 |
|
186 |
150 class RepoLookupError(RepoError): |
187 class RepoLookupError(RepoError): |
151 pass |
188 pass |
152 |
189 |
|
190 |
153 class FilteredRepoLookupError(RepoLookupError): |
191 class FilteredRepoLookupError(RepoLookupError): |
154 pass |
192 pass |
155 |
193 |
|
194 |
156 class CapabilityError(RepoError): |
195 class CapabilityError(RepoError): |
157 pass |
196 pass |
|
197 |
158 |
198 |
159 class RequirementError(RepoError): |
199 class RequirementError(RepoError): |
160 """Exception raised if .hg/requires has an unknown entry.""" |
200 """Exception raised if .hg/requires has an unknown entry.""" |
161 |
201 |
|
202 |
162 class StdioError(IOError): |
203 class StdioError(IOError): |
163 """Raised if I/O to stdout or stderr fails""" |
204 """Raised if I/O to stdout or stderr fails""" |
164 |
205 |
165 def __init__(self, err): |
206 def __init__(self, err): |
166 IOError.__init__(self, err.errno, err.strerror) |
207 IOError.__init__(self, err.errno, err.strerror) |
167 |
208 |
168 # no __bytes__() because error message is derived from the standard IOError |
209 # no __bytes__() because error message is derived from the standard IOError |
|
210 |
169 |
211 |
170 class UnsupportedMergeRecords(Abort): |
212 class UnsupportedMergeRecords(Abort): |
171 def __init__(self, recordtypes): |
213 def __init__(self, recordtypes): |
172 from .i18n import _ |
214 from .i18n import _ |
|
215 |
173 self.recordtypes = sorted(recordtypes) |
216 self.recordtypes = sorted(recordtypes) |
174 s = ' '.join(self.recordtypes) |
217 s = ' '.join(self.recordtypes) |
175 Abort.__init__( |
218 Abort.__init__( |
176 self, _('unsupported merge state records: %s') % s, |
219 self, |
177 hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for ' |
220 _('unsupported merge state records: %s') % s, |
178 'more information')) |
221 hint=_( |
|
222 'see https://mercurial-scm.org/wiki/MergeStateRecords for ' |
|
223 'more information' |
|
224 ), |
|
225 ) |
|
226 |
179 |
227 |
180 class UnknownVersion(Abort): |
228 class UnknownVersion(Abort): |
181 """generic exception for aborting from an encounter with an unknown version |
229 """generic exception for aborting from an encounter with an unknown version |
182 """ |
230 """ |
183 |
231 |
184 def __init__(self, msg, hint=None, version=None): |
232 def __init__(self, msg, hint=None, version=None): |
185 self.version = version |
233 self.version = version |
186 super(UnknownVersion, self).__init__(msg, hint=hint) |
234 super(UnknownVersion, self).__init__(msg, hint=hint) |
|
235 |
187 |
236 |
188 class LockError(IOError): |
237 class LockError(IOError): |
189 def __init__(self, errno, strerror, filename, desc): |
238 def __init__(self, errno, strerror, filename, desc): |
190 IOError.__init__(self, errno, strerror, filename) |
239 IOError.__init__(self, errno, strerror, filename) |
191 self.desc = desc |
240 self.desc = desc |
192 |
241 |
193 # no __bytes__() because error message is derived from the standard IOError |
242 # no __bytes__() because error message is derived from the standard IOError |
194 |
243 |
|
244 |
195 class LockHeld(LockError): |
245 class LockHeld(LockError): |
196 def __init__(self, errno, filename, desc, locker): |
246 def __init__(self, errno, filename, desc, locker): |
197 LockError.__init__(self, errno, 'Lock held', filename, desc) |
247 LockError.__init__(self, errno, 'Lock held', filename, desc) |
198 self.locker = locker |
248 self.locker = locker |
199 |
249 |
|
250 |
200 class LockUnavailable(LockError): |
251 class LockUnavailable(LockError): |
201 pass |
252 pass |
|
253 |
202 |
254 |
203 # LockError is for errors while acquiring the lock -- this is unrelated |
255 # LockError is for errors while acquiring the lock -- this is unrelated |
204 class LockInheritanceContractViolation(RuntimeError): |
256 class LockInheritanceContractViolation(RuntimeError): |
205 __bytes__ = _tobytes |
257 __bytes__ = _tobytes |
206 |
258 |
|
259 |
207 class ResponseError(Exception): |
260 class ResponseError(Exception): |
208 """Raised to print an error with part of output and exit.""" |
261 """Raised to print an error with part of output and exit.""" |
209 __bytes__ = _tobytes |
262 |
|
263 __bytes__ = _tobytes |
|
264 |
210 |
265 |
211 class UnknownCommand(Exception): |
266 class UnknownCommand(Exception): |
212 """Exception raised if command is not in the command table.""" |
267 """Exception raised if command is not in the command table.""" |
213 __bytes__ = _tobytes |
268 |
|
269 __bytes__ = _tobytes |
|
270 |
214 |
271 |
215 class AmbiguousCommand(Exception): |
272 class AmbiguousCommand(Exception): |
216 """Exception raised if command shortcut matches more than one command.""" |
273 """Exception raised if command shortcut matches more than one command.""" |
217 __bytes__ = _tobytes |
274 |
|
275 __bytes__ = _tobytes |
|
276 |
218 |
277 |
219 # derived from KeyboardInterrupt to simplify some breakout code |
278 # derived from KeyboardInterrupt to simplify some breakout code |
220 class SignalInterrupt(KeyboardInterrupt): |
279 class SignalInterrupt(KeyboardInterrupt): |
221 """Exception raised on SIGTERM and SIGHUP.""" |
280 """Exception raised on SIGTERM and SIGHUP.""" |
222 |
281 |
|
282 |
223 class SignatureError(Exception): |
283 class SignatureError(Exception): |
224 __bytes__ = _tobytes |
284 __bytes__ = _tobytes |
|
285 |
225 |
286 |
226 class PushRaced(RuntimeError): |
287 class PushRaced(RuntimeError): |
227 """An exception raised during unbundling that indicate a push race""" |
288 """An exception raised during unbundling that indicate a push race""" |
228 __bytes__ = _tobytes |
289 |
|
290 __bytes__ = _tobytes |
|
291 |
229 |
292 |
230 class ProgrammingError(Hint, RuntimeError): |
293 class ProgrammingError(Hint, RuntimeError): |
231 """Raised if a mercurial (core or extension) developer made a mistake""" |
294 """Raised if a mercurial (core or extension) developer made a mistake""" |
232 |
295 |
233 def __init__(self, msg, *args, **kwargs): |
296 def __init__(self, msg, *args, **kwargs): |
269 entries.append("%s=%r" % (par, pycompat.maybebytestr(val))) |
337 entries.append("%s=%r" % (par, pycompat.maybebytestr(val))) |
270 if entries: |
338 if entries: |
271 msg = '%s - %s' % (msg, ', '.join(entries)) |
339 msg = '%s - %s' % (msg, ', '.join(entries)) |
272 ValueError.__init__(self, msg) |
340 ValueError.__init__(self, msg) |
273 |
341 |
|
342 |
274 class ReadOnlyPartError(RuntimeError): |
343 class ReadOnlyPartError(RuntimeError): |
275 """error raised when code tries to alter a part being generated""" |
344 """error raised when code tries to alter a part being generated""" |
276 __bytes__ = _tobytes |
345 |
|
346 __bytes__ = _tobytes |
|
347 |
277 |
348 |
278 class PushkeyFailed(Abort): |
349 class PushkeyFailed(Abort): |
279 """error raised when a pushkey part failed to update a value""" |
350 """error raised when a pushkey part failed to update a value""" |
280 |
351 |
281 def __init__(self, partid, namespace=None, key=None, new=None, old=None, |
352 def __init__( |
282 ret=None): |
353 self, partid, namespace=None, key=None, new=None, old=None, ret=None |
|
354 ): |
283 self.partid = partid |
355 self.partid = partid |
284 self.namespace = namespace |
356 self.namespace = namespace |
285 self.key = key |
357 self.key = key |
286 self.new = new |
358 self.new = new |
287 self.old = old |
359 self.old = old |
288 self.ret = ret |
360 self.ret = ret |
289 # no i18n expected to be processed into a better message |
361 # no i18n expected to be processed into a better message |
290 Abort.__init__(self, 'failed to update value for "%s/%s"' |
362 Abort.__init__( |
291 % (namespace, key)) |
363 self, 'failed to update value for "%s/%s"' % (namespace, key) |
|
364 ) |
|
365 |
292 |
366 |
293 class CensoredNodeError(StorageError): |
367 class CensoredNodeError(StorageError): |
294 """error raised when content verification fails on a censored node |
368 """error raised when content verification fails on a censored node |
295 |
369 |
296 Also contains the tombstone data substituted for the uncensored data. |
370 Also contains the tombstone data substituted for the uncensored data. |
297 """ |
371 """ |
298 |
372 |
299 def __init__(self, filename, node, tombstone): |
373 def __init__(self, filename, node, tombstone): |
300 from .node import short |
374 from .node import short |
|
375 |
301 StorageError.__init__(self, '%s:%s' % (filename, short(node))) |
376 StorageError.__init__(self, '%s:%s' % (filename, short(node))) |
302 self.tombstone = tombstone |
377 self.tombstone = tombstone |
|
378 |
303 |
379 |
304 class CensoredBaseError(StorageError): |
380 class CensoredBaseError(StorageError): |
305 """error raised when a delta is rejected because its base is censored |
381 """error raised when a delta is rejected because its base is censored |
306 |
382 |
307 A delta based on a censored revision must be formed as single patch |
383 A delta based on a censored revision must be formed as single patch |
308 operation which replaces the entire base with new content. This ensures |
384 operation which replaces the entire base with new content. This ensures |
309 the delta may be applied by clones which have not censored the base. |
385 the delta may be applied by clones which have not censored the base. |
310 """ |
386 """ |
311 |
387 |
|
388 |
312 class InvalidBundleSpecification(Exception): |
389 class InvalidBundleSpecification(Exception): |
313 """error raised when a bundle specification is invalid. |
390 """error raised when a bundle specification is invalid. |
314 |
391 |
315 This is used for syntax errors as opposed to support errors. |
392 This is used for syntax errors as opposed to support errors. |
316 """ |
393 """ |
317 __bytes__ = _tobytes |
394 |
|
395 __bytes__ = _tobytes |
|
396 |
318 |
397 |
319 class UnsupportedBundleSpecification(Exception): |
398 class UnsupportedBundleSpecification(Exception): |
320 """error raised when a bundle specification is not supported.""" |
399 """error raised when a bundle specification is not supported.""" |
321 __bytes__ = _tobytes |
400 |
|
401 __bytes__ = _tobytes |
|
402 |
322 |
403 |
323 class CorruptedState(Exception): |
404 class CorruptedState(Exception): |
324 """error raised when a command is not able to read its state from file""" |
405 """error raised when a command is not able to read its state from file""" |
325 __bytes__ = _tobytes |
406 |
|
407 __bytes__ = _tobytes |
|
408 |
326 |
409 |
327 class PeerTransportError(Abort): |
410 class PeerTransportError(Abort): |
328 """Transport-level I/O error when communicating with a peer repo.""" |
411 """Transport-level I/O error when communicating with a peer repo.""" |
329 |
412 |
|
413 |
330 class InMemoryMergeConflictsError(Exception): |
414 class InMemoryMergeConflictsError(Exception): |
331 """Exception raised when merge conflicts arose during an in-memory merge.""" |
415 """Exception raised when merge conflicts arose during an in-memory merge.""" |
332 __bytes__ = _tobytes |
416 |
|
417 __bytes__ = _tobytes |
|
418 |
333 |
419 |
334 class WireprotoCommandError(Exception): |
420 class WireprotoCommandError(Exception): |
335 """Represents an error during execution of a wire protocol command. |
421 """Represents an error during execution of a wire protocol command. |
336 |
422 |
337 Should only be thrown by wire protocol version 2 commands. |
423 Should only be thrown by wire protocol version 2 commands. |
338 |
424 |
339 The error is a formatter string and an optional iterable of arguments. |
425 The error is a formatter string and an optional iterable of arguments. |
340 """ |
426 """ |
|
427 |
341 def __init__(self, message, args=None): |
428 def __init__(self, message, args=None): |
342 self.message = message |
429 self.message = message |
343 self.messageargs = args |
430 self.messageargs = args |