/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-08-24 00:22:22 UTC
  • mfrom: (1952.1.3 aftp-56472)
  • Revision ID: pqm@pqm.ubuntu.com-20060824002222-09d7139ba6ad0e6c
(ghozzy) fix aftp:// support bug #56472

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
 
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
34
46
... except:
35
47
...   print sys.exc_type
36
48
...   print sys.exc_value
37
 
...   path = getattr(sys.exc_value, 'path')
 
49
...   path = getattr(sys.exc_value, 'path', None)
38
50
...   if path is not None:
39
51
...     print path
40
52
bzrlib.errors.NotBranchError
44
56
Therefore:
45
57
 
46
58
 * create a new exception class for any class of error that can be
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.
 
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.
54
67
"""
55
68
 
56
69
from warnings import warn
57
70
 
 
71
from bzrlib.patches import (PatchSyntax, 
 
72
                            PatchConflict, 
 
73
                            MalformedPatchHeader,
 
74
                            MalformedHunkHeader,
 
75
                            MalformedLine,)
 
76
 
 
77
 
58
78
# based on Scott James Remnant's hct error classes
59
79
 
60
80
# TODO: is there any value in providing the .args field used by standard
68
88
# TODO: Convert all the other error classes here to BzrNewError, and eliminate
69
89
# the old one.
70
90
 
 
91
# TODO: The pattern (from hct) of using classes docstrings as message
 
92
# templates is cute but maybe not such a great idea - perhaps should have a
 
93
# separate static message_template.
 
94
 
71
95
 
72
96
class BzrError(StandardError):
 
97
    
 
98
    is_user_error = True
 
99
    
73
100
    def __str__(self):
74
101
        # XXX: Should we show the exception class in 
75
102
        # exceptions that don't provide their own message?  
99
126
 
100
127
    def __str__(self):
101
128
        try:
102
 
            return self.__doc__ % self.__dict__
 
129
            # __str__() should always return a 'str' object
 
130
            # never a 'unicode' object.
 
131
            s = self.__doc__ % self.__dict__
 
132
            if isinstance(s, unicode):
 
133
                return s.encode('utf8')
 
134
            return s
103
135
        except (NameError, ValueError, KeyError), e:
104
136
            return 'Unprintable exception %s: %s' \
105
137
                % (self.__class__.__name__, str(e))
108
140
class BzrCheckError(BzrNewError):
109
141
    """Internal check failed: %(message)s"""
110
142
 
 
143
    is_user_error = False
 
144
 
111
145
    def __init__(self, message):
112
146
        BzrNewError.__init__(self)
113
147
        self.message = message
115
149
 
116
150
class InvalidEntryName(BzrNewError):
117
151
    """Invalid entry name: %(name)s"""
 
152
 
 
153
    is_user_error = False
 
154
 
118
155
    def __init__(self, name):
119
156
        BzrNewError.__init__(self)
120
157
        self.name = name
130
167
class InvalidRevisionId(BzrNewError):
131
168
    """Invalid revision-id {%(revision_id)s} in %(branch)s"""
132
169
    def __init__(self, revision_id, branch):
 
170
        # branch can be any string or object with __str__ defined
133
171
        BzrNewError.__init__(self)
134
172
        self.revision_id = revision_id
135
173
        self.branch = branch
136
174
 
137
175
 
138
176
class NoWorkingTree(BzrNewError):
139
 
    """No WorkingTree exists for %s(base)."""
 
177
    """No WorkingTree exists for %(base)s."""
140
178
    
141
179
    def __init__(self, base):
142
180
        BzrNewError.__init__(self)
144
182
 
145
183
 
146
184
class NotLocalUrl(BzrNewError):
147
 
    """%s(url) is not a local path."""
 
185
    """%(url)s is not a local path."""
148
186
    
149
187
    def __init__(self, url):
150
188
        BzrNewError.__init__(self)
151
189
        self.url = url
152
190
 
153
191
 
154
 
class BzrCommandError(BzrError):
155
 
    # Error from malformed user command
156
 
    # This is being misused as a generic exception
157
 
    # pleae subclass. RBC 20051030
 
192
class BzrCommandError(BzrNewError):
 
193
    """Error from user command"""
 
194
 
 
195
    is_user_error = True
 
196
 
 
197
    # Error from malformed user command; please avoid raising this as a
 
198
    # generic exception not caused by user input.
158
199
    #
159
200
    # I think it's a waste of effort to differentiate between errors that
160
201
    # are not intended to be caught anyway.  UI code need not subclass
161
202
    # BzrCommandError, and non-UI code should not throw a subclass of
162
203
    # BzrCommandError.  ADHB 20051211
 
204
    def __init__(self, msg):
 
205
        # Object.__str__() must return a real string
 
206
        # returning a Unicode string is a python error.
 
207
        if isinstance(msg, unicode):
 
208
            self.msg = msg.encode('utf8')
 
209
        else:
 
210
            self.msg = msg
 
211
 
163
212
    def __str__(self):
164
 
        return self.args[0]
 
213
        return self.msg
165
214
 
166
215
 
167
216
class BzrOptionError(BzrCommandError):
168
 
    """Some missing or otherwise incorrect option was supplied."""
 
217
    """Error in command line options"""
169
218
 
170
219
    
171
 
class StrictCommitFailed(Exception):
172
 
    """Commit refused because there are unknowns in the tree."""
173
 
 
174
 
 
 
220
class StrictCommitFailed(BzrNewError):
 
221
    """Commit refused because there are unknown files in the tree"""
 
222
 
 
223
 
 
224
# XXX: Should be unified with TransportError; they seem to represent the
 
225
# same thing
175
226
class PathError(BzrNewError):
176
227
    """Generic path error: %(path)r%(extra)s)"""
177
228
 
204
255
    """Permission denied: %(path)r%(extra)s"""
205
256
 
206
257
 
 
258
class InvalidURL(PathError):
 
259
    """Invalid url supplied to transport: %(path)r%(extra)s"""
 
260
 
 
261
 
 
262
class InvalidURLJoin(PathError):
 
263
    """Invalid URL join request: %(args)s%(extra)s"""
 
264
 
 
265
    def __init__(self, msg, base, args):
 
266
        PathError.__init__(self, base, msg)
 
267
        self.args = [base]
 
268
        self.args.extend(args)
 
269
 
 
270
 
 
271
class UnsupportedProtocol(PathError):
 
272
    """Unsupported protocol for url "%(path)s"%(extra)s"""
 
273
 
 
274
    def __init__(self, url, extra):
 
275
        PathError.__init__(self, url, extra=extra)
 
276
 
 
277
 
207
278
class PathNotChild(BzrNewError):
208
279
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
 
280
 
 
281
    is_user_error = False
 
282
 
209
283
    def __init__(self, path, base, extra=None):
210
284
        BzrNewError.__init__(self)
211
285
        self.path = path
216
290
            self.extra = ''
217
291
 
218
292
 
 
293
class InvalidNormalization(PathError):
 
294
    """Path %(path)r is not unicode normalized"""
 
295
 
 
296
 
 
297
# TODO: This is given a URL; we try to unescape it but doing that from inside
 
298
# the exception object is a bit undesirable.
 
299
# TODO: Probably this behavior of should be a common superclass 
219
300
class NotBranchError(PathError):
220
301
    """Not a branch: %(path)s"""
221
302
 
 
303
    def __init__(self, path):
 
304
       import bzrlib.urlutils as urlutils
 
305
       self.path = urlutils.unescape_for_display(path, 'ascii')
 
306
 
222
307
 
223
308
class AlreadyBranchError(PathError):
224
 
    """Already a branch: %(path)s. Use `bzr checkout` to build a working tree."""
 
309
    """Already a branch: %(path)s."""
 
310
 
 
311
 
 
312
class BranchExistsWithoutWorkingTree(PathError):
 
313
    """Directory contains a branch, but no working tree \
 
