~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-06-03 20:18:35 UTC
  • mfrom: (1185.82.137 w-changeset)
  • Revision ID: pqm@pqm.ubuntu.com-20060603201835-1c9a1725641ccd24
Implement bundles

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 Canonical
2
 
#
 
2
 
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.
7
 
#
 
7
 
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.
12
 
#
 
12
 
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
16
16
 
17
17
"""Exceptions for bzr, and reporting of them.
18
18
 
19
 
There are 3 different classes of error:
20
 
 
21
 
 * KeyboardInterrupt, and OSError with EPIPE - the program terminates 
22
 
   with an appropriate short message
23
 
 
24
 
 * User errors, indicating a problem caused by the user such as a bad URL.
25
 
   These are printed in a short form.
26
 
 
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.
30
 
 
31
19
Exceptions are caught at a high level to report errors to the user, and
32
20
might also be caught inside the program.  Therefore it needs to be
33
21
possible to convert them to a meaningful string, and also for them to be
56
44
Therefore:
57
45
 
58
46
 * create a new exception class for any class of error that can be
59
 
   usefully distinguished.  If no callers are likely to want to catch
60
 
   one but not another, don't worry about them.
61
 
 
62
 
 * the __str__ method should generate something useful; BzrError provides
63
 
   a good default implementation
64
 
 
65
 
Exception strings should start with a capital letter and should not have a
66
 
final fullstop.
 
47
   usefully distinguished.
 
48
 
 
49
 * the printable form of an exception is generated by the base class
 
50
   __str__ method
 
51
 
 
52
Exception strings should start with a capital letter and not have a final
 
53
fullstop.
67
54
"""
68
55
 
69
56
from warnings import warn
94
81
 
95
82
 
96
83
class BzrError(StandardError):
97
 
    
98
 
    is_user_error = True
99
 
    
100
84
    def __str__(self):
101
85
        # XXX: Should we show the exception class in 
102
86
        # exceptions that don't provide their own message?  
135
119
class BzrCheckError(BzrNewError):
136
120
    """Internal check failed: %(message)s"""
137
121
 
138
 
    is_user_error = False
139
 
 
140
122
    def __init__(self, message):
141
123
        BzrNewError.__init__(self)
142
124
        self.message = message
144
126
 
145
127
class InvalidEntryName(BzrNewError):
146
128
    """Invalid entry name: %(name)s"""
147
 
 
148
 
    is_user_error = False
149
 
 
150
129
    def __init__(self, name):
151
130
        BzrNewError.__init__(self)
152
131
        self.name = name
184
163
        self.url = url
185
164
 
186
165
 
187
 
class BzrCommandError(BzrNewError):
188
 
    """Error from user command"""
189
 
 
190
 
    is_user_error = True
191
 
 
192
 
    # Error from malformed user command; please avoid raising this as a
193
 
    # generic exception not caused by user input.
 
166
class BzrCommandError(BzrError):
 
167
    # Error from malformed user command
 
168
    # This is being misused as a generic exception
 
169
    # pleae subclass. RBC 20051030
194
170
    #
195
171
    # I think it's a waste of effort to differentiate between errors that
196
172
    # are not intended to be caught anyway.  UI code need not subclass
197
173
    # BzrCommandError, and non-UI code should not throw a subclass of
198
174
    # BzrCommandError.  ADHB 20051211
199
 
    def __init__(self, msg):
200
 
        self.msg = msg
201
 
 
202
175
    def __str__(self):
203
 
        return self.msg
 
176
        return self.args[0]
204
177
 
205
178
 
206
179
class BzrOptionError(BzrCommandError):
207
 
    """Error in command line options"""
 
180
    """Some missing or otherwise incorrect option was supplied."""
208
181
 
209
182
    
210
 
class StrictCommitFailed(BzrNewError):
211
 
    """Commit refused because there are unknown files in the tree"""
 
183
class StrictCommitFailed(Exception):
 
184
    """Commit refused because there are unknowns in the tree."""
212
185
 
213
186
 
214
187
# XXX: Should be unified with TransportError; they seem to represent the
245
218
    """Permission denied: %(path)r%(extra)s"""
246
219
 
247
220
 
248
 
class InvalidURL(PathError):
249
 
    """Invalid url supplied to transport: %(path)r%(extra)s"""
250
 
 
251
 
 
252
 
class InvalidURLJoin(PathError):
253
 
    """Invalid URL join request: %(args)s%(extra)s"""
