1
# Copyright (C) 2005, 2006 Canonical
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Exceptions for bzr, and reporting of them.
19
Exceptions are caught at a high level to report errors to the user, and
20
might also be caught inside the program. Therefore it needs to be
21
possible to convert them to a meaningful string, and also for them to be
22
interrogated by the program.
24
Exceptions are defined such that the arguments given to the constructor
25
are stored in the object as properties of the same name. When the
26
object is printed as a string, the doc string of the class is used as
27
a format string with the property dictionary available to it.
29
This means that exceptions can used like this:
33
... raise NotBranchError(path='/foo/bar')
35
... print sys.exc_type
36
... print sys.exc_value
37
... path = getattr(sys.exc_value, 'path')
38
... if path is not None:
40
bzrlib.errors.NotBranchError
41
Not a branch: /foo/bar
46
* 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
56
from warnings import warn
58
# based on Scott James Remnant's hct error classes
60
# TODO: is there any value in providing the .args field used by standard
61
# python exceptions? A list of values with no names seems less useful
64
# TODO: Perhaps convert the exception to a string at the moment it's
65
# constructed to make sure it will succeed. But that says nothing about
66
# exceptions that are never raised.
68
# TODO: Convert all the other error classes here to BzrNewError, and eliminate
71
# TODO: The pattern (from hct) of using classes docstrings as message
72
# templates is cute but maybe not such a great idea - perhaps should have a
73
# separate static message_template.
76
class BzrError(StandardError):
78
# XXX: Should we show the exception class in
79
# exceptions that don't provide their own message?
80
# maybe it should be done at a higher level
81
## n = self.__class__.__name__ + ': '
83
if len(self.args) == 1:
84
return str(self.args[0])
85
elif len(self.args) == 2:
86
# further explanation or suggestions
88
return n + '\n '.join([self.args[0]] + self.args[1])
90
return n + "%r" % self
92
return n + `self.args`
95
class BzrNewError(BzrError):
97
# base classes should override the docstring with their human-
98
# readable explanation
100
def __init__(self, **kwds):
101
for key, value in kwds.items():
102
setattr(self, key, value)
106
return self.__doc__ % self.__dict__
107
except (NameError, ValueError, KeyError), e:
108
return 'Unprintable exception %s: %s' \
109
% (self.__class__.__name__, str(e))
112
class BzrCheckError(BzrNewError):
113
"""Internal check failed: %(message)s"""
115
def __init__(self, message):
116
BzrNewError.__init__(self)
117
self.message = message
120
class InvalidEntryName(BzrNewError):
121
"""Invalid entry name: %(name)s"""
122
def __init__(self, name):
123
BzrNewError.__init__(self)
127
class InvalidRevisionNumber(BzrNewError):
128
"""Invalid revision number %(revno)d"""
129
def __init__(self, revno):
130
BzrNewError.__init__(self)
134
class InvalidRevisionId(BzrNewError):
135
"""Invalid revision-id {%(revision_id)s} in %(branch)s"""
136
def __init__(self, revision_id, branch):
137
BzrNewError.__init__(self)
138
self.revision_id = revision_id
142
class NoWorkingTree(BzrNewError):
143
"""No WorkingTree exists for %(base)s."""
145
def __init__(self, base):
146
BzrNewError.__init__(self)
150
class NotLocalUrl(BzrNewError):
151
"""%(url)s is not a local path."""
153
def __init__(self, url):
154
BzrNewError.__init__(self)
158
class BzrCommandError(BzrError):
159
# Error from malformed user command
160
# This is being misused as a generic exception
161
# pleae subclass. RBC 20051030
163
# I think it's a waste of effort to differentiate between errors that
164
# are not intended to be caught anyway. UI code need not subclass
165
# BzrCommandError, and non-UI code should not throw a subclass of
166
# BzrCommandError. ADHB 20051211
171
class BzrOptionError(BzrCommandError):
172
"""Some missing or otherwise incorrect option was supplied."""
175
class StrictCommitFailed(Exception):
176
"""Commit refused because there are unknowns in the tree."""
179
# XXX: Should be unified with TransportError; they seem to represent the
181
class PathError(BzrNewError):
182
"""Generic path error: %(path)r%(extra)s)"""
184
def __init__(self, path, extra=None):
185
BzrNewError.__init__(self)
188
self.extra = ': ' + str(extra)
193
class NoSuchFile(PathError):
194
"""No such file: %(path)r%(extra)s"""
197
class FileExists(PathError):
198
"""File exists: %(path)r%(extra)s"""
201
class DirectoryNotEmpty(PathError):
202
"""Directory not empty: %(path)r%(extra)s"""
205
class ResourceBusy(PathError):
206
"""Device or resource busy: %(path)r%(extra)s"""
209
class PermissionDenied(PathError):
210
"""Permission denied: %(path)r%(extra)s"""
213
class PathNotChild(BzrNewError):
214
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
215
def __init__(self, path, base, extra=None):
216
BzrNewError.__init__(self)
220
self.extra = ': ' + str(extra)
225
class NotBranchError(PathError):
226
"""Not a branch: %(path)s"""
229
class AlreadyBranchError(PathError):
230
"""Already a branch: %(path)s. Use `bzr checkout` to build a working tree."""
233
class NoRepositoryPresent(BzrNewError):
234
"""Not repository present: %(path)r"""
235
def __init__(self, bzrdir):
236
BzrNewError.__init__(self)
237
self.path = bzrdir.transport.clone('..').base
240
class FileInWrongBranch(BzrNewError):
241
"""File %(path)s in not in branch %(branch_base)s."""
243
def __init__(self, branch, path):
244
BzrNewError.__init__(self)
246
self.branch_base = branch.base
250
class UnsupportedFormatError(BzrError):
251
"""Specified path is a bzr branch that we recognize but cannot read."""
253
return 'unsupported branch format: %s' % self.args[0]
256
class UnknownFormatError(BzrError):
257
"""Specified path is a bzr branch whose format we do not recognize."""
259
return 'unknown branch format: %s' % self.args[0]
262
class IncompatibleFormat(BzrNewError):
263
"""Format %(format)s is not compatible with .bzr version %(bzrdir)s."""
265
def __init__(self, format, bzrdir_format):
266
BzrNewError.__init__(self)
268
self.bzrdir = bzrdir_format
271
class NotVersionedError(BzrNewError):
272
"""%(path)s is not versioned"""
273
def __init__(self, path):
274
BzrNewError.__init__(self)
278
class PathsNotVersionedError(BzrNewError):
279
# used when reporting several paths are not versioned
280
"""Path(s) are not versioned: %(paths_as_string)s"""
282
def __init__(self, paths):
283
from bzrlib.osutils import quotefn
284
BzrNewError.__init__(self)
286
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
289
class PathsDoNotExist(BzrNewError):
290
"""Path(s) do not exist: %(paths_as_string)s"""
292
# used when reporting that paths are neither versioned nor in the working
295
def __init__(self, paths):
297
from bzrlib.osutils import quotefn
298
BzrNewError.__init__(self)
300
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
303
class BadFileKindError(BzrError):
304
"""Specified file is of a kind that cannot be added.
306
(For example a symlink or device file.)"""
309
class ForbiddenFileError(BzrError):
310
"""Cannot operate on a file because it is a control file."""
313
class LockError(BzrNewError):
314
"""Lock error: %(message)s"""
315
# All exceptions from the lock/unlock functions should be from
316
# this exception class. They will be translated as necessary. The
317
# original exception is available as e.original_error
319
# New code should prefer to raise specific subclasses
320
def __init__(self, message):
321
self.message = message
324
class CommitNotPossible(LockError):
325
"""A commit was attempted but we do not have a write lock open."""
330
class AlreadyCommitted(LockError):
331
"""A rollback was requested, but is not able to be accomplished."""
336
class ReadOnlyError(LockError):
337
"""A write attempt was made in a read only transaction on %(obj)s"""
338
def __init__(self, obj):
342
class OutSideTransaction(BzrNewError):
343
"""A transaction related operation was attempted after the transaction finished."""
346
class ObjectNotLocked(LockError):
347
"""%(obj)r is not locked"""
348
# this can indicate that any particular object is not locked; see also
349
# LockNotHeld which means that a particular *lock* object is not held by
350
# the caller -- perhaps they should be unified.
351
def __init__(self, obj):
355
class ReadOnlyObjectDirtiedError(ReadOnlyError):
356
"""Cannot change object %(obj)r in read only transaction"""
357
def __init__(self, obj):
361
class UnlockableTransport(LockError):
362
"""Cannot lock: transport is read only: %(transport)s"""
363
def __init__(self, transport):
364
self.transport = transport
367
class LockContention(LockError):
368
"""Could not acquire lock %(lock)s"""
369
# TODO: show full url for lock, combining the transport and relative bits?
370
def __init__(self, lock):
374
class LockBroken(LockError):
375
"""Lock was broken while still open: %(lock)s - check storage consistency!"""
376
def __init__(self, lock):
380
class LockBreakMismatch(LockError):
381
"""Lock was released and re-acquired before being broken: %(lock)s: held by %(holder)r, wanted to break %(target)r"""
382
def __init__(self, lock, holder, target):
388
class LockNotHeld(LockError):
389
"""Lock not held: %(lock)s"""
390
def __init__(self, lock):
394
class PointlessCommit(BzrNewError):
395
"""No changes to commit"""
398
class UpgradeReadonly(BzrNewError):
399
"""Upgrade URL cannot work with readonly URL's."""
402
class UpToDateFormat(BzrNewError):
403
"""The branch format %(format)s is already at the most recent format."""
405
def __init__(self, format):
406
BzrNewError.__init__(self)
411
class StrictCommitFailed(Exception):
412
"""Commit refused because there are unknowns in the tree."""
415
class NoSuchRevision(BzrError):
416
def __init__(self, branch, revision):
418
self.revision = revision
419
msg = "Branch %s has no revision %s" % (branch, revision)
420
BzrError.__init__(self, msg)
423
class HistoryMissing(BzrError):
424
def __init__(self, branch, object_type, object_id):
426
BzrError.__init__(self,
427
'%s is missing %s {%s}'
428
% (branch, object_type, object_id))
431
class DivergedBranches(BzrError):
433
def __init__(self, branch1, branch2):
434
BzrError.__init__(self, "These branches have diverged. Try merge.")
435
self.branch1 = branch1
436
self.branch2 = branch2
439
class UnrelatedBranches(BzrCommandError):
441
msg = "Branches have no common ancestor, and no base revision"\
443
BzrCommandError.__init__(self, msg)
446
class NoCommonAncestor(BzrError):
447
def __init__(self, revision_a, revision_b):
448
msg = "Revisions have no common ancestor: %s %s." \
449
% (revision_a, revision_b)
450
BzrError.__init__(self, msg)
453
class NoCommonRoot(BzrError):
454
def __init__(self, revision_a, revision_b):
455
msg = "Revisions are not derived from the same root: %s %s." \
456
% (revision_a, revision_b)
457
BzrError.__init__(self, msg)
461
class NotAncestor(BzrError):
462
def __init__(self, rev_id, not_ancestor_id):
463
msg = "Revision %s is not an ancestor of %s" % (not_ancestor_id,
465
BzrError.__init__(self, msg)
467
self.not_ancestor_id = not_ancestor_id
470
class InstallFailed(BzrError):
471
def __init__(self, revisions):
472
msg = "Could not install revisions:\n%s" % " ,".join(revisions)
473
BzrError.__init__(self, msg)
474
self.revisions = revisions
477
class AmbiguousBase(BzrError):
478
def __init__(self, bases):
479
warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
481
msg = "The correct base is unclear, becase %s are all equally close" %\
483
BzrError.__init__(self, msg)
487
class NoCommits(BzrError):
488
def __init__(self, branch):
489
msg = "Branch %s has no commits." % branch
490
BzrError.__init__(self, msg)
493
class UnlistableStore(BzrError):
494
def __init__(self, store):
495
BzrError.__init__(self, "Store %s is not listable" % store)
499
class UnlistableBranch(BzrError):
500
def __init__(self, br):
501
BzrError.__init__(self, "Stores for branch %s are not listable" % br)
504
class BoundBranchOutOfDate(BzrNewError):
505
"""Bound branch %(branch)s is out of date with master branch %(master)s."""
506
def __init__(self, branch, master):
507
BzrNewError.__init__(self)
512
class CommitToDoubleBoundBranch(BzrNewError):
513
"""Cannot commit to branch %(branch)s. It is bound to %(master)s, which is bound to %(remote)s."""
514
def __init__(self, branch, master, remote):
515
BzrNewError.__init__(self)
521
class OverwriteBoundBranch(BzrNewError):
522
"""Cannot pull --overwrite to a branch which is bound %(branch)s"""
523
def __init__(self, branch):
524
BzrNewError.__init__(self)
528
class BoundBranchConnectionFailure(BzrNewError):
529
"""Unable to connect to target of bound branch %(branch)s => %(target)s: %(error)s"""
530
def __init__(self, branch, target, error):
531
BzrNewError.__init__(self)
537
class WeaveError(BzrNewError):
538
"""Error in processing weave: %(message)s"""
540
def __init__(self, message=None):
541
BzrNewError.__init__(self)
542
self.message = message
545
class WeaveRevisionAlreadyPresent(WeaveError):
546
"""Revision {%(revision_id)s} already present in %(weave)s"""
547
def __init__(self, revision_id, weave):
549
WeaveError.__init__(self)
550
self.revision_id = revision_id
554
class WeaveRevisionNotPresent(WeaveError):
555
"""Revision {%(revision_id)s} not present in %(weave)s"""
557
def __init__(self, revision_id, weave):
558
WeaveError.__init__(self)
559
self.revision_id = revision_id
563
class WeaveFormatError(WeaveError):
564
"""Weave invariant violated: %(what)s"""
566
def __init__(self, what):
567
WeaveError.__init__(self)
571
class WeaveParentMismatch(WeaveError):
572
"""Parents are mismatched between two revisions."""
575
class WeaveInvalidChecksum(WeaveError):
576
"""Text did not match it's checksum: %(message)s"""
579
class WeaveTextDiffers(WeaveError):
580
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
582
def __init__(self, revision_id, weave_a, weave_b):
583
WeaveError.__init__(self)
584
self.revision_id = revision_id
585
self.weave_a = weave_a
586
self.weave_b = weave_b
589
class WeaveTextDiffers(WeaveError):
590
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
592
def __init__(self, revision_id, weave_a, weave_b):
593
WeaveError.__init__(self)
594
self.revision_id = revision_id
595
self.weave_a = weave_a
596
self.weave_b = weave_b
599
class VersionedFileError(BzrNewError):
600
"""Versioned file error."""
603
class RevisionNotPresent(VersionedFileError):
604
"""Revision {%(revision_id)s} not present in %(file_id)s."""
606
def __init__(self, revision_id, file_id):
607
VersionedFileError.__init__(self)
608
self.revision_id = revision_id
609
self.file_id = file_id
612
class RevisionAlreadyPresent(VersionedFileError):
613
"""Revision {%(revision_id)s} already present in %(file_id)s."""
615
def __init__(self, revision_id, file_id):
616
VersionedFileError.__init__(self)
617
self.revision_id = revision_id
618
self.file_id = file_id
621
class KnitError(BzrNewError):
625
class KnitHeaderError(KnitError):
626
"""Knit header error: %(badline)r unexpected"""
628
def __init__(self, badline):
629
KnitError.__init__(self)
630
self.badline = badline
633
class KnitCorrupt(KnitError):
634
"""Knit %(filename)s corrupt: %(how)s"""
636
def __init__(self, filename, how):
637
KnitError.__init__(self)
638
self.filename = filename
642
class NoSuchExportFormat(BzrNewError):
643
"""Export format %(format)r not supported"""
644
def __init__(self, format):
645
BzrNewError.__init__(self)
649
class TransportError(BzrError):
650
"""All errors thrown by Transport implementations should derive
653
def __init__(self, msg=None, orig_error=None):
654
if msg is None and orig_error is not None:
655
msg = str(orig_error)
656
BzrError.__init__(self, msg)
658
self.orig_error = orig_error
661
# A set of semi-meaningful errors which can be thrown
662
class TransportNotPossible(TransportError):
663
"""This is for transports where a specific function is explicitly not
664
possible. Such as pushing files to an HTTP server.
669
class ConnectionError(TransportError):
670
"""A connection problem prevents file retrieval.
671
This does not indicate whether the file exists or not; it indicates that a
672
precondition for requesting the file was not met.
674
def __init__(self, msg=None, orig_error=None):
675
TransportError.__init__(self, msg=msg, orig_error=orig_error)
678
class ConnectionReset(TransportError):
679
"""The connection has been closed."""
683
class ConflictsInTree(BzrError):
685
BzrError.__init__(self, "Working tree has conflicts.")
688
class ParseConfigError(BzrError):
689
def __init__(self, errors, filename):
692
message = "Error(s) parsing config file %s:\n%s" % \
693
(filename, ('\n'.join(e.message for e in errors)))
694
BzrError.__init__(self, message)
697
class SigningFailed(BzrError):
698
def __init__(self, command_line):
699
BzrError.__init__(self, "Failed to gpg sign data with command '%s'"
703
class WorkingTreeNotRevision(BzrError):
704
def __init__(self, tree):
705
BzrError.__init__(self, "The working tree for %s has changed since"
706
" last commit, but weave merge requires that it be"
707
" unchanged." % tree.basedir)
710
class CantReprocessAndShowBase(BzrNewError):
711
"""Can't reprocess and show base.
712
Reprocessing obscures relationship of conflicting lines to base."""
715
class GraphCycleError(BzrNewError):
716
"""Cycle in graph %(graph)r"""
717
def __init__(self, graph):
718
BzrNewError.__init__(self)
722
class NotConflicted(BzrNewError):
723
"""File %(filename)s is not conflicted."""
725
def __init__(self, filename):
726
BzrNewError.__init__(self)
727
self.filename = filename
730
class MustUseDecorated(Exception):
731
"""A decorating function has requested its original command be used.
733
This should never escape bzr, so does not need to be printable.
737
class MissingText(BzrNewError):
738
"""Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
740
def __init__(self, branch, text_revision, file_id):
741
BzrNewError.__init__(self)
743
self.base = branch.base
744
self.text_revision = text_revision
745
self.file_id = file_id
748
class DuplicateKey(BzrNewError):
749
"""Key %(key)s is already present in map"""
752
class MalformedTransform(BzrNewError):
753
"""Tree transform is malformed %(conflicts)r"""
756
class BzrBadParameter(BzrNewError):
757
"""A bad parameter : %(param)s is not usable.
759
This exception should never be thrown, but it is a base class for all
760
parameter-to-function errors.
762
def __init__(self, param):
763
BzrNewError.__init__(self)
767
class BzrBadParameterNotUnicode(BzrBadParameter):
768
"""Parameter %(param)s is neither unicode nor utf8."""
771
class ReusingTransform(BzrNewError):
772
"""Attempt to reuse a transform that has already been applied."""
775
class CantMoveRoot(BzrNewError):
776
"""Moving the root directory is not supported at this time"""
779
class BzrBadParameterNotString(BzrBadParameter):
780
"""Parameter %(param)s is not a string or unicode string."""
783
class BzrBadParameterMissing(BzrBadParameter):
784
"""Parameter $(param)s is required but not present."""
787
class BzrBadParameterUnicode(BzrBadParameter):
788
"""Parameter %(param)s is unicode but only byte-strings are permitted."""
791
class BzrBadParameterContainsNewline(BzrBadParameter):
792
"""Parameter %(param)s contains a newline."""
795
class DependencyNotPresent(BzrNewError):
796
"""Unable to import library "%(library)s": %(error)s"""
798
def __init__(self, library, error):
799
BzrNewError.__init__(self, library=library, error=error)
802
class ParamikoNotPresent(DependencyNotPresent):
803
"""Unable to import paramiko (required for sftp support): %(error)s"""
805
def __init__(self, error):
806
DependencyNotPresent.__init__(self, 'paramiko', error)
809
class UninitializableFormat(BzrNewError):
810
"""Format %(format)s cannot be initialised by this version of bzr."""
812
def __init__(self, format):
813
BzrNewError.__init__(self)
817
class NoDiff3(BzrNewError):
818
"""Diff3 is not installed on this machine."""
821
class ExistingLimbo(BzrNewError):
822
"""This tree contains left-over files from a failed operation.
823
Please examine %(limbo_dir)s to see if it contains any files you wish to
824
keep, and delete it when you are done.
826
def __init__(self, limbo_dir):
827
BzrNewError.__init__(self)
828
self.limbo_dir = limbo_dir
831
class ImmortalLimbo(BzrNewError):
832
"""Unable to delete transform temporary directory $(limbo_dir)s.
833
Please examine %(limbo_dir)s to see if it contains any files you wish to
834
keep, and delete it when you are done.
836
def __init__(self, limbo_dir):
837
BzrNewError.__init__(self)
838
self.limbo_dir = limbo_dir
841
class OutOfDateTree(BzrNewError):
842
"""Working tree is out of date, please run 'bzr update'."""
844
def __init__(self, tree):
845
BzrNewError.__init__(self)
849
class MergeModifiedFormatError(BzrNewError):
850
"""Error in merge modified format"""
853
class ConflictFormatError(BzrNewError):
854
"""Format error in conflict listings"""
857
class CorruptRepository(BzrNewError):
858
"""An error has been detected in the repository %(repo_path)s.
859
Please run bzr reconcile on this repository."""
861
def __init__(self, repo):
862
BzrNewError.__init__(self)
863
self.repo_path = repo.bzrdir.root_transport.base
866
class UpgradeRequired(BzrNewError):
867
"""To use this feature you must upgrade your branch at %(path)s."""
869
def __init__(self, path):
870
BzrNewError.__init__(self)
874
class LocalRequiresBoundBranch(BzrNewError):
875
"""Cannot perform local-only commits on unbound branches."""
878
class MissingProgressBarFinish(BzrNewError):
879
"""A nested progress bar was not 'finished' correctly."""
882
class UnsupportedOperation(BzrNewError):
883
"""The method %(mname)s is not supported on objects of type %(tname)s."""
884
def __init__(self, method, method_self):
886
self.mname = method.__name__
887
self.tname = type(method_self).__name__
890
class BinaryFile(BzrNewError):
891
"""File is binary but should be text."""