314
(use bzr checkout if you wish to build a working tree): %(path)s"""
 
315
 
 
316
 
 
317
class AtomicFileAlreadyClosed(PathError):
 
318
    """'%(function)s' called on an AtomicFile after it was closed: %(path)s"""
 
319
 
 
320
    def __init__(self, path, function):
 
321
        PathError.__init__(self, path=path, extra=None)
 
322
        self.function = function
 
323
 
 
324
 
 
325
class InaccessibleParent(PathError):
 
326
    """Parent not accessible given base %(base)s and relative path %(path)s"""
 
327
 
 
328
    def __init__(self, path, base):
 
329
        PathError.__init__(self, path)
 
330
        self.base = base
225
331
 
226
332
 
227
333
class NoRepositoryPresent(BzrNewError):
228
 
    """Not repository present: %(path)r"""
 
334
    """No repository present: %(path)r"""
229
335
    def __init__(self, bzrdir):
230
336
        BzrNewError.__init__(self)
231
337
        self.path = bzrdir.transport.clone('..').base
241
347
        self.path = path
242
348
 
243
349
 
244
 
class UnsupportedFormatError(BzrError):
245
 
    """Specified path is a bzr branch that we recognize but cannot read."""
246
 
    def __str__(self):
247
 
        return 'unsupported branch format: %s' % self.args[0]
248
 
 
249
 
 
250
 
class UnknownFormatError(BzrError):
251
 
    """Specified path is a bzr branch whose format we do not recognize."""
252
 
    def __str__(self):
253
 
        return 'unknown branch format: %s' % self.args[0]
 
350
class UnsupportedFormatError(BzrNewError):
 
351
    """Unsupported branch format: %(format)s"""
 
352
 
 
353
 
 
354
class UnknownFormatError(BzrNewError):
 
355
    """Unknown branch format: %(format)r"""
254
356
 
255
357
 
256
358
class IncompatibleFormat(BzrNewError):
280
382
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
281
383
 
282
384
 
283
 
class BadFileKindError(BzrError):
284
 
    """Specified file is of a kind that cannot be added.
