/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

Merge updated set_parents api.

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?  
108
135
class BzrCheckError(BzrNewError):
109
136
    """Internal check failed: %(message)s"""
110
137
 
 
138
    is_user_error = False
 
139
 
111
140
    def __init__(self, message):
112
141
        BzrNewError.__init__(self)
113
142
        self.message = message
115
144
 
116
145
class InvalidEntryName(BzrNewError):
117
146
    """Invalid entry name: %(name)s"""
 
147
 
 
148
    is_user_error = False
 
149
 
118
150
    def __init__(self, name):
119
151
        BzrNewError.__init__(self)
120
152
        self.name = name
129
161
 
130
162
class InvalidRevisionId(BzrNewError):
131
163
    """Invalid revision-id {%(revision_id)s} in %(branch)s"""
 
164
 
132
165
    def __init__(self, revision_id, branch):
 
166
        # branch can be any string or object with __str__ defined
133
167
        BzrNewError.__init__(self)
134
168
        self.revision_id = revision_id
135
169
        self.branch = branch
136
170
 
137
171
 
138
172
class NoWorkingTree(BzrNewError):
139
 
    """No WorkingTree exists for %s(base)."""
 
173
    """No WorkingTree exists for %(base)s."""
140
174
    
141
175
    def __init__(self, base):
142
176
        BzrNewError.__init__(self)
144
178
 
145
179
 
146
180
class NotLocalUrl(BzrNewError):
147
 
    """%s(url) is not a local path."""
 
181
    """%(url)s is not a local path."""
148
182
    
149
183
    def __init__(self, url):
150
184
        BzrNewError.__init__(self)
151
185
        self.url = url
152
186
 
153
187
 
154
 
class BzrCommandError(BzrError):
155
 
    # Error from malformed user command
156
 
    # This is being misused as a generic exception
157
 
    # pleae subclass. RBC 20051030
 
188
class BzrCommandError(BzrNewError):
 
189
    """Error from user command"""
 
190
 
 
191
    is_user_error = True
 
192
 
 
193
    # Error from malformed user command; please avoid raising this as a
 
194
    # generic exception not caused by user input.
158
195
    #
159
196
    # I think it's a waste of effort to differentiate between errors that
160
197
    # are not intended to be caught anyway.  UI code need not subclass
161
198
    # BzrCommandError, and non-UI code should not throw a subclass of
162
199
    # BzrCommandError.  ADHB 20051211
 
200
    def __init__(self, msg):
 
201
        self.msg = msg
 
202
 
163
203
    def __str__(self):
164
 
        return self.args[0]
 
204
        return self.msg
165
205
 
166
206
 
167
207
class BzrOptionError(BzrCommandError):
168
 
    """Some missing or otherwise incorrect option was supplied."""
 
208
    """Error in command line options"""
169
209
 
170
210
    
171
 
class StrictCommitFailed(Exception):
172
 
    """Commit refused because there are unknowns in the tree."""
173
 
 
174
 
 
 
211
class StrictCommitFailed(BzrNewError):
 
212
    """Commit refused because there are unknown files in the tree"""
 
213
 
 
214
 
 
215
# XXX: Should be unified with TransportError; they seem to represent the
 
216
# same thing
175
217
class PathError(BzrNewError):
176
218
    """Generic path error: %(path)r%(extra)s)"""
177
219
 
204
246
    """Permission denied: %(path)r%(extra)s"""
205
247
 
206
248
 
 
249
class InvalidURL(PathError):
 
250
    """Invalid url supplied to transport: %(path)r%(extra)s"""
 
251
 
 
252
 
 
253
class InvalidURLJoin(PathError):
 
254
    """Invalid URL join request: %(args)s%(extra)s"""
 
255
 
 
256
    def __init__(self, msg, base, args):
 
257
        PathError.__init__(self, base, msg)
 
258
        self.args = [base]
 
259
        self.args.extend(args)
 
260
 
 
261
 
 
262
class UnsupportedProtocol(PathError):
 
263
    """Unsupported protocol for url "%(path)s"%(extra)s"""
 
264
 
 
265
    def __init__(self, url, extra):
 
266
        PathError.__init__(self, url, extra=extra)
 
267
 
 
268
 
207
269
class PathNotChild(BzrNewError):
208
270
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
 
271
 
 
272
    is_user_error = False
 
273
 
209
274
    def __init__(self, path, base, extra=None):
210
275
        BzrNewError.__init__(self)
211
276
        self.path = path
216
281
            self.extra = ''
217
282
 
218
283
 
 
284
class InvalidNormalization(PathError):
 
285
    """Path %(path)r is not unicode normalized"""
 
