17
17
"""Exceptions for bzr, and reporting of them.
19
There are 3 different classes of error:
21
* KeyboardInterrupt, and OSError with EPIPE - the program terminates
22
with an appropriate short message
24
* User errors, indicating a problem caused by the user such as a bad URL.
25
These are printed in a short form.
27
* Internal unexpected errors, including most Python builtin errors
28
and some raised from inside bzr. These are printed with a full
29
traceback and an invitation to report the bug.
19
31
Exceptions are caught at a high level to report errors to the user, and
20
32
might also be caught inside the program. Therefore it needs to be
21
33
possible to convert them to a meaningful string, and also for them to be
35
47
... print sys.exc_type
36
48
... print sys.exc_value
37
... path = getattr(sys.exc_value, 'path')
49
... path = getattr(sys.exc_value, 'path', None)
38
50
... if path is not None:
40
52
bzrlib.errors.NotBranchError
46
58
* create a new exception class for any class of error that can be
47
usefully distinguished.
49
* the printable form of an exception is generated by the base class
52
Exception strings should start with a capital letter and not have a final
59
usefully distinguished. If no callers are likely to want to catch
60
one but not another, don't worry about them.
62
* the __str__ method should generate something useful; BzrError provides
63
a good default implementation
65
Exception strings should start with a capital letter and should not have a
56
69
from warnings import warn
71
from bzrlib.patches import (PatchSyntax,
58
78
# based on Scott James Remnant's hct error classes
60
80
# TODO: is there any value in providing the .args field used by standard
68
88
# TODO: Convert all the other error classes here to BzrNewError, and eliminate
91
# TODO: The pattern (from hct) of using classes docstrings as message
92
# templates is cute but maybe not such a great idea - perhaps should have a
93
# separate static message_template.
72
96
class BzrError(StandardError):
73
100
def __str__(self):
74
101
# XXX: Should we show the exception class in
75
102
# exceptions that don't provide their own message?
108
135
class BzrCheckError(BzrNewError):
109
136
"""Internal check failed: %(message)s"""
138
is_user_error = False
111
140
def __init__(self, message):
112
141
BzrNewError.__init__(self)
113
142
self.message = message
116
145
class InvalidEntryName(BzrNewError):
117
146
"""Invalid entry name: %(name)s"""
148
is_user_error = False
118
150
def __init__(self, name):
119
151
BzrNewError.__init__(self)
130
162
class InvalidRevisionId(BzrNewError):
131
163
"""Invalid revision-id {%(revision_id)s} in %(branch)s"""
132
164
def __init__(self, revision_id, branch):
165
# branch can be any string or object with __str__ defined
133
166
BzrNewError.__init__(self)
134
167
self.revision_id = revision_id
135
168
self.branch = branch
138
171
class NoWorkingTree(BzrNewError):
139
"""No WorkingTree exists for %s(base)."""
172
"""No WorkingTree exists for %(base)s."""
141
174
def __init__(self, base):
142
175
BzrNewError.__init__(self)
146
179
class NotLocalUrl(BzrNewError):
147
"""%s(url) is not a local path."""
180
"""%(url)s is not a local path."""
149
182
def __init__(self, url):
150
183
BzrNewError.__init__(self)
154
class BzrCommandError(BzrError):
155
# Error from malformed user command
156
# This is being misused as a generic exception
157
# pleae subclass. RBC 20051030
187
class BzrCommandError(BzrNewError):
188
"""Error from user command"""
192
# Error from malformed user command; please avoid raising this as a
193
# generic exception not caused by user input.
159
195
# I think it's a waste of effort to differentiate between errors that
160
196
# are not intended to be caught anyway. UI code need not subclass
161
197
# BzrCommandError, and non-UI code should not throw a subclass of
162
198
# BzrCommandError. ADHB 20051211
199
def __init__(self, msg):
163
202
def __str__(self):
167
206
class BzrOptionError(BzrCommandError):
168
"""Some missing or otherwise incorrect option was supplied."""
207
"""Error in command line options"""
171
class StrictCommitFailed(Exception):
172
"""Commit refused because there are unknowns in the tree."""
210
class StrictCommitFailed(BzrNewError):
211
"""Commit refused because there are unknown files in the tree"""
214
# XXX: Should be unified with TransportError; they seem to represent the
175
216
class PathError(BzrNewError):
176
217
"""Generic path error: %(path)r%(extra)s)"""
204
245
"""Permission denied: %(path)r%(extra)s"""
248
class InvalidURL(PathError):
249
"""Invalid url supplied to transport: %(path)r%(extra)s"""
252
class InvalidURLJoin(PathError):
253
"""Invalid URL join request: %(args)s%(extra)s"""
255
def __init__(self, msg, base, args):
256
PathError.__init__(self, base, msg)
258
self.args.extend(args)
207
261
class PathNotChild(BzrNewError):
208
262
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
264
is_user_error = False
209
266
def __init__(self, path, base, extra=None):
210
267
BzrNewError.__init__(self)
276
# TODO: This is given a URL; we try to unescape it but doing that from inside
277
# the exception object is a bit undesirable.
278
# TODO: Probably this behavior of should be a common superclass
219
279
class NotBranchError(PathError):
220
280
"""Not a branch: %(path)s"""
282
def __init__(self, path):
283
import bzrlib.urlutils as urlutils
284
self.path = urlutils.unescape_for_display(path, 'ascii')
223
287
class AlreadyBranchError(PathError):
224
"""Already a branch: %(path)s. Use `bzr checkout` to build a working tree."""
288
"""Already a branch: %(path)s."""
291
class BranchExistsWithoutWorkingTree(PathError):
292
"""Directory contains a branch, but no working tree \
293
(use bzr checkout if you wish to build a working tree): %(path)s"""
227
296
class NoRepositoryPresent(BzrNewError):
228
"""Not repository present: %(path)r"""
297
"""No repository present: %(path)r"""
229
298
def __init__(self, bzrdir):
230
299
BzrNewError.__init__(self)
231
300
self.path = bzrdir.transport.clone('..').base
244
class UnsupportedFormatError(BzrError):
245
"""Specified path is a bzr branch that we recognize but cannot read."""
247
return 'unsupported branch format: %s' % self.args[0]
250
class UnknownFormatError(BzrError):
251
"""Specified path is a bzr branch whose format we do not recognize."""
253
return 'unknown branch format: %s' % self.args[0]
313
class UnsupportedFormatError(BzrNewError):
314
"""Unsupported branch format: %(format)s"""
317
class UnknownFormatError(BzrNewError):
318
"""Unknown branch format: %(format)r"""
256
321
class IncompatibleFormat(BzrNewError):
280
345
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
283
class BadFileKindError(BzrError):
284
"""Specified file is of a kind that cannot be added.
286
(For example a symlink or device file.)"""
289
class ForbiddenFileError(BzrError):
290
"""Cannot operate on a file because it is a control file."""
348
class PathsDoNotExist(BzrNewError):
349
"""Path(s) do not exist: %(paths_as_string)s"""
351
# used when reporting that paths are neither versioned nor in the working
354
def __init__(self, paths):
356
from bzrlib.osutils import quotefn
357
BzrNewError.__init__(self)
359
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
362
class BadFileKindError(BzrNewError):
363
"""Cannot operate on %(filename)s of unsupported kind %(kind)s"""
366
class ForbiddenControlFileError(BzrNewError):
367
"""Cannot operate on %(filename)s because it is a control file"""
293
370
class LockError(BzrNewError):
326
403
class ObjectNotLocked(LockError):
327
404
"""%(obj)r is not locked"""
406
is_user_error = False
328
408
# this can indicate that any particular object is not locked; see also
329
409
# LockNotHeld which means that a particular *lock* object is not held by
330
410
# the caller -- perhaps they should be unified.
392
472
"""Commit refused because there are unknowns in the tree."""
395
class NoSuchRevision(BzrError):
475
class NoSuchRevision(BzrNewError):
476
"""Branch %(branch)s has no revision %(revision)s"""
478
is_user_error = False
396
480
def __init__(self, branch, revision):
397
481
self.branch = branch
398
482
self.revision = revision
399
msg = "Branch %s has no revision %s" % (branch, revision)
400
BzrError.__init__(self, msg)
403
485
class HistoryMissing(BzrError):
408
490
% (branch, object_type, object_id))
411
class DivergedBranches(BzrError):
493
class DivergedBranches(BzrNewError):
494
"These branches have diverged. Use the merge command to reconcile them."""
413
498
def __init__(self, branch1, branch2):
414
BzrError.__init__(self, "These branches have diverged. Try merge.")
415
499
self.branch1 = branch1
416
500
self.branch2 = branch2
419
class UnrelatedBranches(BzrCommandError):
421
msg = "Branches have no common ancestor, and no base revision"\
423
BzrCommandError.__init__(self, msg)
426
class NoCommonAncestor(BzrError):
503
class UnrelatedBranches(BzrNewError):
504
"Branches have no common ancestor, and no merge base revision was specified."
509
class NoCommonAncestor(BzrNewError):
510
"Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
427
512
def __init__(self, revision_a, revision_b):
428
msg = "Revisions have no common ancestor: %s %s." \
429
% (revision_a, revision_b)
430
BzrError.__init__(self, msg)
513
self.revision_a = revision_a
514
self.revision_b = revision_b
433
517
class NoCommonRoot(BzrError):
458
542
def __init__(self, bases):
459
543
warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
460
544
DeprecationWarning)
461
msg = "The correct base is unclear, becase %s are all equally close" %\
545
msg = "The correct base is unclear, because %s are all equally close" %\
463
547
BzrError.__init__(self, msg)
464
548
self.bases = bases
801
class NoBundleFound(BzrNewError):
802
"""No bundle was found in %(filename)s"""
803
def __init__(self, filename):
804
BzrNewError.__init__(self)
805
self.filename = filename
808
class BundleNotSupported(BzrNewError):
809
"""Unable to handle bundle version %(version)s: %(msg)s"""
810
def __init__(self, version, msg):
811
BzrNewError.__init__(self)
812
self.version = version
717
816
class MissingText(BzrNewError):
718
817
"""Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
764
863
"""Parameter $(param)s is required but not present."""
866
class BzrBadParameterUnicode(BzrBadParameter):
867
"""Parameter %(param)s is unicode but only byte-strings are permitted."""
870
class BzrBadParameterContainsNewline(BzrBadParameter):
871
"""Parameter %(param)s contains a newline."""
767
874
class DependencyNotPresent(BzrNewError):
768
875
"""Unable to import library "%(library)s": %(error)s"""
786
893
self.format = format
896
class NoDiff(BzrNewError):
897
"""Diff is not installed on this machine: %(msg)s"""
899
def __init__(self, msg):
900
super(NoDiff, self).__init__(msg=msg)
789
903
class NoDiff3(BzrNewError):
790
904
"""Diff3 is not installed on this machine."""
857
971
self.method = method
858
972
self.mname = method.__name__
859
973
self.tname = type(method_self).__name__
976
class BinaryFile(BzrNewError):
977
"""File is binary but should be text."""
980
class IllegalPath(BzrNewError):
981
"""The path %(path)s is not permitted on this platform"""
983
def __init__(self, path):
984
BzrNewError.__init__(self)
988
class TestamentMismatch(BzrNewError):
989
"""Testament did not match expected value.
990
For revision_id {%(revision_id)s}, expected {%(expected)s}, measured
993
def __init__(self, revision_id, expected, measured):
994
self.revision_id = revision_id
995
self.expected = expected
996
self.measured = measured
999
class NotABundle(BzrNewError):
1000
"""Not a bzr revision-bundle: %(text)r"""
1002
def __init__(self, text):
1006
class BadBundle(Exception): pass
1009
class MalformedHeader(BadBundle): pass
1012
class MalformedPatches(BadBundle): pass
1015
class MalformedFooter(BadBundle): pass