254
 
 
255
 
    def __init__(self, msg, base, args):
256
 
        PathError.__init__(self, base, msg)
257
 
        self.args = [base]
258
 
        self.args.extend(args)
259
 
 
260
 
 
261
 
class UnsupportedProtocol(PathError):
262
 
    """Unsupported protocol for url "%(path)s"%(extra)s"""
263
 
 
264
 
    def __init__(self, url, extra):
265
 
        PathError.__init__(self, url, extra=extra)
266
 
 
267
 
 
268
221
class PathNotChild(BzrNewError):
269
222
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
270
 
 
271
 
    is_user_error = False
272
 
 
273
223
    def __init__(self, path, base, extra=None):
274
224
        BzrNewError.__init__(self)
275
225
        self.path = path
280
230
            self.extra = ''
281
231
 
282
232
 
283
 
class InvalidNormalization(PathError):
284
 
    """Path %(path)r is not unicode normalized"""
285
 
 
286
 
 
287
 
# TODO: This is given a URL; we try to unescape it but doing that from inside
288
 
# the exception object is a bit undesirable.
289
 
# TODO: Probably this behavior of should be a common superclass 
290
233
class NotBranchError(PathError):
291
234
    """Not a branch: %(path)s"""
292
235
 
293
 
    def __init__(self, path):
294
 
       import bzrlib.urlutils as urlutils
295
 
       self.path = urlutils.unescape_for_display(path, 'ascii')
296
 
 
297
236
 
298
237
class AlreadyBranchError(PathError):
299
238
    """Already a branch: %(path)s."""
304
243
(use bzr checkout if you wish to build a working tree): %(path)s"""
305
244
 
306
245
 
307
 
class AtomicFileAlreadyClosed(PathError):
308
 
    """'%(function)s' called on an AtomicFile after it was closed: %(path)s"""
309
 
 
310
 
    def __init__(self, path, function):
311
 
        PathError.__init__(self, path=path, extra=None)
312
 
        self.function = function
313
 
 
314
 
 
315
 
class InaccessibleParent(PathError):
316
 
    """Parent not accessible given base %(base)s and relative path %(path)s"""
317
 
 
318
 
    def __init__(self, path, base):
319
 
        PathError.__init__(self, path)
320
 
        self.base = base
321
 
 
322
 
 
323
246
class NoRepositoryPresent(BzrNewError):
324
247
    """No repository present: %(path)r"""
325
248
    def __init__(self, bzrdir):
337
260
        self.path = path
338
261
 
339
262
 
340
 
class UnsupportedFormatError(BzrNewError):
341
 
    """Unsupported branch format: %(format)s"""
342
 
 
343
 
 
344
 
class UnknownFormatError(BzrNewError):
345
 
    """Unknown branch format: %(format)r"""
 
263
class UnsupportedFormatError(BzrError):
 
264
    """Specified path is a bzr branch that we recognize but cannot read."""
 
265
    def __str__(self):
 
266
        return 'unsupported branch format: %s' % self.args[0]
 
267
 
 
268
 
 
269
class UnknownFormatError(BzrError):
 
270
    """Specified path is a bzr branch whose format we do not recognize."""
 
271
    def __str__(self):
 
272
        return 'unknown branch format: %s' % self.args[0]
346
273
 
347
274
 
348
275
class IncompatibleFormat(BzrNewError):
386
313
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
387
314
 
388
315
 
389
 
class BadFileKindError(BzrNewError):
390
 
    """Cannot operate on %(filename)s of unsupported kind %(kind)s"""
391
 
 
392
 
 
393
 
class ForbiddenControlFileError(BzrNewError):
394
 
    """Cannot operate on %(filename)s because it is a control file"""
 
316
class BadFileKindError(BzrError):
 
317
    """Specified file is of a kind that cannot be added.
 
