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 PathNotChild(BzrNewError):
218
"""Path %(path)r is not a child of path %(base)r%(extra)s"""
219
def __init__(self, path, base, extra=None):
220
BzrNewError.__init__(self)
224
self.extra = ': ' + str(extra)
229
class NotBranchError(PathError):
230
"""Not a branch: %(path)s"""
233
class AlreadyBranchError(PathError):
234
"""Already a branch: %(path)s."""
237
class BranchExistsWithoutWorkingTree(PathError):
238
"""Directory contains a branch, but no working tree \
239
(use bzr checkout if you wish to build a working tree): %(path)s"""
242
class NoRepositoryPresent(BzrNewError):
243
"""Not repository present: %(path)r"""
244
def __init__(self, bzrdir):
245
BzrNewError.__init__(self)
246
self.path = bzrdir.transport.clone('..').base
249
class FileInWrongBranch(BzrNewError):
250
"""File %(path)s in not in branch %(branch_base)s."""
252
def __init__(self, branch, path):
253
BzrNewError.__init__(self)
255
self.branch_base = branch.base
259
class UnsupportedFormatError(BzrError):
260
"""Specified path is a bzr branch that we recognize but cannot read."""
262
return 'unsupported branch format: %s' % self.args[0]
265
class UnknownFormatError(BzrError):
266
"""Specified path is a bzr branch whose format we do not recognize."""
268
return 'unknown branch format: %s' % self.args[0]
271
class IncompatibleFormat(BzrNewError):
272
"""Format %(format)s is not compatible with .bzr version %(bzrdir)s."""
274
def __init__(self, format, bzrdir_format):
275
BzrNewError.__init__(self)
277
self.bzrdir = bzrdir_format
280
class NotVersionedError(BzrNewError):
281
"""%(path)s is not versioned"""
282
def __init__(self, path):
283
BzrNewError.__init__(self)
287
class PathsNotVersionedError(BzrNewError):
288
# used when reporting several paths are not versioned
289
"""Path(s) are not versioned: %(paths_as_string)s"""
291
def __init__(self, paths):
292
from bzrlib.osutils import quotefn
293
BzrNewError.__init__(self)
295
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
298
class PathsDoNotExist(BzrNewError):
299
"""Path(s) do not exist: %(paths_as_string)s"""
301
# used when reporting that paths are neither versioned nor in the working
304
def __init__(self, paths):
306
from bzrlib.osutils import quotefn
307
BzrNewError.__init__(self)
309
self.paths_as_string = ' '.join([quotefn(p) for p in paths])
312
class BadFileKindError(BzrError):
313
"""Specified file is of a kind that cannot be added.
315
(For example a symlink or device file.)"""
318
class ForbiddenFileError(BzrError):
319
"""Cannot operate on a file because it is a control file."""
322
class LockError(BzrNewError):
323
"""Lock error: %(message)s"""
324
# All exceptions from the lock/unlock functions should be from
325
# this exception class. They will be translated as necessary. The
326
# original exception is available as e.original_error
328
# New code should prefer to raise specific subclasses
329
def __init__(self, message):
330
self.message = message
333
class CommitNotPossible(LockError):
334
"""A commit was attempted but we do not have a write lock open."""
339
class AlreadyCommitted(LockError):
340
"""A rollback was requested, but is not able to be accomplished."""
345
class ReadOnlyError(LockError):
346
"""A write attempt was made in a read only transaction on %(obj)s"""
347
def __init__(self, obj):
351
class OutSideTransaction(BzrNewError):
352
"""A transaction related operation was attempted after the transaction finished."""
355
class ObjectNotLocked(LockError):
356
"""%(obj)r is not locked"""
357
# this can indicate that any particular object is not locked; see also
358
# LockNotHeld which means that a particular *lock* object is not held by
359
# the caller -- perhaps they should be unified.
360
def __init__(self, obj):
364
class ReadOnlyObjectDirtiedError(ReadOnlyError):
365
"""Cannot change object %(obj)r in read only transaction"""
366
def __init__(self, obj):
370
class UnlockableTransport(LockError):
371
"""Cannot lock: transport is read only: %(transport)s"""
372
def __init__(self, transport):
373
self.transport = transport
376
class LockContention(LockError):
377
"""Could not acquire lock %(lock)s"""
378
# TODO: show full url for lock, combining the transport and relative bits?
379
def __init__(self, lock):
383
class LockBroken(LockError):
384
"""Lock was broken while still open: %(lock)s - check storage consistency!"""
385
def __init__(self, lock):
389
class LockBreakMismatch(LockError):
390
"""Lock was released and re-acquired before being broken: %(lock)s: held by %(holder)r, wanted to break %(target)r"""
391
def __init__(self, lock, holder, target):
397
class LockNotHeld(LockError):
398
"""Lock not held: %(lock)s"""
399
def __init__(self, lock):
403
class PointlessCommit(BzrNewError):
404
"""No changes to commit"""
407
class UpgradeReadonly(BzrNewError):
408
"""Upgrade URL cannot work with readonly URL's."""
411
class UpToDateFormat(BzrNewError):
412
"""The branch format %(format)s is already at the most recent format."""
414
def __init__(self, format):
415
BzrNewError.__init__(self)
420
class StrictCommitFailed(Exception):
421
"""Commit refused because there are unknowns in the tree."""
424
class NoSuchRevision(BzrError):
425
def __init__(self, branch, revision):
427
self.revision = revision
428
msg = "Branch %s has no revision %s" % (branch, revision)
429
BzrError.__init__(self, msg)
432
class HistoryMissing(BzrError):
433
def __init__(self, branch, object_type, object_id):
435
BzrError.__init__(self,
436
'%s is missing %s {%s}'
437
% (branch, object_type, object_id))
440
class DivergedBranches(BzrError):
442
def __init__(self, branch1, branch2):
443
BzrError.__init__(self, "These branches have diverged. Try merge.")
444
self.branch1 = branch1
445
self.branch2 = branch2
448
class UnrelatedBranches(BzrCommandError):
450
msg = "Branches have no common ancestor, and no base revision"\
452
BzrCommandError.__init__(self, msg)
455
class NoCommonAncestor(BzrError):
456
def __init__(self, revision_a, revision_b):
457
msg = "Revisions have no common ancestor: %s %s." \
458
% (revision_a, revision_b)
459
BzrError.__init__(self, msg)
462
class NoCommonRoot(BzrError):
463
def __init__(self, revision_a, revision_b):
464
msg = "Revisions are not derived from the same root: %s %s." \
465
% (revision_a, revision_b)
466
BzrError.__init__(self, msg)
470
class NotAncestor(BzrError):
471
def __init__(self, rev_id, not_ancestor_id):
472
msg = "Revision %s is not an ancestor of %s" % (not_ancestor_id,
474
BzrError.__init__(self, msg)
476
self.not_ancestor_id = not_ancestor_id
479
class InstallFailed(BzrError):
480
def __init__(self, revisions):
481
msg = "Could not install revisions:\n%s" % " ,".join(revisions)
482
BzrError.__init__(self, msg)
483
self.revisions = revisions
486
class AmbiguousBase(BzrError):
487
def __init__(self, bases):
488
warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
490
msg = "The correct base is unclear, becase %s are all equally close" %\
492
BzrError.__init__(self, msg)
496
class NoCommits(BzrError):
497
def __init__(self, branch):
498
msg = "Branch %s has no commits." % branch
499
BzrError.__init__(self, msg)
502
class UnlistableStore(BzrError):
503
def __init__(self, store):
504
BzrError.__init__(self, "Store %s is not listable" % store)
508
class UnlistableBranch(BzrError):
509
def __init__(self, br):
510
BzrError.__init__(self, "Stores for branch %s are not listable" % br)
513
class BoundBranchOutOfDate(BzrNewError):
514
"""Bound branch %(branch)s is out of date with master branch %(master)s."""
515
def __init__(self, branch, master):
516
BzrNewError.__init__(self)
521
class CommitToDoubleBoundBranch(BzrNewError):
522
"""Cannot commit to branch %(branch)s. It is bound to %(master)s, which is bound to %(remote)s."""
523
def __init__(self, branch, master, remote):
524
BzrNewError.__init__(self)
530
class OverwriteBoundBranch(BzrNewError):
531
"""Cannot pull --overwrite to a branch which is bound %(branch)s"""
532
def __init__(self, branch):
533
BzrNewError.__init__(self)
537
class BoundBranchConnectionFailure(BzrNewError):
538
"""Unable to connect to target of bound branch %(branch)s => %(target)s: %(error)s"""
539
def __init__(self, branch, target, error):
540
BzrNewError.__init__(self)
546
class WeaveError(BzrNewError):
547
"""Error in processing weave: %(message)s"""
549
def __init__(self, message=None):
550
BzrNewError.__init__(self)
551
self.message = message
554
class WeaveRevisionAlreadyPresent(WeaveError):
555
"""Revision {%(revision_id)s} already present in %(weave)s"""
556
def __init__(self, revision_id, weave):
558
WeaveError.__init__(self)
559
self.revision_id = revision_id
563
class WeaveRevisionNotPresent(WeaveError):
564
"""Revision {%(revision_id)s} not present in %(weave)s"""
566
def __init__(self, revision_id, weave):
567
WeaveError.__init__(self)
568
self.revision_id = revision_id
572
class WeaveFormatError(WeaveError):
573
"""Weave invariant violated: %(what)s"""
575
def __init__(self, what):
576
WeaveError.__init__(self)
580
class WeaveParentMismatch(WeaveError):
581
"""Parents are mismatched between two revisions."""
584
class WeaveInvalidChecksum(WeaveError):
585
"""Text did not match it's checksum: %(message)s"""
588
class WeaveTextDiffers(WeaveError):
589
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
591
def __init__(self, revision_id, weave_a, weave_b):
592
WeaveError.__init__(self)
593
self.revision_id = revision_id
594
self.weave_a = weave_a
595
self.weave_b = weave_b
598
class WeaveTextDiffers(WeaveError):
599
"""Weaves differ on text content. Revision: {%(revision_id)s}, %(weave_a)s, %(weave_b)s"""
601
def __init__(self, revision_id, weave_a, weave_b):
602
WeaveError.__init__(self)
603
self.revision_id = revision_id
604
self.weave_a = weave_a
605
self.weave_b = weave_b
608
class VersionedFileError(BzrNewError):
609
"""Versioned file error."""
612
class RevisionNotPresent(VersionedFileError):
613
"""Revision {%(revision_id)s} not 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 RevisionAlreadyPresent(VersionedFileError):
622
"""Revision {%(revision_id)s} already 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 KnitError(BzrNewError):
634
class KnitHeaderError(KnitError):
635
"""Knit header error: %(badline)r unexpected"""
637
def __init__(self, badline):
638
KnitError.__init__(self)
639
self.badline = badline
642
class KnitCorrupt(KnitError):
643
"""Knit %(filename)s corrupt: %(how)s"""
645
def __init__(self, filename, how):
646
KnitError.__init__(self)
647
self.filename = filename
651
class NoSuchExportFormat(BzrNewError):
652
"""Export format %(format)r not supported"""
653
def __init__(self, format):
654
BzrNewError.__init__(self)
658
class TransportError(BzrError):
659
"""All errors thrown by Transport implementations should derive
662
def __init__(self, msg=None, orig_error=None):
663
if msg is None and orig_error is not None:
664
msg = str(orig_error)
665
BzrError.__init__(self, msg)
667
self.orig_error = orig_error
670
# A set of semi-meaningful errors which can be thrown
671
class TransportNotPossible(TransportError):
672
"""This is for transports where a specific function is explicitly not
673
possible. Such as pushing files to an HTTP server.
678
class ConnectionError(TransportError):
679
"""A connection problem prevents file retrieval.
680
This does not indicate whether the file exists or not; it indicates that a
681
precondition for requesting the file was not met.
683
def __init__(self, msg=None, orig_error=None):
684
TransportError.__init__(self, msg=msg, orig_error=orig_error)
687
class ConnectionReset(TransportError):
688
"""The connection has been closed."""
692
class ConflictsInTree(BzrError):
694
BzrError.__init__(self, "Working tree has conflicts.")
697
class ParseConfigError(BzrError):
698
def __init__(self, errors, filename):
701
message = "Error(s) parsing config file %s:\n%s" % \
702
(filename, ('\n'.join(e.message for e in errors)))
703
BzrError.__init__(self, message)
706
class SigningFailed(BzrError):
707
def __init__(self, command_line):
708
BzrError.__init__(self, "Failed to gpg sign data with command '%s'"
712
class WorkingTreeNotRevision(BzrError):
713
def __init__(self, tree):
714
BzrError.__init__(self, "The working tree for %s has changed since"
715
" last commit, but weave merge requires that it be"
716
" unchanged." % tree.basedir)
719
class CantReprocessAndShowBase(BzrNewError):
720
"""Can't reprocess and show base.
721
Reprocessing obscures relationship of conflicting lines to base."""
724
class GraphCycleError(BzrNewError):
725
"""Cycle in graph %(graph)r"""
726
def __init__(self, graph):
727
BzrNewError.__init__(self)
731
class NotConflicted(BzrNewError):
732
"""File %(filename)s is not conflicted."""
734
def __init__(self, filename):
735
BzrNewError.__init__(self)
736
self.filename = filename
739
class MustUseDecorated(Exception):
740
"""A decorating function has requested its original command be used.
742
This should never escape bzr, so does not need to be printable.
746
class MissingText(BzrNewError):
747
"""Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
749
def __init__(self, branch, text_revision, file_id):
750
BzrNewError.__init__(self)
752
self.base = branch.base
753
self.text_revision = text_revision
754
self.file_id = file_id
757
class DuplicateKey(BzrNewError):
758
"""Key %(key)s is already present in map"""
761
class MalformedTransform(BzrNewError):
762
"""Tree transform is malformed %(conflicts)r"""
765
class BzrBadParameter(BzrNewError):
766
"""A bad parameter : %(param)s is not usable.
768
This exception should never be thrown, but it is a base class for all
769
parameter-to-function errors.
771
def __init__(self, param):
772
BzrNewError.__init__(self)
776
class BzrBadParameterNotUnicode(BzrBadParameter):
777
"""Parameter %(param)s is neither unicode nor utf8."""
780
class ReusingTransform(BzrNewError):
781
"""Attempt to reuse a transform that has already been applied."""
784
class CantMoveRoot(BzrNewError):
785
"""Moving the root directory is not supported at this time"""
788
class BzrBadParameterNotString(BzrBadParameter):
789
"""Parameter %(param)s is not a string or unicode string."""
792
class BzrBadParameterMissing(BzrBadParameter):
793
"""Parameter $(param)s is required but not present."""
796
class BzrBadParameterUnicode(BzrBadParameter):
797
"""Parameter %(param)s is unicode but only byte-strings are permitted."""
800
class BzrBadParameterContainsNewline(BzrBadParameter):
801
"""Parameter %(param)s contains a newline."""
804
class DependencyNotPresent(BzrNewError):
805
"""Unable to import library "%(library)s": %(error)s"""
807
def __init__(self, library, error):
808
BzrNewError.__init__(self, library=library, error=error)
811
class ParamikoNotPresent(DependencyNotPresent):
812
"""Unable to import paramiko (required for sftp support): %(error)s"""
814
def __init__(self, error):
815
DependencyNotPresent.__init__(self, 'paramiko', error)
818
class UninitializableFormat(BzrNewError):
819
"""Format %(format)s cannot be initialised by this version of bzr."""
821
def __init__(self, format):
822
BzrNewError.__init__(self)
826
class NoDiff3(BzrNewError):
827
"""Diff3 is not installed on this machine."""
830
class ExistingLimbo(BzrNewError):
831
"""This tree contains left-over files from a failed operation.
832
Please examine %(limbo_dir)s to see if it contains any files you wish to
833
keep, and delete it when you are done.
835
def __init__(self, limbo_dir):
836
BzrNewError.__init__(self)
837
self.limbo_dir = limbo_dir
840
class ImmortalLimbo(BzrNewError):
841
"""Unable to delete transform temporary directory $(limbo_dir)s.
842
Please examine %(limbo_dir)s to see if it contains any files you wish to
843
keep, and delete it when you are done.
845
def __init__(self, limbo_dir):
846
BzrNewError.__init__(self)
847
self.limbo_dir = limbo_dir
850
class OutOfDateTree(BzrNewError):
851
"""Working tree is out of date, please run 'bzr update'."""
853
def __init__(self, tree):
854
BzrNewError.__init__(self)
858
class MergeModifiedFormatError(BzrNewError):
859
"""Error in merge modified format"""
862
class ConflictFormatError(BzrNewError):
863
"""Format error in conflict listings"""
866
class CorruptRepository(BzrNewError):
867
"""An error has been detected in the repository %(repo_path)s.
868
Please run bzr reconcile on this repository."""
870
def __init__(self, repo):
871
BzrNewError.__init__(self)
872
self.repo_path = repo.bzrdir.root_transport.base
875
class UpgradeRequired(BzrNewError):
876
"""To use this feature you must upgrade your branch at %(path)s."""
878
def __init__(self, path):
879
BzrNewError.__init__(self)
883
class LocalRequiresBoundBranch(BzrNewError):
884
"""Cannot perform local-only commits on unbound branches."""
887
class MissingProgressBarFinish(BzrNewError):
888
"""A nested progress bar was not 'finished' correctly."""
891
class UnsupportedOperation(BzrNewError):
892
"""The method %(mname)s is not supported on objects of type %(tname)s."""
893
def __init__(self, method, method_self):
895
self.mname = method.__name__
896
self.tname = type(method_self).__name__
899
class BinaryFile(BzrNewError):
900
"""File is binary but should be text."""
903
class IllegalPath(BzrNewError):
904
"""The path %(path)s is not permitted on this platform"""
906
def __init__(self, path):
907
BzrNewError.__init__(self)