286
 
 
287
 
 
288
# TODO: This is given a URL; we try to unescape it but doing that from inside
 
289
# the exception object is a bit undesirable.
 
290
# TODO: Probably this behavior of should be a common superclass 
219
291
class NotBranchError(PathError):
220
292
    """Not a branch: %(path)s"""
221
293
 
 
294
    def __init__(self, path):
 
295
       import bzrlib.urlutils as urlutils
 
296
       self.path = urlutils.unescape_for_display(path, 'ascii')
 
297
 
222
298
 
223
299
class AlreadyBranchError(PathError):
224
 
    """Already a branch: %(path)s. Use `bzr checkout` to build a working tree."""
 
300
    """Already a branch: %(path)s."""
 
301
 
 
302
 
 
303
class BranchExistsWithoutWorkingTree(PathError):
 
304
    """Directory contains a branch, but no working tree \
 
305
(use bzr checkout if you wish to build a working tree): %(path)s"""
 
306
 
 
307
 
 
308
class AtomicFileAlreadyClosed(PathError):
 
309
    """'%(function)s' called on an AtomicFile after it was closed: %(path)s"""
 
310
 
 
311
    def __init__(self, path, function):
 
312
        PathError.__init__(self, path=path, extra=None)
 
313
        self.function = function
 
314
 
 
315
 
 
316
class InaccessibleParent(PathError):
 
317
    """Parent not accessible given base %(base)s and relative path %(path)s"""
 
318
 
 
319
    def __init__(self, path, base):
 
320
        PathError.__init__(self, path)
 
321
        self.base = base
225
322
 
226
323
 
227
324
class NoRepositoryPresent(BzrNewError):
228
 
    """Not repository present: %(path)r"""
 
325
    """No repository present: %(path)r"""
229
326
    def __init__(self, bzrdir):
230
327
        BzrNewError.__init__(self)
231
328
        self.path = bzrdir.transport.clone('..').base
241
338
        self.path = path
242
339
 
243
340
 
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]
 
341
class UnsupportedFormatError(BzrNewError):
 
342
    """Unsupported branch format: %(format)s"""
 
343
 
 
344
 
 
345
class UnknownFormatError(BzrNewError):
 
346
    """Unknown branch format: %(format)r"""
254
347
 
255
348
 
256
349
class IncompatibleFormat(BzrNewError):
280
373
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
281
374
 
282
375
 
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."""
 
376
class PathsDoNotExist(BzrNewError):
 
377
    """Path(s) do not exist: %(paths_as_string)s"""
 
378
 
 
379
    # used when reporting that paths are neither versioned nor in the working
 
380
    # tree
 
381
 
 
382
    def __init__(self, paths):
 
383
        # circular import
 
384
        from bzrlib.osutils import quotefn
 
385
        BzrNewError.__init__(self)
 
386
        self.paths = paths
 
387
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
 
388
 
 
389
 
 
390
class BadFileKindError(BzrNewError):
 
391
    """Cannot operate on %(filename)s of unsupported kind %(kind)s"""
 
392
 
 
393
 
 
394
class ForbiddenControlFileError(BzrNewError):
 
395
    """Cannot operate on %(filename)s because it is a control file"""
291
396
 
292
397
 
293
398
class LockError(BzrNewError):
325
430
 
326
431
class ObjectNotLocked(LockError):
327
432
    """%(obj)r is not locked"""
 
433
 
 
434
    is_user_error = False
 
435
 
328
436
    # this can indicate that any particular object is not locked; see also
329
437
    # LockNotHeld which means that a particular *lock* object is not held by
330
438
    # the caller -- perhaps they should be unified.
392
500
    """Commit refused because there are unknowns in the tree."""
393
501
 
394
502
 
395
 
class NoSuchRevision(BzrError):
 
503
class NoSuchRevision(BzrNewError):
 
504
    """Branch %(branch)s has no revision %(revision)s"""
 
505
 
 
506
    is_user_error = False
 
507
 
396
508
    def __init__(self, branch, revision):
397
509
        self.branch = branch
398
510
        self.revision = revision
399
 
        msg = "Branch %s has no revision %s" % (branch, revision)
400
 
        BzrError.__init__(self, msg)
401
511
 
402
512
 
403
513
class HistoryMissing(BzrError):
408
518
                          % (branch, object_type, object_id))
409
519
 
410
520
 
411
 
class DivergedBranches(BzrError):
 
521
class DivergedBranches(BzrNewError):
 
522
    "These branches have diverged.  Use the merge command to reconcile them."""
 
523
 
 
524
    is_user_error = True
412
525
 
413
526
    def __init__(self, branch1, branch2):