318
 
 
319
    (For example a symlink or device file.)"""
 
320
 
 
321
 
 
322
class ForbiddenFileError(BzrError):
 
323
    """Cannot operate on a file because it is a control file."""
395
324
 
396
325
 
397
326
class LockError(BzrNewError):
429
358
 
430
359
class ObjectNotLocked(LockError):
431
360
    """%(obj)r is not locked"""
432
 
 
433
 
    is_user_error = False
434
 
 
435
361
    # this can indicate that any particular object is not locked; see also
436
362
    # LockNotHeld which means that a particular *lock* object is not held by
437
363
    # the caller -- perhaps they should be unified.
499
425
    """Commit refused because there are unknowns in the tree."""
500
426
 
501
427
 
502
 
class NoSuchRevision(BzrNewError):
503
 
    """Branch %(branch)s has no revision %(revision)s"""
504
 
 
505
 
    is_user_error = False
506
 
 
 
428
class NoSuchRevision(BzrError):
507
429
    def __init__(self, branch, revision):
508
430
        self.branch = branch
509
431
        self.revision = revision
 
432
        msg = "Branch %s has no revision %s" % (branch, revision)
 
433
        BzrError.__init__(self, msg)
510
434
 
511
435
 
512
436
class HistoryMissing(BzrError):
517
441
                          % (branch, object_type, object_id))
518
442
 
519
443
 
520
 
class DivergedBranches(BzrNewError):
521
 
    "These branches have diverged.  Use the merge command to reconcile them."""
522
 
 
523
 
    is_user_error = True
 
444
class DivergedBranches(BzrError):
524
445
 
525
446
    def __init__(self, branch1, branch2):
 
447
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
526
448
        self.branch1 = branch1
527
449
        self.branch2 = branch2
528
450
 
529
451
 
530
 
class UnrelatedBranches(BzrNewError):
531
 
    "Branches have no common ancestor, and no merge base revision was specified."
532
 
 
533
 
    is_user_error = True
534
 
 
535
 
 
536
 
class NoCommonAncestor(BzrNewError):
537
 
    "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
538
 
 
 
452
class UnrelatedBranches(BzrCommandError):
 
453
    def __init__(self):
 
454
        msg = "Branches have no common ancestor, and no base revision"\
 
455
            " specified."
 
456
        BzrCommandError.__init__(self, msg)
 
457
 
 
458
 
 
459
class NoCommonAncestor(BzrError):
539
460
    def __init__(self, revision_a, revision_b):
540
 
        self.revision_a = revision_a
541
 
        self.revision_b = revision_b
 
461
        msg = "Revisions have no common ancestor: %s %s." \
 
462
            % (revision_a, revision_b) 
 
463
        BzrError.__init__(self, msg)
542
464
 
543
465
 
544
466
class NoCommonRoot(BzrError):
569
491
    def __init__(self, bases):
570
492
        warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
571
493
                DeprecationWarning)
572
 
        msg = "The correct base is unclear, because %s are all equally close" %\
 
494
        msg = "The correct base is unclear, becase %s are all equally close" %\
573
495
            ", ".join(bases)
574
496
        BzrError.__init__(self, msg)
575
497
        self.bases = bases
737
659
        self.format = format
738
660
 
739
661
 
740
 
class TransportError(BzrNewError):
741
 
    """Transport error: %(msg)s %(orig_error)s"""
742
 
 
 
662
class TransportError(BzrError):
 
663
    """All errors thrown by Transport implementations should derive
 
664
    from this class.
 
665
    """
743
666
    def __init__(self, msg=None, orig_error=None):
744
667
        if msg is None and orig_error is not None:
745
668
            msg = str(orig_error)
746
 
        if orig_error is None:
747
 
            orig_error = ''
748
 
        if msg is None:
749
 
            msg =  ''
 
669
        BzrError.__init__(self, msg)
750
670
        self.msg = msg
751
671
        self.orig_error = orig_error
752
 
        BzrNewError.__init__(self)
753
672
 
754
673
 
755
674
# A set of semi-meaningful errors which can be thrown
756
675
class TransportNotPossible(TransportError):
757
 
    """Transport operation not possible: %(msg)s %(orig_error)%"""
 
676
    """This is for transports where a specific function is explicitly not
 
677
    possible. Such as pushing files to an HTTP server.
 
678
    """
 
679
    pass
758
680
 
759
681
 
760
682
class ConnectionError(TransportError):
761
 
    """Connection error: %(msg)s %(orig_error)s"""
 
683
    """A connection problem prevents file retrieval.
 
684
    This does not indicate whether the file exists or not; it indicates that a
 
685
    precondition for requesting the file was not met.
 
686
    """
 
687
    def __init__(self, msg=None, orig_error=None):
 
688
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
762
689
 
763
690
 
764
691
class ConnectionReset(TransportError):
765
 
    """Connection closed: %(msg)s %(orig_error)s"""
766
 
 
767
 
 
768
 
class InvalidRange(TransportError):
769
 
    """Invalid range access."""
770
 
    
771
 
    def __init__(self, path, offset):
772
 
        TransportError.__init__(self, ("Invalid range access in %s at %d"
773
 
                                       % (path, offset)))