285
 
 
286
 
    (For example a symlink or device file.)"""
287
 
 
288
 
 
289
 
class ForbiddenFileError(BzrError):
290
 
    """Cannot operate on a file because it is a control file."""
 
385
class PathsDoNotExist(BzrNewError):
 
386
    """Path(s) do not exist: %(paths_as_string)s"""
 
387
 
 
388
    # used when reporting that paths are neither versioned nor in the working
 
389
    # tree
 
390
 
 
391
    def __init__(self, paths):
 
392
        # circular import
 
393
        from bzrlib.osutils import quotefn
 
394
        BzrNewError.__init__(self)
 
395
        self.paths = paths
 
396
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
 
397
 
 
398
 
 
399
class BadFileKindError(BzrNewError):
 
400
    """Cannot operate on %(filename)s of unsupported kind %(kind)s"""
 
401
 
 
402
 
 
403
class ForbiddenControlFileError(BzrNewError):
 
404
    """Cannot operate on %(filename)s because it is a control file"""
291
405
 
292
406
 
293
407
class LockError(BzrNewError):
325
439
 
326
440
class ObjectNotLocked(LockError):
327
441
    """%(obj)r is not locked"""
 
442
 
 
443
    is_user_error = False
 
444
 
328
445
    # this can indicate that any particular object is not locked; see also
329
446
    # LockNotHeld which means that a particular *lock* object is not held by
330
447
    # the caller -- perhaps they should be unified.
392
509
    """Commit refused because there are unknowns in the tree."""
393
510
 
394
511
 
395
 
class NoSuchRevision(BzrError):
 
512
class NoSuchRevision(BzrNewError):
 
513
    """Branch %(branch)s has no revision %(revision)s"""
 
514
 
 
515
    is_user_error = False
 
516
 
396
517
    def __init__(self, branch, revision):
397
518
        self.branch = branch
398
519
        self.revision = revision
399
 
        msg = "Branch %s has no revision %s" % (branch, revision)
400
 
        BzrError.__init__(self, msg)
401
520
 
402
521
 
403
522
class HistoryMissing(BzrError):
408
527
                          % (branch, object_type, object_id))
409
528
 
410
529
 
411
 
class DivergedBranches(BzrError):
 
530
class DivergedBranches(BzrNewError):
 
531
    "These branches have diverged.  Use the merge command to reconcile them."""
 
532
 
 
533
    is_user_error = True
412
534
 
413
535
    def __init__(self, branch1, branch2):
414
 
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
415
536
        self.branch1 = branch1
416
537
        self.branch2 = branch2
417
538
 
418
539
 
419
 
class UnrelatedBranches(BzrCommandError):
420
 
    def __init__(self):
421
 
        msg = "Branches have no common ancestor, and no base revision"\
422
 
            " specified."
423
 
        BzrCommandError.__init__(self, msg)
424
 
 
425
 
 
426
 
class NoCommonAncestor(BzrError):
 
540
class UnrelatedBranches(BzrNewError):
 
541
    "Branches have no common ancestor, and no merge base revision was specified."
 
