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 InvalidURL(PathError):
214
"""Invalid url supplied to transport: %(path)r%(extra)s"""
217
class InvalidURLJoin(PathError):
218
"""Invalid URL join request: %(args)s%(extra)s"""
220
def __init__(self, msg, base, args):
221
PathError.__init__(self, base, msg)
223
self.args.extend(args)
226
class PathNotChild(BzrNewError):
227
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
228
def __init__(self, path, base, extra=None):
229
BzrNewError.__init__(self)
233
self.extra = ': ' + str(extra)
238
class NotBranchError(PathError):
239
"""Not a branch: %(path)s"""
242
class AlreadyBranchError(PathError):
243
"""Already a branch: %(path)s."""
246
class BranchExistsWithoutWorkingTree(PathError):
247
"""Directory contains a branch, but no working tree \
248
(use bzr checkout if you wish to build a working tree): %(path)s"""
251
class NoRepositoryPresent(BzrNewError):
252
"""No repository present: %(path)r"""
253
def __init__(self, bzrdir):
254
BzrNewError.__init__(self)
255
self.path = bzrdir.transport.clone('..').base
258
class FileInWrongBranch(BzrNewError):
259
"""File %(path)s in not in branch %(branch_base)s."""
261
def __init__(self, branch, path):
262
BzrNewError.__init__(self)
264
self.branch_base = branch.base
268
class UnsupportedFormatError(BzrError):
269
"""Specified path is a bzr branch that we recognize but cannot read."""
271
return 'unsupported branch format: %s' % self.args[0]
274
class UnknownFormatError(BzrError):
275
"""Specified path is a bzr branch whose format we do not recognize."""
277
return 'unknown branch format: %s' % self.args[0]
280
class IncompatibleFormat(BzrNewError):
281
"""Format %(format)s is not compatible with .bzr version %(bzrdir)s."""
283
def __init__(self, format, bzrdir_format):
284
BzrNewError.__init__(self)
286
self.bzrdir = bzrdir_format
289
class NotVersionedError(BzrNewError):
290
"""%(path)s is not versioned"""
291
def __init__(self, path):
292
BzrNewError.__init__(self)
296
class PathsNotVersionedError(BzrNewError):
297
# used when reporting several paths are not versioned
298
"""Path(s) are not versioned: %(paths_as_string)s"""
300
def __init__(self, paths):
301
from bzrlib.osutils import quotefn
302
BzrNewError.__init__(self)
304
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
307
class PathsDoNotExist(BzrNewError):
308
"""Path(s) do not exist: %(paths_as_string)s"""
310
# used when reporting that paths are neither versioned nor in the working
313
def __init__(self, paths):
315
from bzrlib.osutils import quotefn
316
BzrNewError.__init__(self)
318
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
321
class BadFileKindError(BzrError):
322
"""Specified file is of a kind that cannot be added.
324
(For example a symlink or device file.)"""
327
class ForbiddenFileError(BzrError):
328
"""Cannot operate on a file because it is a control file."""
331
class LockError(BzrNewError):
332
"""Lock error: %(message)s"""
333
# All exceptions from the lock/unlock functions should be from
334
# this exception class. They will be translated as necessary. The
335
# original exception is available as e.original_error
337
# New code should prefer to raise specific subclasses
338
def __init__(self, message):
339
self.message = message
342
class CommitNotPossible(LockError):
343
"""A commit was attempted but we do not have a write lock open."""
348
class AlreadyCommitted(LockError):
349
"""A rollback was requested, but is not able to be accomplished."""
354
class ReadOnlyError(LockError):
355
"""A write attempt was made in a read only transaction on %(obj)s"""
356
def __init__(self, obj):
360
class OutSideTransaction(BzrNewError):
361
"""A transaction related operation was attempted after the transaction finished."""
364
class ObjectNotLocked(LockError):
365
"""%(obj)r is not locked"""
366
# this can indicate that any particular object is not locked; see also
367
# LockNotHeld which means that a particular *lock* object is not held by
368
# the caller -- perhaps they should be unified.
369
def __init__(self, obj):
373
class ReadOnlyObjectDirtiedError(ReadOnlyError):
374
"""Cannot change object %(obj)r in read only transaction"""
375
def __init__(self, obj):
379
class UnlockableTransport(LockError):
380
"""Cannot lock: transport is read only: %(transport)s"""
381
def __init__(self, transport):
382
self.transport = transport
385
class LockContention(LockError):
386
"""Could not acquire lock %(lock)s"""
387
# TODO: show full url for lock, combining the transport and relative bits?
388
def __init__(self, lock):
392
class LockBroken(LockError):
393
"""Lock was broken while still open: %(lock)s - check storage consistency!"""
394
def __init__(self, lock):
398
class LockBreakMismatch(LockError):
399
"""Lock was released and re-acquired before being broken: %(lock)s: held by %(holder)r, wanted to break %(target)r"""
400
def __init__(self, lock, holder, target):
406
class LockNotHeld(LockError):
407
"""Lock not held: %(lock)s"""
408
def __init__(self, lock):
412
class PointlessCommit(BzrNewError):
413
"""No changes to commit"""
416
class UpgradeReadonly(BzrNewError):
417
"""Upgrade URL cannot work with readonly URL's."""
420
class UpToDateFormat(BzrNewError):
421
"""The branch format %(format)s is already at the most recent format."""
423
def __init__(self, format):
424
BzrNewError.__init__(self)
429
class StrictCommitFailed(Exception):
430
"""Commit refused because there are unknowns in the tree."""
433
class NoSuchRevision(BzrError):
434
def __init__(self, branch, revision):
436
self.revision = revision
437
msg = "Branch %s has no revision %s" % (branch, revision)
438
BzrError.__init__(self, msg)
441
class HistoryMissing(BzrError):
442
def __init__(self, branch, object_type, object_id):
444
BzrError.__init__(self,
445
'%s is missing %s {%s}'
446
% (branch, object_type, object_id))
449
class DivergedBranches(BzrError):
451
def __init__(self, branch1, branch2):
452
BzrError.__init__(self, "These branches have diverged. Try merge.")
453
self.branch1 = branch1
454
self.branch2 = branch2
457
class UnrelatedBranches(BzrCommandError):
459
msg = "Branches have no common ancestor, and no base revision"\
461
BzrCommandError.__init__(self, msg)
464
class NoCommonAncestor(BzrError):
465
def __init__(self, revision_a, revision_b):
466
msg = "Revisions have no common ancestor: %s %s." \
467
% (revision_a, revision_b)
468
BzrError.__init__(self, msg)
471
class NoCommonRoot(BzrError):
472
def __init__(self, revision_a, revision_b):
473
msg = "Revisions are not derived from the same root: %s %s." \
474
% (revision_a, revision_b)
475
BzrError.__init__(self, msg)
479
class NotAncestor(BzrError):
480
def __init__(self, rev_id, not_ancestor_id):
481
msg = "Revision %s is not an ancestor of %s" % (not_ancestor_id,
483
BzrError.__init__(self, msg)
485
self.not_ancestor_id = not_ancestor_id
488
class InstallFailed(BzrError):
489
def __init__(self, revisions):
490
msg = "Could not install revisions:\n%s" % " ,".join(revisions)
491
BzrError.__init__(self, msg)
492
self.revisions = revisions
495
class AmbiguousBase(BzrError):
496
def __init__(self, bases):
497
warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
499
msg = "The correct base is unclear, becase %s are all equally close" %\
501
BzrError.__init__(self, msg)
505
class NoCommits(BzrError):
506
def __init__(self, branch):
507
msg = "Branch %s has no commits." % branch
508
BzrError.__init__(self, msg)
511
class UnlistableStore(BzrError):
512
def __init__(self, store):
513
BzrError.__init__(self, "Store %s is not listable" % store)
517
class UnlistableBranch(BzrError):
518
def __init__(self, br):
519
BzrError.__init__(self, "Stores for branch %s are not listable" % br)
522
class BoundBranchOutOfDate(BzrNewError):
523
"""Bound branch %(branch)s is out of date with master branch %(master)s."""
524
def __init__(self, branch, master):
525
BzrNewError.__init__(self)
530
class CommitToDoubleBoundBranch(BzrNewError):
531
"""Cannot commit to branch %(branch)s. It is bound to %(master)s, which is bound to %(remote)s."""
532
def __init__(self, branch, master, remote):
533
BzrNewError.__init__(self)
539
class OverwriteBoundBranch(BzrNewError):
540
"""Cannot pull --overwrite to a branch which is bound %(branch)s"""
541
def __init__(self, branch):
542
BzrNewError.__init__(self)
546
class BoundBranchConnectionFailure(BzrNewError):
547
"""Unable to connect to target of bound branch %(branch)s => %(target)s: %(error)s"""
548
def __init__(self, branch, target, error):
549
BzrNewError.__init__(self)
555
class WeaveError(BzrNewError):
556
"""Error in processing weave: %(message)s"""
558
def __init__(self, message=None):
559
BzrNewError.__init__(self)
560
self.message = message
563
class WeaveRevisionAlreadyPresent(WeaveError):
564
"""Revision {%(revision_id)s} already present in %(weave)s"""
565
def __init__(self, revision_id, weave):
567
WeaveError.__init__(self)
568
self.revision_id = revision_id
572
class WeaveRevisionNotPresent(WeaveError):
573
"""Revision {%(revision_id)s} not present in %(weave)s"""
575
def __init__(self, revision_id, weave):
576
WeaveError.__init__(self)
577
self.revision_id = revision_id
581
class WeaveFormatError(WeaveError):
582
"""Weave invariant violated: %(what)s"""
584
def __init__(self, what):
585
WeaveError.__init__(self)
589
class WeaveParentMismatch(WeaveError):
590
"""Parents are mismatched between two revisions."""
593
class WeaveInvalidChecksum(WeaveError):
594
"""Text did not match it's checksum: %(message)s"""
597
class WeaveTextDiffers(WeaveError):
598
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
600
def __init__(self, revision_id, weave_a, weave_b):
601
WeaveError.__init__(self)
602
self.revision_id = revision_id
603
self.weave_a = weave_a
604
self.weave_b = weave_b
607
class WeaveTextDiffers(WeaveError):
608
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
610
def __init__(self, revision_id, weave_a, weave_b):
611
WeaveError.__init__(self)
612
self.revision_id = revision_id
613
self.weave_a = weave_a
614
self.weave_b = weave_b
617
class VersionedFileError(BzrNewError):
618
"""Versioned file error."""
621
class RevisionNotPresent(VersionedFileError):
622
"""Revision {%(revision_id)s} not present in %(file_id)s."""
624
def __init__(self, revision_id, file_id):
625
VersionedFileError.__init__(self)
626
self.revision_id = revision_id
627
self.file_id = file_id
630
class RevisionAlreadyPresent(VersionedFileError):
631
"""Revision {%(revision_id)s} already present in %(file_id)s."""
633
def __init__(self, revision_id, file_id):
634
VersionedFileError.__init__(self)
635
self.revision_id = revision_id
636
self.file_id = file_id
639
class KnitError(BzrNewError):
643
class KnitHeaderError(KnitError):
644
"""Knit header error: %(badline)r unexpected"""
646
def __init__(self, badline):
647
KnitError.__init__(self)
648
self.badline = badline
651
class KnitCorrupt(KnitError):
652
"""Knit %(filename)s corrupt: %(how)s"""
654
def __init__(self, filename, how):
655
KnitError.__init__(self)
656
self.filename = filename
660
class NoSuchExportFormat(BzrNewError):
661
"""Export format %(format)r not supported"""
662
def __init__(self, format):
663
BzrNewError.__init__(self)
667
class TransportError(BzrError):
668
"""All errors thrown by Transport implementations should derive
671
def __init__(self, msg=None, orig_error=None):
672
if msg is None and orig_error is not None:
673
msg = str(orig_error)
674
BzrError.__init__(self, msg)
676
self.orig_error = orig_error
679
# A set of semi-meaningful errors which can be thrown
680
class TransportNotPossible(TransportError):
681
"""This is for transports where a specific function is explicitly not
682
possible. Such as pushing files to an HTTP server.
687
class ConnectionError(TransportError):
688
"""A connection problem prevents file retrieval.
689
This does not indicate whether the file exists or not; it indicates that a
690
precondition for requesting the file was not met.
692
def __init__(self, msg=None, orig_error=None):
693
TransportError.__init__(self, msg=msg, orig_error=orig_error)
696
class ConnectionReset(TransportError):
697
"""The connection has been closed."""
701
class ConflictsInTree(BzrError):
703
BzrError.__init__(self, "Working tree has conflicts.")
706
class ParseConfigError(BzrError):
707
def __init__(self, errors, filename):
710
message = "Error(s) parsing config file %s:\n%s" % \
711
(filename, ('\n'.join(e.message for e in errors)))
712
BzrError.__init__(self, message)
715
class SigningFailed(BzrError):
716
def __init__(self, command_line):
717
BzrError.__init__(self, "Failed to gpg sign data with command '%s'"
721
class WorkingTreeNotRevision(BzrError):
722
def __init__(self, tree):
723
BzrError.__init__(self, "The working tree for %s has changed since"
724
" last commit, but weave merge requires that it be"
725
" unchanged." % tree.basedir)
728
class CantReprocessAndShowBase(BzrNewError):
729
"""Can't reprocess and show base.
730
Reprocessing obscures relationship of conflicting lines to base."""
733
class GraphCycleError(BzrNewError):
734
"""Cycle in graph %(graph)r"""
735
def __init__(self, graph):
736
BzrNewError.__init__(self)
740
class NotConflicted(BzrNewError):
741
"""File %(filename)s is not conflicted."""
743
def __init__(self, filename):
744
BzrNewError.__init__(self)
745
self.filename = filename
748
class MustUseDecorated(Exception):
749
"""A decorating function has requested its original command be used.
751
This should never escape bzr, so does not need to be printable.
755
class MissingText(BzrNewError):
756
"""Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
758
def __init__(self, branch, text_revision, file_id):
759
BzrNewError.__init__(self)
761
self.base = branch.base
762
self.text_revision = text_revision
763
self.file_id = file_id
766
class DuplicateKey(BzrNewError):
767
"""Key %(key)s is already present in map"""
770
class MalformedTransform(BzrNewError):
771
"""Tree transform is malformed %(conflicts)r"""
774
class BzrBadParameter(BzrNewError):
775
"""A bad parameter : %(param)s is not usable.
777
This exception should never be thrown, but it is a base class for all
778
parameter-to-function errors.
780
def __init__(self, param):
781
BzrNewError.__init__(self)
785
class BzrBadParameterNotUnicode(BzrBadParameter):
786
"""Parameter %(param)s is neither unicode nor utf8."""
789
class ReusingTransform(BzrNewError):
790
"""Attempt to reuse a transform that has already been applied."""
793
class CantMoveRoot(BzrNewError):
794
"""Moving the root directory is not supported at this time"""
797
class BzrBadParameterNotString(BzrBadParameter):
798
"""Parameter %(param)s is not a string or unicode string."""
801
class BzrBadParameterMissing(BzrBadParameter):
802
"""Parameter $(param)s is required but not present."""
805
class BzrBadParameterUnicode(BzrBadParameter):
806
"""Parameter %(param)s is unicode but only byte-strings are permitted."""
809
class BzrBadParameterContainsNewline(BzrBadParameter):
810
"""Parameter %(param)s contains a newline."""
813
class DependencyNotPresent(BzrNewError):
814
"""Unable to import library "%(library)s": %(error)s"""
816
def __init__(self, library, error):
817
BzrNewError.__init__(self, library=library, error=error)
820
class ParamikoNotPresent(DependencyNotPresent):
821
"""Unable to import paramiko (required for sftp support): %(error)s"""
823
def __init__(self, error):
824
DependencyNotPresent.__init__(self, 'paramiko', error)
827
class UninitializableFormat(BzrNewError):
828
"""Format %(format)s cannot be initialised by this version of bzr."""
830
def __init__(self, format):
831
BzrNewError.__init__(self)
835
class NoDiff3(BzrNewError):
836
"""Diff3 is not installed on this machine."""
839
class ExistingLimbo(BzrNewError):
840
"""This tree contains left-over files from a failed operation.
841
Please examine %(limbo_dir)s to see if it contains any files you wish to
842
keep, and delete it when you are done.
844
def __init__(self, limbo_dir):
845
BzrNewError.__init__(self)
846
self.limbo_dir = limbo_dir
849
class ImmortalLimbo(BzrNewError):
850
"""Unable to delete transform temporary directory $(limbo_dir)s.
851
Please examine %(limbo_dir)s to see if it contains any files you wish to
852
keep, and delete it when you are done.
854
def __init__(self, limbo_dir):
855
BzrNewError.__init__(self)
856
self.limbo_dir = limbo_dir
859
class OutOfDateTree(BzrNewError):
860
"""Working tree is out of date, please run 'bzr update'."""
862
def __init__(self, tree):
863
BzrNewError.__init__(self)
867
class MergeModifiedFormatError(BzrNewError):
868
"""Error in merge modified format"""
871
class ConflictFormatError(BzrNewError):
872
"""Format error in conflict listings"""
875
class CorruptRepository(BzrNewError):
876
"""An error has been detected in the repository %(repo_path)s.
877
Please run bzr reconcile on this repository."""
879
def __init__(self, repo):
880
BzrNewError.__init__(self)
881
self.repo_path = repo.bzrdir.root_transport.base
884
class UpgradeRequired(BzrNewError):
885
"""To use this feature you must upgrade your branch at %(path)s."""
887
def __init__(self, path):
888
BzrNewError.__init__(self)
892
class LocalRequiresBoundBranch(BzrNewError):
893
"""Cannot perform local-only commits on unbound branches."""
896
class MissingProgressBarFinish(BzrNewError):
897
"""A nested progress bar was not 'finished' correctly."""
900
class UnsupportedOperation(BzrNewError):
901
"""The method %(mname)s is not supported on objects of type %(tname)s."""
902
def __init__(self, method, method_self):
904
self.mname = method.__name__
905
self.tname = type(method_self).__name__
908
class BinaryFile(BzrNewError):
909
"""File is binary but should be text."""
912
class IllegalPath(BzrNewError):
913
"""The path %(path)s is not permitted on this platform"""
915
def __init__(self, path):
916
BzrNewError.__init__(self)