414
 
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
415
527
        self.branch1 = branch1
416
528
        self.branch2 = branch2
417
529
 
418
530
 
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):
 
531
class UnrelatedBranches(BzrNewError):
 
532
    "Branches have no common ancestor, and no merge base revision was specified."
 
533
 
 
534
    is_user_error = True
 
535
 
 
536
 
 
537
class NoCommonAncestor(BzrNewError):
 
538
    "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
 
539
 
427
540
    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)
 
541
        self.revision_a = revision_a
 
542
        self.revision_b = revision_b
431
543
 
432
544
 
433
545
class NoCommonRoot(BzrError):
458
570
    def __init__(self, bases):
459
571
        warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
460
572
                DeprecationWarning)
461
 
        msg = "The correct base is unclear, becase %s are all equally close" %\
 
573
        msg = "The correct base is unclear, because %s are all equally close" %\
462
574
            ", ".join(bases)
463
575
        BzrError.__init__(self, msg)
464
576
        self.bases = bases
626
738
        self.format = format
627
739
 
628
740
 
629
 
class TransportError(BzrError):
630
 
    """All errors thrown by Transport implementations should derive
631
 
    from this class.
632
 
    """
 
741
class TransportError(BzrNewError):
 
742
    """Transport error: %(msg)s %(orig_error)s"""
 
743
 
633
744
    def __init__(self, msg=None, orig_error=None):
634
745
        if msg is None and orig_error is not None:
635
746
            msg = str(orig_error)
636
 
        BzrError.__init__(self, msg)
 
747
        if orig_error is None:
 
748
            orig_error = ''
 
749
        if msg is None:
 
750
            msg =  ''
637
751
        self.msg = msg
638
752
        self.orig_error = orig_error
 
753
        BzrNewError.__init__(self)
639
754
 
640
755
 
641
756
# A set of semi-meaningful errors which can be thrown
642
757
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
 
758
    """Transport operation not possible: %(msg)s %(orig_error)%"""
647
759
 
648
760
 
649
761
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)
 
762
    """Connection error: %(msg)s %(orig_error)s"""
656
763
 
657
764
 
658
765
class ConnectionReset(TransportError):
659
 
    """The connection has been closed."""
660
 
    pass
 
766
    """Connection closed: %(msg)s %(orig_error)s"""
 
767
 
 
768
 
 
769
class InvalidRange(TransportError):
 
770
    """Invalid range access."""
 
771
    
 
772
    def __init__(self, path, offset):
 
773
        TransportError.__init__(self, ("Invalid range access in %s at %d"
 
774
                                       % (path, offset)))
 
775
 
 
776
 
 
777
class InvalidHttpResponse(TransportError):
 
778
    """Invalid http response for %(path)s: %(msg)s"""
 
779
 
 
780
    def __init__(self, path, msg, orig_error=None):
 
781
        self.path = path
 
782
        TransportError.__init__(self, msg, orig_error=orig_error)
 
783
 
 
784
 
 
785
class InvalidHttpRange(InvalidHttpResponse):
 
786
    """Invalid http range "%(range)s" for %(path)s: %(msg)s"""
 
787
    
 
788
    def __init__(self, path, range, msg):
 
789
        self.range = range
 
790
        InvalidHttpResponse.__init__(self, path, msg)
 
791
 
 
792
 
 
793
class InvalidHttpContentType(InvalidHttpResponse):
 
794
    """Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s"""
 
795
    
 
796
    def __init__(self, path, ctype, msg):
 
797
        self.ctype = ctype
 
798
        InvalidHttpResponse.__init__(self, path, msg)
661
799
 
662
800
 
663
801
class ConflictsInTree(BzrError):
714
852
    """
715
853
 
716
854
 
 
855
class NoBundleFound(BzrNewError):
 
856
    """No bundle was found in %(filename)s"""
 
857
    def __init__(self, filename):
 
858
        BzrNewError.__init__(self)
 
859
        self.filename = filename
 
860
 
 
861
 
 
862
class BundleNotSupported(BzrNewError):
 
863
    """Unable to handle bundle version %(version)s: %(msg)s"""
 
864
    def __init__(self, version, msg):
 
865
        BzrNewError.__init__(self)
 
866
        self.version = version
 
867
        self.msg = msg
 
868
 
 
869
 
717
870
class MissingText(BzrNewError):
718
871
    """Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
719
872
 
764
917
    """Parameter $(param)s is required but not present."""
765
918
 
766
919
 
 
920
class BzrBadParameterUnicode(BzrBadParameter):
 
921
    """Parameter %(param)s is unicode but only byte-strings are permitted."""
 