542
 
 
543
    is_user_error = True
 
544
 
 
545
 
 
546
class NoCommonAncestor(BzrNewError):
 
547
    "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
 
548
 
427
549
    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)
 
550
        self.revision_a = revision_a
 
551
        self.revision_b = revision_b
431
552
 
432
553
 
433
554
class NoCommonRoot(BzrError):
458
579
    def __init__(self, bases):
459
580
        warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
460
581
                DeprecationWarning)
461
 
        msg = "The correct base is unclear, becase %s are all equally close" %\
 
582
        msg = "The correct base is unclear, because %s are all equally close" %\
462
583
            ", ".join(bases)
463
584
        BzrError.__init__(self, msg)
464
585
        self.bases = bases
626
747
        self.format = format
627
748
 
628
749
 
629
 
class TransportError(BzrError):
630
 
    """All errors thrown by Transport implementations should derive
631
 
    from this class.
632
 
    """
 
750
class TransportError(BzrNewError):
 
751
    """Transport error: %(msg)s %(orig_error)s"""
 
752
 
633
753
    def __init__(self, msg=None, orig_error=None):
634
754
        if msg is None and orig_error is not None:
635
755
            msg = str(orig_error)
636
 
        BzrError.__init__(self, msg)
 
756
        if orig_error is None:
 
757
            orig_error = ''
 
758
        if msg is None:
 
759
            msg =  ''
637
760
        self.msg = msg
638
761
        self.orig_error = orig_error
 
762
        BzrNewError.__init__(self)
639
763
 
640
764
 
641
765
# A set of semi-meaningful errors which can be thrown
642
766
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.
645
 
    """
646
 
    pass
 
767
    """Transport operation not possible: %(msg)s %(orig_error)%"""
647
768
 
648
769
 
649
770
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.
653
 
    """
654
 
    def __init__(self, msg=None, orig_error=None):
655
 
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
 
771
    """Connection error: %(msg)s %(orig_error)s"""
656
772
 
657
773
 
658
774
class ConnectionReset(TransportError):
659
 
    """The connection has been closed."""
660
 
    pass
 
775
    """Connection closed: %(msg)s %(orig_error)s"""
 
776
 
 
777
 
 
778
class InvalidRange(TransportError):
 
779
    """Invalid range access."""
 
780
    
 
781
    def __init__(self, path, offset):
 
782
        TransportError.__init__(self, ("Invalid range access in %s at %d"
 
783
                                       % (path, offset)))
 
784
 
 
785
 
 
786
class InvalidHttpResponse(TransportError):
 
787
    """Invalid http response for %(path)s: %(msg)s"""
 
788
 
 
789
    def __init__(self, path, msg, orig_error=None):
 
790
        self.path = path
 
791
        TransportError.__init__(self, msg, orig_error=orig_error)
 
792
 
 
793
 
 
794
class InvalidHttpRange(InvalidHttpResponse):
 
795
    """Invalid http range "%(range)s" for %(path)s: %(msg)s"""
 
796
    
 
797
    def __init__(self, path, range, msg):
 
798
        self.range = range
 
799
        InvalidHttpResponse.__init__(self, path, msg)
 
800
 
 
801
 
 
802
class InvalidHttpContentType(InvalidHttpResponse):
 
803
    """Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s"""
 
804
    
 
805
    def __init__(self, path, ctype, msg):
 
806
        self.ctype = ctype
 
807
        InvalidHttpResponse.__init__(self, path, msg)
661
808
 
662
809
 
663
810
class ConflictsInTree(BzrError):
714
861
    """
715
862
 
716
863
 
 
864
class NoBundleFound(BzrNewError):
 
865
    """No bundle was found in %(filename)s"""
 
866
    def __init__(self, filename):
 
867
        BzrNewError.__init__(self)
 
868
        self.filename = filename
 
869
 
 
870
 
 
871
class BundleNotSupported(BzrNewError):
 
872
    """Unable to handle bundle version %(version)s: %(msg)s"""
 
873
    def __init__(self, version, msg):
 
874
        BzrNewError.__init__(self)
 
875
        self.version = version
 
876
        self.msg = msg
 
877
 
 
878
 
717
879
class MissingText(BzrNewError):
718
880
    """Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
719
881
 
764
926
    """Parameter $(param)s is required but not present."""
765
927
 
766
928
 
 
929
class BzrBadParameterUnicode(BzrBadParameter):
 
