1
# Copyright (C) 2005, 2006 Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
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
93
120
# base classes should override the docstring with their human-
94
121
# readable explanation
96
def __init__(self, **kwds):
123
def __init__(self, *args, **kwds):
124
# XXX: Use the underlying BzrError to always generate the args attribute
125
# if it doesn't exist. We can't use super here, because exceptions are
126
# old-style classes in python2.4 (but new in 2.5). --bmc, 20060426
127
BzrError.__init__(self, *args)
97
128
for key, value in kwds.items():
98
129
setattr(self, key, value)
100
131
def __str__(self):
102
return self.__doc__ % self.__dict__
103
except (NameError, ValueError, KeyError), e:
104
return 'Unprintable exception %s: %s' \
105
% (self.__class__.__name__, str(e))
133
# __str__() should always return a 'str' object
134
# never a 'unicode' object.
135
s = self.__doc__ % self.__dict__
136
if isinstance(s, unicode):
137
return s.encode('utf8')
139
except (TypeError, NameError, ValueError, KeyError), e:
140
return 'Unprintable exception %s(%r): %s' \
141
% (self.__class__.__name__,
142
self.__dict__, str(e))
145
class AlreadyBuilding(BzrNewError):
146
"""The tree builder is already building a tree."""
108
149
class BzrCheckError(BzrNewError):
109
150
"""Internal check failed: %(message)s"""
152
is_user_error = False
111
154
def __init__(self, message):
112
155
BzrNewError.__init__(self)
113
156
self.message = message
130
176
class InvalidRevisionId(BzrNewError):
131
177
"""Invalid revision-id {%(revision_id)s} in %(branch)s"""
132
179
def __init__(self, revision_id, branch):
180
# branch can be any string or object with __str__ defined
133
181
BzrNewError.__init__(self)
134
182
self.revision_id = revision_id
135
183
self.branch = branch
186
class InventoryModified(BzrNewError):
187
"""The current inventory for the tree %(tree)r has been modified, so a clean inventory cannot be read without data loss."""
189
def __init__(self, tree):
190
BzrNewError.__init__(self)
194
class NoSuchId(BzrNewError):
195
"""The file id %(file_id)s is not present in the tree %(tree)s."""
197
def __init__(self, tree, file_id):
198
BzrNewError.__init__(self)
199
self.file_id = file_id
138
203
class NoWorkingTree(BzrNewError):
139
"""No WorkingTree exists for %s(base)."""
204
"""No WorkingTree exists for %(base)s."""
141
206
def __init__(self, base):
142
207
BzrNewError.__init__(self)
211
class WorkingTreeAlreadyPopulated(BzrNewError):
212
"""Working tree already populated in %(base)s"""
214
is_user_error = False
217
class NotBuilding(BzrNewError):
218
"""Not currently building a tree."""
146
221
class NotLocalUrl(BzrNewError):
147
"""%s(url) is not a local path."""
222
"""%(url)s is not a local path."""
149
224
def __init__(self, url):
150
225
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
229
class NotWriteLocked(BzrNewError):
230
"""%(not_locked)r is not write locked but needs to be."""
232
def __init__(self, not_locked):
233
BzrNewError.__init__(self)
234
self.not_locked = not_locked
237
class BzrCommandError(BzrNewError):
238
"""Error from user command"""
242
# Error from malformed user command; please avoid raising this as a
243
# generic exception not caused by user input.
159
245
# I think it's a waste of effort to differentiate between errors that
160
246
# are not intended to be caught anyway. UI code need not subclass
161
247
# BzrCommandError, and non-UI code should not throw a subclass of
162
248
# BzrCommandError. ADHB 20051211
249
def __init__(self, msg):
250
# Object.__str__() must return a real string
251
# returning a Unicode string is a python error.
252
if isinstance(msg, unicode):
253
self.msg = msg.encode('utf8')
163
257
def __str__(self):
167
261
class BzrOptionError(BzrCommandError):
168
"""Some missing or otherwise incorrect option was supplied."""
262
"""Error in command line options"""
171
class StrictCommitFailed(Exception):
172
"""Commit refused because there are unknowns in the tree."""
265
class StrictCommitFailed(BzrNewError):
266
"""Commit refused because there are unknown files in the tree"""
269
# XXX: Should be unified with TransportError; they seem to represent the
175
271
class PathError(BzrNewError):
176
272
"""Generic path error: %(path)r%(extra)s)"""
204
310
"""Permission denied: %(path)r%(extra)s"""
313
class InvalidURL(PathError):
314
"""Invalid url supplied to transport: %(path)r%(extra)s"""
317
class InvalidURLJoin(PathError):
318
"""Invalid URL join request: %(args)s%(extra)s"""
320
def __init__(self, msg, base, args):
321
PathError.__init__(self, base, msg)
322
self.args = [base] + list(args)
325
class UnsupportedProtocol(PathError):
326
"""Unsupported protocol for url "%(path)s"%(extra)s"""
328
def __init__(self, url, extra):
329
PathError.__init__(self, url, extra=extra)
332
class ShortReadvError(PathError):
333
"""readv() read %(actual)s bytes rather than %(length)s bytes at %(offset)s for %(path)s%(extra)s"""
335
is_user_error = False
337
def __init__(self, path, offset, length, actual, extra=None):
338
PathError.__init__(self, path, extra=extra)
207
344
class PathNotChild(BzrNewError):
208
345
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
347
is_user_error = False
209
349
def __init__(self, path, base, extra=None):
210
350
BzrNewError.__init__(self)
359
class InvalidNormalization(PathError):
360
"""Path %(path)r is not unicode normalized"""
363
# TODO: This is given a URL; we try to unescape it but doing that from inside
364
# the exception object is a bit undesirable.
365
# TODO: Probably this behavior of should be a common superclass
219
366
class NotBranchError(PathError):
220
367
"""Not a branch: %(path)s"""
369
def __init__(self, path):
370
import bzrlib.urlutils as urlutils
371
self.path = urlutils.unescape_for_display(path, 'ascii')
223
374
class AlreadyBranchError(PathError):
224
"""Already a branch: %(path)s. Use `bzr checkout` to build a working tree."""
375
"""Already a branch: %(path)s."""
378
class BranchExistsWithoutWorkingTree(PathError):
379
"""Directory contains a branch, but no working tree \
380
(use bzr checkout if you wish to build a working tree): %(path)s"""
383
class AtomicFileAlreadyClosed(PathError):
384
"""'%(function)s' called on an AtomicFile after it was closed: %(path)s"""
386
def __init__(self, path, function):
387
PathError.__init__(self, path=path, extra=None)
388
self.function = function
391
class InaccessibleParent(PathError):
392
"""Parent not accessible given base %(base)s and relative path %(path)s"""
394
def __init__(self, path, base):
395
PathError.__init__(self, path)
227
399
class NoRepositoryPresent(BzrNewError):
228
"""Not repository present: %(path)r"""
400
"""No repository present: %(path)r"""
229
401
def __init__(self, bzrdir):
230
402
BzrNewError.__init__(self)
231
403
self.path = bzrdir.transport.clone('..').base
280
456
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."""
459
class PathsDoNotExist(BzrNewError):
460
"""Path(s) do not exist: %(paths_as_string)s"""
462
# used when reporting that paths are neither versioned nor in the working
465
def __init__(self, paths):
467
from bzrlib.osutils import quotefn
468
BzrNewError.__init__(self)
470
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
473
class BadFileKindError(BzrNewError):
474
"""Cannot operate on %(filename)s of unsupported kind %(kind)s"""
477
class ForbiddenControlFileError(BzrNewError):
478
"""Cannot operate on %(filename)s because it is a control file"""
293
481
class LockError(BzrNewError):
387
578
self.format = format
391
581
class StrictCommitFailed(Exception):
392
582
"""Commit refused because there are unknowns in the tree."""
395
class NoSuchRevision(BzrError):
585
class NoSuchRevision(BzrNewError):
586
"""Branch %(branch)s has no revision %(revision)s"""
588
is_user_error = False
396
590
def __init__(self, branch, revision):
398
self.revision = revision
399
msg = "Branch %s has no revision %s" % (branch, revision)
400
BzrError.__init__(self, msg)
591
BzrNewError.__init__(self, branch=branch, revision=revision)
594
class NoSuchRevisionSpec(BzrNewError):
595
"""No namespace registered for string: %(spec)r"""
597
def __init__(self, spec):
598
BzrNewError.__init__(self, spec=spec)
601
class InvalidRevisionSpec(BzrNewError):
602
"""Requested revision: '%(spec)s' does not exist in branch:
603
%(branch)s%(extra)s"""
605
def __init__(self, spec, branch, extra=None):
606
BzrNewError.__init__(self, branch=branch, spec=spec)
608
self.extra = '\n' + str(extra)
403
613
class HistoryMissing(BzrError):
408
618
% (branch, object_type, object_id))
411
class DivergedBranches(BzrError):
621
class DivergedBranches(BzrNewError):
622
"These branches have diverged. Use the merge command to reconcile them."""
413
626
def __init__(self, branch1, branch2):
414
BzrError.__init__(self, "These branches have diverged. Try merge.")
415
627
self.branch1 = branch1
416
628
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):
631
class UnrelatedBranches(BzrNewError):
632
"Branches have no common ancestor, and no merge base revision was specified."
637
class NoCommonAncestor(BzrNewError):
638
"Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
427
640
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)
641
self.revision_a = revision_a
642
self.revision_b = revision_b
433
645
class NoCommonRoot(BzrError):
458
670
def __init__(self, bases):
459
671
warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
460
672
DeprecationWarning)
461
msg = "The correct base is unclear, becase %s are all equally close" %\
673
msg = "The correct base is unclear, because %s are all equally close" %\
463
675
BzrError.__init__(self, msg)
464
676
self.bases = bases
467
class NoCommits(BzrError):
679
class NoCommits(BzrNewError):
680
"""Branch %(branch)s has no commits."""
468
682
def __init__(self, branch):
469
msg = "Branch %s has no commits." % branch
470
BzrError.__init__(self, msg)
683
BzrNewError.__init__(self, branch=branch)
473
686
class UnlistableStore(BzrError):
622
835
class NoSuchExportFormat(BzrNewError):
623
836
"""Export format %(format)r not supported"""
624
838
def __init__(self, format):
625
839
BzrNewError.__init__(self)
626
840
self.format = format
629
class TransportError(BzrError):
630
"""All errors thrown by Transport implementations should derive
844
class TooManyConcurrentRequests(BzrNewError):
845
"""The medium '%(medium)s' has reached its concurrent request limit. Be sure to finish_writing and finish_reading on the current request that is open."""
847
def __init__(self, medium):
848
BzrNewError.__init__(self)
852
class TransportError(BzrNewError):
853
"""Transport error: %(msg)s %(orig_error)s"""
633
855
def __init__(self, msg=None, orig_error=None):
634
856
if msg is None and orig_error is not None:
635
857
msg = str(orig_error)
636
BzrError.__init__(self, msg)
858
if orig_error is None:
638
863
self.orig_error = orig_error
864
BzrNewError.__init__(self)
867
class SmartProtocolError(TransportError):
868
"""Generic bzr smart protocol error: %(details)s"""
870
def __init__(self, details):
871
self.details = details
641
874
# A set of semi-meaningful errors which can be thrown
642
875
class TransportNotPossible(TransportError):
643
"""This is for transports where a specific function is explicitly not
644
possible. Such as pushing files to an HTTP server.
876
"""Transport operation not possible: %(msg)s %(orig_error)s"""
649
879
class ConnectionError(TransportError):
650
"""A connection problem prevents file retrieval.
651
This does not indicate whether the file exists or not; it indicates that a
652
precondition for requesting the file was not met.
654
def __init__(self, msg=None, orig_error=None):
655
TransportError.__init__(self, msg=msg, orig_error=orig_error)
880
"""Connection error: %(msg)s %(orig_error)s"""
658
883
class ConnectionReset(TransportError):
659
"""The connection has been closed."""
884
"""Connection closed: %(msg)s %(orig_error)s"""
887
class InvalidRange(TransportError):
888
"""Invalid range access in %(path)s at %(offset)s."""
890
def __init__(self, path, offset):
891
TransportError.__init__(self, ("Invalid range access in %s at %d"
897
class InvalidHttpResponse(TransportError):
898
"""Invalid http response for %(path)s: %(msg)s"""
900
def __init__(self, path, msg, orig_error=None):
902
TransportError.__init__(self, msg, orig_error=orig_error)
905
class InvalidHttpRange(InvalidHttpResponse):
906
"""Invalid http range "%(range)s" for %(path)s: %(msg)s"""
908
def __init__(self, path, range, msg):
910
InvalidHttpResponse.__init__(self, path, msg)
913
class InvalidHttpContentType(InvalidHttpResponse):
914
"""Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s"""
916
def __init__(self, path, ctype, msg):
918
InvalidHttpResponse.__init__(self, path, msg)
663
921
class ConflictsInTree(BzrError):
851
1200
"""A nested progress bar was not 'finished' correctly."""
1203
class InvalidProgressBarType(BzrNewError):
1204
"""Environment variable BZR_PROGRESS_BAR='%(bar_type)s is not a supported type
1205
Select one of: %(valid_types)s"""
1207
def __init__(self, bar_type, valid_types):
1208
BzrNewError.__init__(self, bar_type=bar_type, valid_types=valid_types)
854
1211
class UnsupportedOperation(BzrNewError):
855
1212
"""The method %(mname)s is not supported on objects of type %(tname)s."""
856
1213
def __init__(self, method, method_self):
857
1214
self.method = method
858
1215
self.mname = method.__name__
859
1216
self.tname = type(method_self).__name__
1219
class BinaryFile(BzrNewError):
1220
"""File is binary but should be text."""
1223
class IllegalPath(BzrNewError):
1224
"""The path %(path)s is not permitted on this platform"""
1226
def __init__(self, path):
1227
BzrNewError.__init__(self)
1231
class TestamentMismatch(BzrNewError):
1232
"""Testament did not match expected value.
1233
For revision_id {%(revision_id)s}, expected {%(expected)s}, measured
1236
def __init__(self, revision_id, expected, measured):
1237
self.revision_id = revision_id
1238
self.expected = expected
1239
self.measured = measured
1242
class NotABundle(BzrNewError):
1243
"""Not a bzr revision-bundle: %(text)r"""
1245
def __init__(self, text):
1246
BzrNewError.__init__(self)
1250
class BadBundle(BzrNewError):
1251
"""Bad bzr revision-bundle: %(text)r"""
1253
def __init__(self, text):
1254
BzrNewError.__init__(self)
1258
class MalformedHeader(BadBundle):
1259
"""Malformed bzr revision-bundle header: %(text)r"""
1261
def __init__(self, text):
1262
BzrNewError.__init__(self)
1266
class MalformedPatches(BadBundle):
1267
"""Malformed patches in bzr revision-bundle: %(text)r"""
1269
def __init__(self, text):
1270
BzrNewError.__init__(self)
1274
class MalformedFooter(BadBundle):
1275
"""Malformed footer in bzr revision-bundle: %(text)r"""
1277
def __init__(self, text):
1278
BzrNewError.__init__(self)
1282
class UnsupportedEOLMarker(BadBundle):
1283
"""End of line marker was not \\n in bzr revision-bundle"""
1286
BzrNewError.__init__(self)
1289
class IncompatibleFormat(BzrNewError):
1290
"""Bundle format %(bundle_format)s is incompatible with %(other)s"""
1292
def __init__(self, bundle_format, other):
1293
BzrNewError.__init__(self)
1294
self.bundle_format = bundle_format
1298
class BadInventoryFormat(BzrNewError):
1299
"""Root class for inventory serialization errors"""
1302
class UnexpectedInventoryFormat(BadInventoryFormat):
1303
"""The inventory was not in the expected format:\n %(msg)s"""
1305
def __init__(self, msg):
1306
BadInventoryFormat.__init__(self, msg=msg)
1309
class NoSmartMedium(BzrNewError):
1310
"""The transport '%(transport)s' cannot tunnel the smart protocol."""
1312
def __init__(self, transport):
1313
BzrNewError.__init__(self)
1314
self.transport = transport
1317
class NoSmartServer(NotBranchError):
1318
"""No smart server available at %(url)s"""
1320
def __init__(self, url):
1324
class UnknownSSH(BzrNewError):
1325
"""Unrecognised value for BZR_SSH environment variable: %(vendor)s"""
1327
def __init__(self, vendor):
1328
BzrNewError.__init__(self)
1329
self.vendor = vendor
1332
class GhostRevisionUnusableHere(BzrNewError):
1333
"""Ghost revision {%(revision_id)s} cannot be used here."""
1335
def __init__(self, revision_id):
1336
BzrNewError.__init__(self)
1337
self.revision_id = revision_id
1340
class IllegalUseOfScopeReplacer(BzrNewError):
1341
"""ScopeReplacer object %(name)r was used incorrectly: %(msg)s%(extra)s"""
1343
is_user_error = False
1345
def __init__(self, name, msg, extra=None):
1346
BzrNewError.__init__(self)
1350
self.extra = ': ' + str(extra)
1355
class InvalidImportLine(BzrNewError):
1356
"""Not a valid import statement: %(msg)\n%(text)s"""
1358
is_user_error = False
1360
def __init__(self, text, msg):
1361
BzrNewError.__init__(self)
1366
class ImportNameCollision(BzrNewError):
1367
"""Tried to import an object to the same name as an existing object. %(name)s"""
1369
is_user_error = False
1371
def __init__(self, name):
1372
BzrNewError.__init__(self)