922
 
 
923
 
 
924
class BzrBadParameterContainsNewline(BzrBadParameter):
 
925
    """Parameter %(param)s contains a newline."""
 
926
 
 
927
 
767
928
class DependencyNotPresent(BzrNewError):
768
929
    """Unable to import library "%(library)s": %(error)s"""
769
930
 
786
947
        self.format = format
787
948
 
788
949
 
 
950
class NoDiff(BzrNewError):
 
951
    """Diff is not installed on this machine: %(msg)s"""
 
952
 
 
953
    def __init__(self, msg):
 
954
        BzrNewError.__init__(self, msg=msg)
 
955
 
 
956
 
789
957
class NoDiff3(BzrNewError):
790
958
    """Diff3 is not installed on this machine."""
791
959
 
851
1019
    """A nested progress bar was not 'finished' correctly."""
852
1020
 
853
1021
 
 
1022
class InvalidProgressBarType(BzrNewError):
 
1023
    """Environment variable BZR_PROGRESS_BAR='%(bar_type)s is not a supported type
 
1024
Select one of: %(valid_types)s"""
 
1025
 
 
1026
    def __init__(self, bar_type, valid_types):
 
1027
        BzrNewError.__init__(self, bar_type=bar_type, valid_types=valid_types)
 
1028
 
 
1029
 
854
1030
class UnsupportedOperation(BzrNewError):
855
1031
    """The method %(mname)s is not supported on objects of type %(tname)s."""
856
1032
    def __init__(self, method, method_self):
857
1033
        self.method = method
858
1034
        self.mname = method.__name__
859
1035
        self.tname = type(method_self).__name__
 
1036
 
 
1037
 
 
1038
class BinaryFile(BzrNewError):
 
1039
    """File is binary but should be text."""
 
1040
 
 
1041
 
 
1042
class IllegalPath(BzrNewError):
 
1043
    """The path %(path)s is not permitted on this platform"""
 
1044
 
 
1045
    def __init__(self, path):
 
1046
        BzrNewError.__init__(self)
 
1047
        self.path = path
 
1048
 
 
1049
 
 
1050
class TestamentMismatch(BzrNewError):
 
1051
    """Testament did not match expected value.  
 
1052
       For revision_id {%(revision_id)s}, expected {%(expected)s}, measured 
 
1053
       {%(measured)s}
 
1054
    """
 
1055
    def __init__(self, revision_id, expected, measured):
 
1056
        self.revision_id = revision_id
 
1057
        self.expected = expected
 
1058
        self.measured = measured
 
1059
 
 
1060
 
 
1061
class NotABundle(BzrNewError):
 
1062
    """Not a bzr revision-bundle: %(text)r"""
 
1063
 
 
1064
    def __init__(self, text):
 
1065
        BzrNewError.__init__(self)
 
1066
        self.text = text
 
1067
 
 
1068
 
 
1069
class BadBundle(BzrNewError): 
 
1070
    """Bad bzr revision-bundle: %(text)r"""
 
1071
 
 
1072
    def __init__(self, text):
 
1073
        BzrNewError.__init__(self)
 
1074
        self.text = text
 
1075
 
 
1076
 
 
1077
class MalformedHeader(BadBundle): 
 
1078
    """Malformed bzr revision-bundle header: %(text)r"""
 
1079
 
 
1080
    def __init__(self, text):
 
1081
        BzrNewError.__init__(self)
 
1082
        self.text = text
 
1083
 
 
1084
 
 
1085
class MalformedPatches(BadBundle): 
 
1086
    """Malformed patches in bzr revision-bundle: %(text)r"""
 
1087
 
 
1088
    def __init__(self, text):
 
1089
        BzrNewError.__init__(self)
 
1090
        self.text = text
 
1091
 
 
1092
 
 
1093
class MalformedFooter(BadBundle): 
 
1094
    """Malformed footer in bzr revision-bundle: %(text)r"""
 
1095
 
 
1096
    def __init__(self, text):
 
1097
        BzrNewError.__init__(self)
 
1098
        self.text = text
 
1099
 
 
1100
 
 
1101
class UnsupportedEOLMarker(BadBundle):
 
1102
    """End of line marker was not \\n in bzr revision-bundle"""    
 
1103
 
 
1104
    def __init__(self):
 
1105
        BzrNewError.__init__(self)
 
1106
 
 
1107
 
 
1108
class GhostRevisionUnusableHere(BzrNewError):
 
1109
    """Ghost revision {%(revision_id)s} cannot be used here."""
 
1110
 
 
1111
    def __init__(self, revision_id):
 
1112
        BzrNewError.__init__(self)
 
1113
        self.revision_id = revision_id