930
    """Parameter %(param)s is unicode but only byte-strings are permitted."""
 
931
 
 
932
 
 
933
class BzrBadParameterContainsNewline(BzrBadParameter):
 
934
    """Parameter %(param)s contains a newline."""
 
935
 
 
936
 
767
937
class DependencyNotPresent(BzrNewError):
768
938
    """Unable to import library "%(library)s": %(error)s"""
769
939
 
786
956
        self.format = format
787
957
 
788
958
 
 
959
class NoDiff(BzrNewError):
 
960
    """Diff is not installed on this machine: %(msg)s"""
 
961
 
 
962
    def __init__(self, msg):
 
963
        BzrNewError.__init__(self, msg=msg)
 
964
 
 
965
 
789
966
class NoDiff3(BzrNewError):
790
967
    """Diff3 is not installed on this machine."""
791
968
 
851
1028
    """A nested progress bar was not 'finished' correctly."""
852
1029
 
853
1030
 
 
1031
class InvalidProgressBarType(BzrNewError):
 
1032
    """Environment variable BZR_PROGRESS_BAR='%(bar_type)s is not a supported type
 
1033
Select one of: %(valid_types)s"""
 
1034
 
 
1035
    def __init__(self, bar_type, valid_types):
 
1036
        BzrNewError.__init__(self, bar_type=bar_type, valid_types=valid_types)
 
1037
 
 
1038
 
854
1039
class UnsupportedOperation(BzrNewError):
855
1040
    """The method %(mname)s is not supported on objects of type %(tname)s."""
856
1041
    def __init__(self, method, method_self):
857
1042
        self.method = method
858
1043
        self.mname = method.__name__
859
1044
        self.tname = type(method_self).__name__
 
1045
 
 
1046
 
 
1047
class BinaryFile(BzrNewError):
 
1048
    """File is binary but should be text."""
 
1049
 
 
1050
 
 
1051
class IllegalPath(BzrNewError):
 
1052
    """The path %(path)s is not permitted on this platform"""
 
1053
 
 
1054
    def __init__(self, path):
 
1055
        BzrNewError.__init__(self)
 
1056
        self.path = path
 
1057
 
 
1058
 
 
1059
class TestamentMismatch(BzrNewError):
 
1060
    """Testament did not match expected value.  
 
1061
       For revision_id {%(revision_id)s}, expected {%(expected)s}, measured 
 
1062
       {%(measured)s}
 
1063
    """
 
1064
    def __init__(self, revision_id, expected, measured):
 
1065
        self.revision_id = revision_id
 
1066
        self.expected = expected
 
1067
        self.measured = measured
 
1068
 
 
1069
 
 
1070
class NotABundle(BzrNewError):
 
1071
    """Not a bzr revision-bundle: %(text)r"""
 
1072
 
 
1073
    def __init__(self, text):
 
1074
        BzrNewError.__init__(self)
 
1075
        self.text = text
 
1076
 
 
1077
 
 
1078
class BadBundle(BzrNewError): 
 
1079
    """Bad bzr revision-bundle: %(text)r"""
 
1080
 
 
1081
    def __init__(self, text):
 
1082
        BzrNewError.__init__(self)
 
1083
        self.text = text
 
1084
 
 
1085
 
 
1086
class MalformedHeader(BadBundle): 
 
1087
    """Malformed bzr revision-bundle header: %(text)r"""
 
1088
 
 
1089
    def __init__(self, text):
 
1090
        BzrNewError.__init__(self)
 
1091
        self.text = text
 
1092
 
 
1093
 
 
1094
class MalformedPatches(BadBundle): 
 
1095
    """Malformed patches in bzr revision-bundle: %(text)r"""
 
1096
 
 
1097
    def __init__(self, text):
 
1098
        BzrNewError.__init__(self)
 
1099
        self.text = text
 
1100
 
 
1101
 
 
1102
class MalformedFooter(BadBundle): 
 
1103
    """Malformed footer in bzr revision-bundle: %(text)r"""
 
1104
 
 
1105
    def __init__(self, text):
 
1106
        BzrNewError.__init__(self)
 
1107
        self.text = text
 
1108
 
 
1109
class UnsupportedEOLMarker(BadBundle):
 
1110
    """End of line marker was not \\n in bzr revision-bundle"""    
 
1111
 
 
1112
    def __init__(self):
 
1113
        BzrNewError.__init__(self)