774
 
 
775
 
 
776
 
class InvalidHttpResponse(TransportError):
777
 
    """Invalid http response for %(path)s: %(msg)s"""
778
 
 
779
 
    def __init__(self, path, msg, orig_error=None):
780
 
        self.path = path
781
 
        TransportError.__init__(self, msg, orig_error=orig_error)
782
 
 
783
 
 
784
 
class InvalidHttpRange(InvalidHttpResponse):
785
 
    """Invalid http range "%(range)s" for %(path)s: %(msg)s"""
786
 
    
787
 
    def __init__(self, path, range, msg):
788
 
        self.range = range
789
 
        InvalidHttpResponse.__init__(self, path, msg)
790
 
 
791
 
 
792
 
class InvalidHttpContentType(InvalidHttpResponse):
793
 
    """Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s"""
794
 
    
795
 
    def __init__(self, path, ctype, msg):
796
 
        self.ctype = ctype
797
 
        InvalidHttpResponse.__init__(self, path, msg)
 
692
    """The connection has been closed."""
 
693
    pass
798
694
 
799
695
 
800
696
class ConflictsInTree(BzrError):
946
842
        self.format = format
947
843
 
948
844
 
949
 
class NoDiff(BzrNewError):
950
 
    """Diff is not installed on this machine: %(msg)s"""
951
 
 
952
 
    def __init__(self, msg):
953
 
        BzrNewError.__init__(self, msg=msg)
954
 
 
955
 
 
956
845
class NoDiff3(BzrNewError):
957
846
    """Diff3 is not installed on this machine."""
958
847
 
1018
907
    """A nested progress bar was not 'finished' correctly."""
1019
908
 
1020
909
 
1021
 
class InvalidProgressBarType(BzrNewError):
1022
 
    """Environment variable BZR_PROGRESS_BAR='%(bar_type)s is not a supported type
1023
 
Select one of: %(valid_types)s"""
1024
 
 
1025
 
    def __init__(self, bar_type, valid_types):
1026
 
        BzrNewError.__init__(self, bar_type=bar_type, valid_types=valid_types)
1027
 
 
1028
 
 
1029
910
class UnsupportedOperation(BzrNewError):
1030
911
    """The method %(mname)s is not supported on objects of type %(tname)s."""
1031
912
    def __init__(self, method, method_self):
1057
938
        self.measured = measured
1058
939
 
1059
940
 
1060
 
class NotABundle(BzrNewError):
1061
 
    """Not a bzr revision-bundle: %(text)r"""
1062
 
 
1063
 
    def __init__(self, text):
1064
 
        BzrNewError.__init__(self)
1065
 
        self.text = text
1066
 
 
1067
 
 
1068
 
class BadBundle(BzrNewError): 
1069
 
    """Bad bzr revision-bundle: %(text)r"""
1070
 
 
1071
 
    def __init__(self, text):
1072
 
        BzrNewError.__init__(self)
1073
 
        self.text = text
1074
 
 
1075
 
 
1076
 
class MalformedHeader(BadBundle): 
1077
 
    """Malformed bzr revision-bundle header: %(text)r"""
1078
 
 
1079
 
    def __init__(self, text):
1080
 
        BzrNewError.__init__(self)
1081
 
        self.text = text
1082
 
 
1083
 
 
1084
 
class MalformedPatches(BadBundle): 
1085
 
    """Malformed patches in bzr revision-bundle: %(text)r"""
1086
 
 
1087
 
    def __init__(self, text):
1088
 
        BzrNewError.__init__(self)
1089
 
        self.text = text
1090
 
 
1091
 
 
1092
 
class MalformedFooter(BadBundle): 
1093
 
    """Malformed footer in bzr revision-bundle: %(text)r"""
1094
 
 
1095
 
    def __init__(self, text):
1096
 
        BzrNewError.__init__(self)
1097
 
        self.text = text
1098
 
 
1099
 
class UnsupportedEOLMarker(BadBundle):
1100
 
    """End of line marker was not \\n in bzr revision-bundle"""    
1101
 
 
1102
 
    def __init__(self):
1103
 
        BzrNewError.__init__(self)    
 
941
class BadBundle(Exception): pass
 
942
 
 
943
 
 
944
class MalformedHeader(BadBundle): pass
 
945
 
 
946
 
 
947
class MalformedPatches(BadBundle): pass
 
948
 
 
949
 
 
950
class MalformedFooter(BadBundle): pass