1
1
# Copyright (C) 2005, 2006 Canonical
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
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
111
127
def __str__(self):
113
return self.__doc__ % self.__dict__
114
except (NameError, ValueError, KeyError), e:
115
return 'Unprintable exception %s: %s' \
116
% (self.__class__.__name__, str(e))
129
# __str__() should always return a 'str' object
130
# never a 'unicode' object.
131
s = self.__doc__ % self.__dict__
132
if isinstance(s, unicode):
133
return s.encode('utf8')
135
except (TypeError, NameError, ValueError, KeyError), e:
136
return 'Unprintable exception %s(%r): %s' \
137
% (self.__class__.__name__,
138
self.__dict__, str(e))
141
class AlreadyBuilding(BzrNewError):
142
"""The tree builder is already building a tree."""
119
145
class BzrCheckError(BzrNewError):
120
146
"""Internal check failed: %(message)s"""
148
is_user_error = False
122
150
def __init__(self, message):
123
151
BzrNewError.__init__(self)
124
152
self.message = message
166
class BzrCommandError(BzrError):
167
# Error from malformed user command
168
# This is being misused as a generic exception
169
# please subclass. RBC 20051030
211
class BzrCommandError(BzrNewError):
212
"""Error from user command"""
216
# Error from malformed user command; please avoid raising this as a
217
# generic exception not caused by user input.
171
219
# I think it's a waste of effort to differentiate between errors that
172
220
# are not intended to be caught anyway. UI code need not subclass
173
221
# BzrCommandError, and non-UI code should not throw a subclass of
174
222
# BzrCommandError. ADHB 20051211
223
def __init__(self, msg):
224
# Object.__str__() must return a real string
225
# returning a Unicode string is a python error.
226
if isinstance(msg, unicode):
227
self.msg = msg.encode('utf8')
175
231
def __str__(self):
179
235
class BzrOptionError(BzrCommandError):
180
"""Some missing or otherwise incorrect option was supplied."""
236
"""Error in command line options"""
183
class StrictCommitFailed(Exception):
184
"""Commit refused because there are unknowns in the tree."""
239
class StrictCommitFailed(BzrNewError):
240
"""Commit refused because there are unknown files in the tree"""
187
243
# XXX: Should be unified with TransportError; they seem to represent the
231
287
self.args.extend(args)
290
class UnsupportedProtocol(PathError):
291
"""Unsupported protocol for url "%(path)s"%(extra)s"""
293
def __init__(self, url, extra):
294
PathError.__init__(self, url, extra=extra)
297
class ShortReadvError(PathError):
298
"""readv() read %(actual)s bytes rather than %(length)s bytes at %(offset)s for %(path)s%(extra)s"""
300
is_user_error = False
302
def __init__(self, path, offset, length, actual, extra=None):
303
PathError.__init__(self, path, extra=extra)
234
309
class PathNotChild(BzrNewError):
235
310
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
312
is_user_error = False
236
314
def __init__(self, path, base, extra=None):
237
315
BzrNewError.__init__(self)
263
345
(use bzr checkout if you wish to build a working tree): %(path)s"""
348
class AtomicFileAlreadyClosed(PathError):
349
"""'%(function)s' called on an AtomicFile after it was closed: %(path)s"""
351
def __init__(self, path, function):
352
PathError.__init__(self, path=path, extra=None)
353
self.function = function
356
class InaccessibleParent(PathError):
357
"""Parent not accessible given base %(base)s and relative path %(path)s"""
359
def __init__(self, path, base):
360
PathError.__init__(self, path)
266
364
class NoRepositoryPresent(BzrNewError):
267
365
"""No repository present: %(path)r"""
268
366
def __init__(self, bzrdir):
283
class UnsupportedFormatError(BzrError):
284
"""Specified path is a bzr branch that we recognize but cannot read."""
286
return 'unsupported branch format: %s' % self.args[0]
289
class UnknownFormatError(BzrError):
290
"""Specified path is a bzr branch whose format we do not recognize."""
292
return 'unknown branch format: %s' % self.args[0]
381
class UnsupportedFormatError(BzrNewError):
382
"""Unsupported branch format: %(format)s"""
385
class UnknownFormatError(BzrNewError):
386
"""Unknown branch format: %(format)r"""
295
389
class IncompatibleFormat(BzrNewError):
333
427
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
336
class BadFileKindError(BzrError):
337
"""Specified file is of a kind that cannot be added.
339
(For example a symlink or device file.)"""
342
class ForbiddenFileError(BzrError):
343
"""Cannot operate on a file because it is a control file."""
430
class BadFileKindError(BzrNewError):
431
"""Cannot operate on %(filename)s of unsupported kind %(kind)s"""
434
class ForbiddenControlFileError(BzrNewError):
435
"""Cannot operate on %(filename)s because it is a control file"""
346
438
class LockError(BzrNewError):
440
535
self.format = format
444
538
class StrictCommitFailed(Exception):
445
539
"""Commit refused because there are unknowns in the tree."""
448
class NoSuchRevision(BzrError):
542
class NoSuchRevision(BzrNewError):
543
"""Branch %(branch)s has no revision %(revision)s"""
545
is_user_error = False
449
547
def __init__(self, branch, revision):
451
self.revision = revision
452
msg = "Branch %s has no revision %s" % (branch, revision)
453
BzrError.__init__(self, msg)
548
BzrNewError.__init__(self, branch=branch, revision=revision)
551
class NoSuchRevisionSpec(BzrNewError):
552
"""No namespace registered for string: %(spec)r"""
554
def __init__(self, spec):
555
BzrNewError.__init__(self, spec=spec)
558
class InvalidRevisionSpec(BzrNewError):
559
"""Requested revision: '%(spec)s' does not exist in branch:
560
%(branch)s%(extra)s"""
562
def __init__(self, spec, branch, extra=None):
563
BzrNewError.__init__(self, branch=branch, spec=spec)
565
self.extra = '\n' + str(extra)
456
570
class HistoryMissing(BzrError):
461
575
% (branch, object_type, object_id))
464
class DivergedBranches(BzrError):
578
class DivergedBranches(BzrNewError):
579
"These branches have diverged. Use the merge command to reconcile them."""
466
583
def __init__(self, branch1, branch2):
467
BzrError.__init__(self, "These branches have diverged. Try merge.")
468
584
self.branch1 = branch1
469
585
self.branch2 = branch2
472
class UnrelatedBranches(BzrCommandError):
474
msg = "Branches have no common ancestor, and no base revision"\
476
BzrCommandError.__init__(self, msg)
479
class NoCommonAncestor(BzrError):
588
class UnrelatedBranches(BzrNewError):
589
"Branches have no common ancestor, and no merge base revision was specified."
594
class NoCommonAncestor(BzrNewError):
595
"Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
480
597
def __init__(self, revision_a, revision_b):
481
msg = "Revisions have no common ancestor: %s %s." \
482
% (revision_a, revision_b)
483
BzrError.__init__(self, msg)
598
self.revision_a = revision_a
599
self.revision_b = revision_b
486
602
class NoCommonRoot(BzrError):
517
633
self.bases = bases
520
class NoCommits(BzrError):
636
class NoCommits(BzrNewError):
637
"""Branch %(branch)s has no commits."""
521
639
def __init__(self, branch):
522
msg = "Branch %s has no commits." % branch
523
BzrError.__init__(self, msg)
640
BzrNewError.__init__(self, branch=branch)
526
643
class UnlistableStore(BzrError):
679
796
self.format = format
682
class TransportError(BzrError):
683
"""All errors thrown by Transport implementations should derive
799
class TransportError(BzrNewError):
800
"""Transport error: %(msg)s %(orig_error)s"""
686
802
def __init__(self, msg=None, orig_error=None):
687
803
if msg is None and orig_error is not None:
688
804
msg = str(orig_error)
689
BzrError.__init__(self, msg)
805
if orig_error is None:
691
810
self.orig_error = orig_error
811
BzrNewError.__init__(self)
814
class SmartProtocolError(TransportError):
815
"""Generic bzr smart protocol error: %(details)s"""
817
def __init__(self, details):
818
self.details = details
694
821
# A set of semi-meaningful errors which can be thrown
695
822
class TransportNotPossible(TransportError):
696
"""This is for transports where a specific function is explicitly not
697
possible. Such as pushing files to an HTTP server.
823
"""Transport operation not possible: %(msg)s %(orig_error)%"""
702
826
class ConnectionError(TransportError):
703
"""A connection problem prevents file retrieval.
704
This does not indicate whether the file exists or not; it indicates that a
705
precondition for requesting the file was not met.
707
def __init__(self, msg=None, orig_error=None):
708
TransportError.__init__(self, msg=msg, orig_error=orig_error)
827
"""Connection error: %(msg)s %(orig_error)s"""
711
830
class ConnectionReset(TransportError):
712
"""The connection has been closed."""
831
"""Connection closed: %(msg)s %(orig_error)s"""
834
class InvalidRange(TransportError):
835
"""Invalid range access in %(path)s at %(offset)s."""
837
def __init__(self, path, offset):
838
TransportError.__init__(self, ("Invalid range access in %s at %d"
844
class InvalidHttpResponse(TransportError):
845
"""Invalid http response for %(path)s: %(msg)s"""
847
def __init__(self, path, msg, orig_error=None):
849
TransportError.__init__(self, msg, orig_error=orig_error)
852
class InvalidHttpRange(InvalidHttpResponse):
853
"""Invalid http range "%(range)s" for %(path)s: %(msg)s"""
855
def __init__(self, path, range, msg):
857
InvalidHttpResponse.__init__(self, path, msg)
860
class InvalidHttpContentType(InvalidHttpResponse):
861
"""Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s"""
863
def __init__(self, path, ctype, msg):
865
InvalidHttpResponse.__init__(self, path, msg)
716
868
class ConflictsInTree(BzrError):
862
1018
self.format = format
1021
class BadConversionTarget(BzrNewError):
1022
"""Cannot convert to format %(format)s. %(problem)s"""
1024
def __init__(self, problem, format):
1025
BzrNewError.__init__(self)
1026
self.problem = problem
1027
self.format = format
1030
class NoDiff(BzrNewError):
1031
"""Diff is not installed on this machine: %(msg)s"""
1033
def __init__(self, msg):
1034
BzrNewError.__init__(self, msg=msg)
865
1037
class NoDiff3(BzrNewError):
866
1038
"""Diff3 is not installed on this machine."""
927
1099
"""A nested progress bar was not 'finished' correctly."""
1102
class InvalidProgressBarType(BzrNewError):
1103
"""Environment variable BZR_PROGRESS_BAR='%(bar_type)s is not a supported type
1104
Select one of: %(valid_types)s"""
1106
def __init__(self, bar_type, valid_types):
1107
BzrNewError.__init__(self, bar_type=bar_type, valid_types=valid_types)
930
1110
class UnsupportedOperation(BzrNewError):
931
1111
"""The method %(mname)s is not supported on objects of type %(tname)s."""
932
1112
def __init__(self, method, method_self):
962
1142
"""Not a bzr revision-bundle: %(text)r"""
964
1144
def __init__(self, text):
968
class BadBundle(Exception): pass
971
class MalformedHeader(BadBundle): pass
974
class MalformedPatches(BadBundle): pass
977
class MalformedFooter(BadBundle): pass
1145
BzrNewError.__init__(self)
1149
class BadBundle(BzrNewError):
1150
"""Bad bzr revision-bundle: %(text)r"""
1152
def __init__(self, text):
1153
BzrNewError.__init__(self)
1157
class MalformedHeader(BadBundle):
1158
"""Malformed bzr revision-bundle header: %(text)r"""
1160
def __init__(self, text):
1161
BzrNewError.__init__(self)
1165
class MalformedPatches(BadBundle):
1166
"""Malformed patches in bzr revision-bundle: %(text)r"""
1168
def __init__(self, text):
1169
BzrNewError.__init__(self)
1173
class MalformedFooter(BadBundle):
1174
"""Malformed footer in bzr revision-bundle: %(text)r"""
1176
def __init__(self, text):
1177
BzrNewError.__init__(self)
1181
class UnsupportedEOLMarker(BadBundle):
1182
"""End of line marker was not \\n in bzr revision-bundle"""
1185
BzrNewError.__init__(self)
1188
class BadInventoryFormat(BzrNewError):
1189
"""Root class for inventory serialization errors"""
1192
class UnexpectedInventoryFormat(BadInventoryFormat):
1193
"""The inventory was not in the expected format:\n %(msg)s"""
1195
def __init__(self, msg):
1196
BadInventoryFormat.__init__(self, msg=msg)
1199
class NoSmartServer(NotBranchError):
1200
"""No smart server available at %(url)s"""
1202
def __init__(self, url):
1206
class UnknownSSH(BzrNewError):
1207
"""Unrecognised value for BZR_SSH environment variable: %(vendor)s"""
1209
def __init__(self, vendor):
1210
BzrNewError.__init__(self)
1211
self.vendor = vendor
1214
class GhostRevisionUnusableHere(BzrNewError):
1215
"""Ghost revision {%(revision_id)s} cannot be used here."""
1217
def __init__(self, revision_id):
1218
BzrNewError.__init__(self)
1219
self.revision_id = revision_id
1222
class IllegalUseOfScopeReplacer(BzrNewError):
1223
"""ScopeReplacer object %(name)r was used incorrectly: %(msg)s%(extra)s"""
1225
is_user_error = False
1227
def __init__(self, name, msg, extra=None):
1228
BzrNewError.__init__(self)
1232
self.extra = ': ' + str(extra)
1237
class InvalidImportLine(BzrNewError):
1238
"""Not a valid import statement: %(msg)\n%(text)s"""
1240
is_user_error = False
1242
def __init__(self, text, msg):
1243
BzrNewError.__init__(self)
1248
class ImportNameCollision(BzrNewError):
1249
"""Tried to import an object to the same name as an existing object. %(name)s"""
1251
is_user_error = False
1253
def __init__(self, name):
1254
BzrNewError.__init__(self)