1# Copyright (C) 2005-2013, 2016 Canonical Ltd
2#
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.
7#
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.
12#
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17"""Exceptions for bzr, and reporting of them.
18"""
19
20
21# TODO: is there any value in providing the .args field used by standard
22# python exceptions?   A list of values with no names seems less useful
23# to me.
24
25# TODO: Perhaps convert the exception to a string at the moment it's
26# constructed to make sure it will succeed.  But that says nothing about
27# exceptions that are never raised.
28
29# TODO: selftest assertRaises should probably also check that every error
30# raised can be formatted as a string successfully, and without giving
31# 'unprintable'.
32
33
34# return codes from the brz program
35EXIT_OK = 0
36EXIT_ERROR = 3
37EXIT_INTERNAL_ERROR = 4
38
39
40class BzrError(Exception):
41    """
42    Base class for errors raised by breezy.
43
44    :cvar internal_error: if True this was probably caused by a brz bug and
45        should be displayed with a traceback; if False (or absent) this was
46        probably a user or environment error and they don't need the gory
47        details.  (That can be overridden by -Derror on the command line.)
48
49    :cvar _fmt: Format string to display the error; this is expanded
50        by the instance's dict.
51    """
52
53    internal_error = False
54
55    def __init__(self, msg=None, **kwds):
56        """Construct a new BzrError.
57
58        There are two alternative forms for constructing these objects.
59        Either a preformatted string may be passed, or a set of named
60        arguments can be given.  The first is for generic "user" errors which
61        are not intended to be caught and so do not need a specific subclass.
62        The second case is for use with subclasses that provide a _fmt format
63        string to print the arguments.
64
65        Keyword arguments are taken as parameters to the error, which can
66        be inserted into the format string template.  It's recommended
67        that subclasses override the __init__ method to require specific
68        parameters.
69
70        :param msg: If given, this is the literal complete text for the error,
71           not subject to expansion. 'msg' is used instead of 'message' because
72           python evolved and, in 2.6, forbids the use of 'message'.
73        """
74        Exception.__init__(self)
75        if msg is not None:
76            # I was going to deprecate this, but it actually turns out to be
77            # quite handy - mbp 20061103.
78            self._preformatted_string = msg
79        else:
80            self._preformatted_string = None
81            for key, value in kwds.items():
82                setattr(self, key, value)
83
84    def _format(self):
85        s = getattr(self, '_preformatted_string', None)
86        if s is not None:
87            # contains a preformatted message
88            return s
89        err = None
90        try:
91            fmt = self._get_format_string()
92            if fmt:
93                d = dict(self.__dict__)
94                s = fmt % d
95                # __str__() should always return a 'str' object
96                # never a 'unicode' object.
97                return s
98        except Exception as e:
99            err = e
100        return 'Unprintable exception %s: dict=%r, fmt=%r, error=%r' \
101            % (self.__class__.__name__,
102               self.__dict__,
103               getattr(self, '_fmt', None),
104               err)
105
106    __str__ = _format
107
108    def __repr__(self):
109        return '%s(%s)' % (self.__class__.__name__, str(self))
110
111    def _get_format_string(self):
112        """Return format string for this exception or None"""
113        fmt = getattr(self, '_fmt', None)
114        if fmt is not None:
115            from breezy.i18n import gettext
116            return gettext(fmt)  # _fmt strings should be ascii
117
118    def __eq__(self, other):
119        if self.__class__ is not other.__class__:
120            return NotImplemented
121        return self.__dict__ == other.__dict__
122
123    def __hash__(self):
124        return id(self)
125
126
127class InternalBzrError(BzrError):
128    """Base class for errors that are internal in nature.
129
130    This is a convenience class for errors that are internal. The
131    internal_error attribute can still be altered in subclasses, if needed.
132    Using this class is simply an easy way to get internal errors.
133    """
134
135    internal_error = True
136
137
138class BranchError(BzrError):
139    """Base class for concrete 'errors about a branch'."""
140
141    def __init__(self, branch):
142        BzrError.__init__(self, branch=branch)
143
144
145class BzrCheckError(InternalBzrError):
146
147    _fmt = "Internal check failed: %(msg)s"
148
149    def __init__(self, msg):
150        BzrError.__init__(self)
151        self.msg = msg
152
153
154class IncompatibleVersion(BzrError):
155
156    _fmt = 'API %(api)s is not compatible; one of versions %(wanted)r '\
157           'is required, but current version is %(current)r.'
158
159    def __init__(self, api, wanted, current):
160        self.api = api
161        self.wanted = wanted
162        self.current = current
163
164
165class InProcessTransport(BzrError):
166
167    _fmt = "The transport '%(transport)s' is only accessible within this " \
168        "process."
169
170    def __init__(self, transport):
171        self.transport = transport
172
173
174class InvalidRevisionNumber(BzrError):
175
176    _fmt = "Invalid revision number %(revno)s"
177
178    def __init__(self, revno):
179        BzrError.__init__(self)
180        self.revno = revno
181
182
183class InvalidRevisionId(BzrError):
184
185    _fmt = "Invalid revision-id {%(revision_id)s} in %(branch)s"
186
187    def __init__(self, revision_id, branch):
188        # branch can be any string or object with __str__ defined
189        BzrError.__init__(self)
190        self.revision_id = revision_id
191        self.branch = branch
192
193
194class ReservedId(BzrError):
195
196    _fmt = "Reserved revision-id {%(revision_id)s}"
197
198    def __init__(self, revision_id):
199        self.revision_id = revision_id
200
201
202class RootMissing(InternalBzrError):
203
204    _fmt = ("The root entry of a tree must be the first entry supplied to "
205            "the commit builder.")
206
207
208class NoPublicBranch(BzrError):
209
210    _fmt = 'There is no public branch set for "%(branch_url)s".'
211
212    def __init__(self, branch):
213        from . import urlutils
214        public_location = urlutils.unescape_for_display(branch.base, 'ascii')
215        BzrError.__init__(self, branch_url=public_location)
216
217
218class NoSuchId(BzrError):
219
220    _fmt = 'The file id "%(file_id)s" is not present in the tree %(tree)s.'
221
222    def __init__(self, tree, file_id):
223        BzrError.__init__(self)
224        self.file_id = file_id
225        self.tree = tree
226
227
228class NotStacked(BranchError):
229
230    _fmt = "The branch '%(branch)s' is not stacked."
231
232
233class NoWorkingTree(BzrError):
234
235    _fmt = 'No WorkingTree exists for "%(base)s".'
236
237    def __init__(self, base):
238        BzrError.__init__(self)
239        self.base = base
240
241
242class NotLocalUrl(BzrError):
243
244    _fmt = "%(url)s is not a local path."
245
246    def __init__(self, url):
247        self.url = url
248
249
250class WorkingTreeAlreadyPopulated(InternalBzrError):
251
252    _fmt = 'Working tree already populated in "%(base)s"'
253
254    def __init__(self, base):
255        self.base = base
256
257
258class NoWhoami(BzrError):
259
260    _fmt = ('Unable to determine your name.\n'
261            "Please, set your name with the 'whoami' command.\n"
262            'E.g. brz whoami "Your Name <name@example.com>"')
263
264
265class CommandError(BzrError):
266    """Error from user command"""
267
268    # Error from malformed user command; please avoid raising this as a
269    # generic exception not caused by user input.
270    #
271    # I think it's a waste of effort to differentiate between errors that
272    # are not intended to be caught anyway.  UI code need not subclass
273    # CommandError, and non-UI code should not throw a subclass of
274    # CommandError.  ADHB 20051211
275
276
277# Provide the old name as backup, for the moment.
278BzrCommandError = CommandError
279
280
281class NotWriteLocked(BzrError):
282
283    _fmt = """%(not_locked)r is not write locked but needs to be."""
284
285    def __init__(self, not_locked):
286        self.not_locked = not_locked
287
288
289class StrictCommitFailed(BzrError):
290
291    _fmt = "Commit refused because there are unknown files in the tree"
292
293
294# XXX: Should be unified with TransportError; they seem to represent the
295# same thing
296# RBC 20060929: I think that unifiying with TransportError would be a mistake
297# - this is finer than a TransportError - and more useful as such. It
298# differentiates between 'transport has failed' and 'operation on a transport
299# has failed.'
300class PathError(BzrError):
301
302    _fmt = "Generic path error: %(path)r%(extra)s)"
303
304    def __init__(self, path, extra=None):
305        BzrError.__init__(self)
306        self.path = path
307        if extra:
308            self.extra = ': ' + str(extra)
309        else:
310            self.extra = ''
311
312
313class NoSuchFile(PathError):
314
315    _fmt = "No such file: %(path)r%(extra)s"
316
317
318class FileExists(PathError):
319
320    _fmt = "File exists: %(path)r%(extra)s"
321
322
323class RenameFailedFilesExist(BzrError):
324    """Used when renaming and both source and dest exist."""
325
326    _fmt = ("Could not rename %(source)s => %(dest)s because both files exist."
327            " (Use --after to tell brz about a rename that has already"
328            " happened)%(extra)s")
329
330    def __init__(self, source, dest, extra=None):
331        BzrError.__init__(self)
332        self.source = str(source)
333        self.dest = str(dest)
334        if extra:
335            self.extra = ' ' + str(extra)
336        else:
337            self.extra = ''
338
339
340class NotADirectory(PathError):
341
342    _fmt = '"%(path)s" is not a directory %(extra)s'
343
344
345class NotInWorkingDirectory(PathError):
346
347    _fmt = '"%(path)s" is not in the working directory %(extra)s'
348
349
350class DirectoryNotEmpty(PathError):
351
352    _fmt = 'Directory not empty: "%(path)s"%(extra)s'
353
354
355class HardLinkNotSupported(PathError):
356
357    _fmt = 'Hard-linking "%(path)s" is not supported'
358
359
360class ReadingCompleted(InternalBzrError):
361
362    _fmt = ("The MediumRequest '%(request)s' has already had finish_reading "
363            "called upon it - the request has been completed and no more "
364            "data may be read.")
365
366    def __init__(self, request):
367        self.request = request
368
369
370class ResourceBusy(PathError):
371
372    _fmt = 'Device or resource busy: "%(path)s"%(extra)s'
373
374
375class PermissionDenied(PathError):
376
377    _fmt = 'Permission denied: "%(path)s"%(extra)s'
378
379
380class UnsupportedProtocol(PathError):
381
382    _fmt = 'Unsupported protocol for url "%(path)s"%(extra)s'
383
384    def __init__(self, url, extra=""):
385        PathError.__init__(self, url, extra=extra)
386
387
388class UnstackableLocationError(BzrError):
389
390    _fmt = "The branch '%(branch_url)s' cannot be stacked on '%(target_url)s'."
391
392    def __init__(self, branch_url, target_url):
393        BzrError.__init__(self)
394        self.branch_url = branch_url
395        self.target_url = target_url
396
397
398class UnstackableRepositoryFormat(BzrError):
399
400    _fmt = ("The repository '%(url)s'(%(format)s) is not a stackable format. "
401            "You will need to upgrade the repository to permit branch stacking.")
402
403    def __init__(self, format, url):
404        BzrError.__init__(self)
405        self.format = format
406        self.url = url
407
408
409class ReadError(PathError):
410
411    _fmt = """Error reading from %(path)r."""
412
413
414class ShortReadvError(PathError):
415
416    _fmt = ('readv() read %(actual)s bytes rather than %(length)s bytes'
417            ' at %(offset)s for "%(path)s"%(extra)s')
418
419    internal_error = True
420
421    def __init__(self, path, offset, length, actual, extra=None):
422        PathError.__init__(self, path, extra=extra)
423        self.offset = offset
424        self.length = length
425        self.actual = actual
426
427
428class PathNotChild(PathError):
429
430    _fmt = 'Path "%(path)s" is not a child of path "%(base)s"%(extra)s'
431
432    internal_error = False
433
434    def __init__(self, path, base, extra=None):
435        BzrError.__init__(self)
436        self.path = path
437        self.base = base
438        if extra:
439            self.extra = ': ' + str(extra)
440        else:
441            self.extra = ''
442
443
444class InvalidNormalization(PathError):
445
446    _fmt = 'Path "%(path)s" is not unicode normalized'
447
448
449# TODO: This is given a URL; we try to unescape it but doing that from inside
450# the exception object is a bit undesirable.
451# TODO: Probably this behavior of should be a common superclass
452class NotBranchError(PathError):
453
454    _fmt = 'Not a branch: "%(path)s"%(detail)s.'
455
456    def __init__(self, path, detail=None, controldir=None):
457        from . import urlutils
458        path = urlutils.unescape_for_display(path, 'ascii')
459        if detail is not None:
460            detail = ': ' + detail
461        self.detail = detail
462        self.controldir = controldir
463        PathError.__init__(self, path=path)
464
465    def __repr__(self):
466        return '<%s %r>' % (self.__class__.__name__, self.__dict__)
467
468    def _get_format_string(self):
469        # GZ 2017-06-08: Not the best place to lazy fill detail in.
470        if self.detail is None:
471            self.detail = self._get_detail()
472        return super(NotBranchError, self)._get_format_string()
473
474    def _get_detail(self):
475        if self.controldir is not None:
476            try:
477                self.controldir.open_repository()
478            except NoRepositoryPresent:
479                return ''
480            except Exception as e:
481                # Just ignore unexpected errors.  Raising arbitrary errors
482                # during str(err) can provoke strange bugs.  Concretely
483                # Launchpad's codehosting managed to raise NotBranchError
484                # here, and then get stuck in an infinite loop/recursion
485                # trying to str() that error.  All this error really cares
486                # about that there's no working repository there, and if
487                # open_repository() fails, there probably isn't.
488                return ': ' + e.__class__.__name__
489            else:
490                return ': location is a repository'
491        return ''
492
493
494class NoSubmitBranch(PathError):
495
496    _fmt = 'No submit branch available for branch "%(path)s"'
497
498    def __init__(self, branch):
499        from . import urlutils
500        self.path = urlutils.unescape_for_display(branch.base, 'ascii')
501
502
503class AlreadyControlDirError(PathError):
504
505    _fmt = 'A control directory already exists: "%(path)s".'
506
507
508class AlreadyBranchError(PathError):
509
510    _fmt = 'Already a branch: "%(path)s".'
511
512
513class InvalidBranchName(PathError):
514
515    _fmt = "Invalid branch name: %(name)s"
516
517    def __init__(self, name):
518        BzrError.__init__(self)
519        self.name = name
520
521
522class ParentBranchExists(AlreadyBranchError):
523
524    _fmt = 'Parent branch already exists: "%(path)s".'
525
526
527class BranchExistsWithoutWorkingTree(PathError):
528
529    _fmt = 'Directory contains a branch, but no working tree \
530(use brz checkout if you wish to build a working tree): "%(path)s"'
531
532
533class InaccessibleParent(PathError):
534
535    _fmt = ('Parent not accessible given base "%(base)s" and'
536            ' relative path "%(path)s"')
537
538    def __init__(self, path, base):
539        PathError.__init__(self, path)
540        self.base = base
541
542
543class NoRepositoryPresent(BzrError):
544
545    _fmt = 'No repository present: "%(path)s"'
546
547    def __init__(self, controldir):
548        BzrError.__init__(self)
549        self.path = controldir.transport.clone('..').base
550
551
552class UnsupportedFormatError(BzrError):
553
554    _fmt = "Unsupported branch format: %(format)s\nPlease run 'brz upgrade'"
555
556
557class UnknownFormatError(BzrError):
558
559    _fmt = "Unknown %(kind)s format: %(format)r"
560
561    def __init__(self, format, kind='branch'):
562        self.kind = kind
563        self.format = format
564
565
566class IncompatibleFormat(BzrError):
567
568    _fmt = "Format %(format)s is not compatible with .bzr version %(controldir)s."
569
570    def __init__(self, format, controldir_format):
571        BzrError.__init__(self)
572        self.format = format
573        self.controldir = controldir_format
574
575
576class ParseFormatError(BzrError):
577
578    _fmt = "Parse error on line %(lineno)d of %(format)s format: %(line)s"
579
580    def __init__(self, format, lineno, line, text):
581        BzrError.__init__(self)
582        self.format = format
583        self.lineno = lineno
584        self.line = line
585        self.text = text
586
587
588class IncompatibleRepositories(BzrError):
589    """Report an error that two repositories are not compatible.
590
591    Note that the source and target repositories are permitted to be strings:
592    this exception is thrown from the smart server and may refer to a
593    repository the client hasn't opened.
594    """
595
596    _fmt = "%(target)s\n" \
597        "is not compatible with\n" \
598        "%(source)s\n" \
599        "%(details)s"
600
601    def __init__(self, source, target, details=None):
602        if details is None:
603            details = "(no details)"
604        BzrError.__init__(self, target=target, source=source, details=details)
605
606
607class IncompatibleRevision(BzrError):
608
609    _fmt = "Revision is not compatible with %(repo_format)s"
610
611    def __init__(self, repo_format):
612        BzrError.__init__(self)
613        self.repo_format = repo_format
614
615
616class AlreadyVersionedError(BzrError):
617    """Used when a path is expected not to be versioned, but it is."""
618
619    _fmt = "%(context_info)s%(path)s is already versioned."
620
621    def __init__(self, path, context_info=None):
622        """Construct a new AlreadyVersionedError.
623
624        :param path: This is the path which is versioned,
625            which should be in a user friendly form.
626        :param context_info: If given, this is information about the context,
627            which could explain why this is expected to not be versioned.
628        """
629        BzrError.__init__(self)
630        self.path = path
631        if context_info is None:
632            self.context_info = ''
633        else:
634            self.context_info = context_info + ". "
635
636
637class NotVersionedError(BzrError):
638    """Used when a path is expected to be versioned, but it is not."""
639
640    _fmt = "%(context_info)s%(path)s is not versioned."
641
642    def __init__(self, path, context_info=None):
643        """Construct a new NotVersionedError.
644
645        :param path: This is the path which is not versioned,
646            which should be in a user friendly form.
647        :param context_info: If given, this is information about the context,
648            which could explain why this is expected to be versioned.
649        """
650        BzrError.__init__(self)
651        self.path = path
652        if context_info is None:
653            self.context_info = ''
654        else:
655            self.context_info = context_info + ". "
656
657
658class PathsNotVersionedError(BzrError):
659    """Used when reporting several paths which are not versioned"""
660
661    _fmt = "Path(s) are not versioned: %(paths_as_string)s"
662
663    def __init__(self, paths):
664        from breezy.osutils import quotefn
665        BzrError.__init__(self)
666        self.paths = paths
667        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
668
669
670class PathsDoNotExist(BzrError):
671
672    _fmt = "Path(s) do not exist: %(paths_as_string)s%(extra)s"
673
674    # used when reporting that paths are neither versioned nor in the working
675    # tree
676
677    def __init__(self, paths, extra=None):
678        # circular import
679        from breezy.osutils import quotefn
680        BzrError.__init__(self)
681        self.paths = paths
682        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
683        if extra:
684            self.extra = ': ' + str(extra)
685        else:
686            self.extra = ''
687
688
689class BadFileKindError(BzrError):
690
691    _fmt = 'Cannot operate on "%(filename)s" of unsupported kind "%(kind)s"'
692
693    def __init__(self, filename, kind):
694        BzrError.__init__(self, filename=filename, kind=kind)
695
696
697class BadFilenameEncoding(BzrError):
698
699    _fmt = ('Filename %(filename)r is not valid in your current filesystem'
700            ' encoding %(fs_encoding)s')
701
702    def __init__(self, filename, fs_encoding):
703        BzrError.__init__(self)
704        self.filename = filename
705        self.fs_encoding = fs_encoding
706
707
708class ForbiddenControlFileError(BzrError):
709
710    _fmt = 'Cannot operate on "%(filename)s" because it is a control file'
711
712
713class LockError(InternalBzrError):
714
715    _fmt = "Lock error: %(msg)s"
716
717    # All exceptions from the lock/unlock functions should be from
718    # this exception class.  They will be translated as necessary. The
719    # original exception is available as e.original_error
720    #
721    # New code should prefer to raise specific subclasses
722    def __init__(self, msg):
723        self.msg = msg
724
725
726class LockActive(LockError):
727
728    _fmt = "The lock for '%(lock_description)s' is in use and cannot be broken."
729
730    internal_error = False
731
732    def __init__(self, lock_description):
733        self.lock_description = lock_description
734
735
736class CommitNotPossible(LockError):
737
738    _fmt = "A commit was attempted but we do not have a write lock open."
739
740    def __init__(self):
741        pass
742
743
744class AlreadyCommitted(LockError):
745
746    _fmt = "A rollback was requested, but is not able to be accomplished."
747
748    def __init__(self):
749        pass
750
751
752class ReadOnlyError(LockError):
753
754    _fmt = "A write attempt was made in a read only transaction on %(obj)s"
755
756    # TODO: There should also be an error indicating that you need a write
757    # lock and don't have any lock at all... mbp 20070226
758
759    def __init__(self, obj):
760        self.obj = obj
761
762
763class LockFailed(LockError):
764
765    internal_error = False
766
767    _fmt = "Cannot lock %(lock)s: %(why)s"
768
769    def __init__(self, lock, why):
770        LockError.__init__(self, '')
771        self.lock = lock
772        self.why = why
773
774
775class OutSideTransaction(BzrError):
776
777    _fmt = ("A transaction related operation was attempted after"
778            " the transaction finished.")
779
780
781class ObjectNotLocked(LockError):
782
783    _fmt = "%(obj)r is not locked"
784
785    # this can indicate that any particular object is not locked; see also
786    # LockNotHeld which means that a particular *lock* object is not held by
787    # the caller -- perhaps they should be unified.
788    def __init__(self, obj):
789        self.obj = obj
790
791
792class ReadOnlyObjectDirtiedError(ReadOnlyError):
793
794    _fmt = "Cannot change object %(obj)r in read only transaction"
795
796    def __init__(self, obj):
797        self.obj = obj
798
799
800class UnlockableTransport(LockError):
801
802    internal_error = False
803
804    _fmt = "Cannot lock: transport is read only: %(transport)s"
805
806    def __init__(self, transport):
807        self.transport = transport
808
809
810class LockContention(LockError):
811
812    _fmt = 'Could not acquire lock "%(lock)s": %(msg)s'
813
814    internal_error = False
815
816    def __init__(self, lock, msg=''):
817        self.lock = lock
818        self.msg = msg
819
820
821class LockBroken(LockError):
822
823    _fmt = ("Lock was broken while still open: %(lock)s"
824            " - check storage consistency!")
825
826    internal_error = False
827
828    def __init__(self, lock):
829        self.lock = lock
830
831
832class LockBreakMismatch(LockError):
833
834    _fmt = ("Lock was released and re-acquired before being broken:"
835            " %(lock)s: held by %(holder)r, wanted to break %(target)r")
836
837    internal_error = False
838
839    def __init__(self, lock, holder, target):
840        self.lock = lock
841        self.holder = holder
842        self.target = target
843
844
845class LockCorrupt(LockError):
846
847    _fmt = ("Lock is apparently held, but corrupted: %(corruption_info)s\n"
848            "Use 'brz break-lock' to clear it")
849
850    internal_error = False
851
852    def __init__(self, corruption_info, file_data=None):
853        self.corruption_info = corruption_info
854        self.file_data = file_data
855
856
857class LockNotHeld(LockError):
858
859    _fmt = "Lock not held: %(lock)s"
860
861    internal_error = False
862
863    def __init__(self, lock):
864        self.lock = lock
865
866
867class TokenLockingNotSupported(LockError):
868
869    _fmt = "The object %(obj)s does not support token specifying a token when locking."
870
871    def __init__(self, obj):
872        self.obj = obj
873
874
875class TokenMismatch(LockBroken):
876
877    _fmt = "The lock token %(given_token)r does not match lock token %(lock_token)r."
878
879    internal_error = True
880
881    def __init__(self, given_token, lock_token):
882        self.given_token = given_token
883        self.lock_token = lock_token
884
885
886class UpgradeReadonly(BzrError):
887
888    _fmt = "Upgrade URL cannot work with readonly URLs."
889
890
891class UpToDateFormat(BzrError):
892
893    _fmt = "The branch format %(format)s is already at the most recent format."
894
895    def __init__(self, format):
896        BzrError.__init__(self)
897        self.format = format
898
899
900class NoSuchRevision(InternalBzrError):
901
902    _fmt = "%(branch)s has no revision %(revision)s"
903
904    def __init__(self, branch, revision):
905        # 'branch' may sometimes be an internal object like a KnitRevisionStore
906        BzrError.__init__(self, branch=branch, revision=revision)
907
908
909class RangeInChangeOption(BzrError):
910
911    _fmt = "Option --change does not accept revision ranges"
912
913
914class NoSuchRevisionSpec(BzrError):
915
916    _fmt = "No namespace registered for string: %(spec)r"
917
918    def __init__(self, spec):
919        BzrError.__init__(self, spec=spec)
920
921
922class NoSuchRevisionInTree(NoSuchRevision):
923    """When using Tree.revision_tree, and the revision is not accessible."""
924
925    _fmt = "The revision id {%(revision_id)s} is not present in the tree %(tree)s."
926
927    def __init__(self, tree, revision_id):
928        BzrError.__init__(self)
929        self.tree = tree
930        self.revision_id = revision_id
931
932
933class AppendRevisionsOnlyViolation(BzrError):
934
935    _fmt = ('Operation denied because it would change the main history,'
936            ' which is not permitted by the append_revisions_only setting on'
937            ' branch "%(location)s".')
938
939    def __init__(self, location):
940        import breezy.urlutils as urlutils
941        location = urlutils.unescape_for_display(location, 'ascii')
942        BzrError.__init__(self, location=location)
943
944
945class DivergedBranches(BzrError):
946
947    _fmt = ("These branches have diverged."
948            " Use the missing command to see how.\n"
949            "Use the merge command to reconcile them.")
950
951    def __init__(self, branch1, branch2):
952        self.branch1 = branch1
953        self.branch2 = branch2
954
955
956class NotLefthandHistory(InternalBzrError):
957
958    _fmt = "Supplied history does not follow left-hand parents"
959
960    def __init__(self, history):
961        BzrError.__init__(self, history=history)
962
963
964class UnrelatedBranches(BzrError):
965
966    _fmt = ("Branches have no common ancestor, and"
967            " no merge base revision was specified.")
968
969
970class CannotReverseCherrypick(BzrError):
971
972    _fmt = ('Selected merge cannot perform reverse cherrypicks.  Try merge3'
973            ' or diff3.')
974
975
976class NoCommonAncestor(BzrError):
977
978    _fmt = "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
979
980    def __init__(self, revision_a, revision_b):
981        self.revision_a = revision_a
982        self.revision_b = revision_b
983
984
985class NoCommonRoot(BzrError):
986
987    _fmt = ("Revisions are not derived from the same root: "
988            "%(revision_a)s %(revision_b)s.")
989
990    def __init__(self, revision_a, revision_b):
991        BzrError.__init__(self, revision_a=revision_a, revision_b=revision_b)
992
993
994class NotAncestor(BzrError):
995
996    _fmt = "Revision %(rev_id)s is not an ancestor of %(not_ancestor_id)s"
997
998    def __init__(self, rev_id, not_ancestor_id):
999        BzrError.__init__(self, rev_id=rev_id,
1000                          not_ancestor_id=not_ancestor_id)
1001
1002
1003class NoCommits(BranchError):
1004
1005    _fmt = "Branch %(branch)s has no commits."
1006
1007
1008class UnlistableStore(BzrError):
1009
1010    def __init__(self, store):
1011        BzrError.__init__(self, "Store %s is not listable" % store)
1012
1013
1014class UnlistableBranch(BzrError):
1015
1016    def __init__(self, br):
1017        BzrError.__init__(self, "Stores for branch %s are not listable" % br)
1018
1019
1020class BoundBranchOutOfDate(BzrError):
1021
1022    _fmt = ("Bound branch %(branch)s is out of date with master branch"
1023            " %(master)s.%(extra_help)s")
1024
1025    def __init__(self, branch, master):
1026        BzrError.__init__(self)
1027        self.branch = branch
1028        self.master = master
1029        self.extra_help = ''
1030
1031
1032class CommitToDoubleBoundBranch(BzrError):
1033
1034    _fmt = ("Cannot commit to branch %(branch)s."
1035            " It is bound to %(master)s, which is bound to %(remote)s.")
1036
1037    def __init__(self, branch, master, remote):
1038        BzrError.__init__(self)
1039        self.branch = branch
1040        self.master = master
1041        self.remote = remote
1042
1043
1044class OverwriteBoundBranch(BzrError):
1045
1046    _fmt = "Cannot pull --overwrite to a branch which is bound %(branch)s"
1047
1048    def __init__(self, branch):
1049        BzrError.__init__(self)
1050        self.branch = branch
1051
1052
1053class BoundBranchConnectionFailure(BzrError):
1054
1055    _fmt = ("Unable to connect to target of bound branch %(branch)s"
1056            " => %(target)s: %(error)s")
1057
1058    def __init__(self, branch, target, error):
1059        BzrError.__init__(self)
1060        self.branch = branch
1061        self.target = target
1062        self.error = error
1063
1064
1065class VersionedFileError(BzrError):
1066
1067    _fmt = "Versioned file error"
1068
1069
1070class RevisionNotPresent(VersionedFileError):
1071
1072    _fmt = 'Revision {%(revision_id)s} not present in "%(file_id)s".'
1073
1074    def __init__(self, revision_id, file_id):
1075        VersionedFileError.__init__(self)
1076        self.revision_id = revision_id
1077        self.file_id = file_id
1078
1079
1080class RevisionAlreadyPresent(VersionedFileError):
1081
1082    _fmt = 'Revision {%(revision_id)s} already present in "%(file_id)s".'
1083
1084    def __init__(self, revision_id, file_id):
1085        VersionedFileError.__init__(self)
1086        self.revision_id = revision_id
1087        self.file_id = file_id
1088
1089
1090class VersionedFileInvalidChecksum(VersionedFileError):
1091
1092    _fmt = "Text did not match its checksum: %(msg)s"
1093
1094
1095class RetryWithNewPacks(BzrError):
1096    """Raised when we realize that the packs on disk have changed.
1097
1098    This is meant as more of a signaling exception, to trap between where a
1099    local error occurred and the code that can actually handle the error and
1100    code that can retry appropriately.
1101    """
1102
1103    internal_error = True
1104
1105    _fmt = ("Pack files have changed, reload and retry. context: %(context)s"
1106            " %(orig_error)s")
1107
1108    def __init__(self, context, reload_occurred, exc_info):
1109        """create a new RetryWithNewPacks error.
1110
1111        :param reload_occurred: Set to True if we know that the packs have
1112            already been reloaded, and we are failing because of an in-memory
1113            cache miss. If set to True then we will ignore if a reload says
1114            nothing has changed, because we assume it has already reloaded. If
1115            False, then a reload with nothing changed will force an error.
1116        :param exc_info: The original exception traceback, so if there is a
1117            problem we can raise the original error (value from sys.exc_info())
1118        """
1119        BzrError.__init__(self)
1120        self.context = context
1121        self.reload_occurred = reload_occurred
1122        self.exc_info = exc_info
1123        self.orig_error = exc_info[1]
1124        # TODO: The global error handler should probably treat this by
1125        #       raising/printing the original exception with a bit about
1126        #       RetryWithNewPacks also not being caught
1127
1128
1129class RetryAutopack(RetryWithNewPacks):
1130    """Raised when we are autopacking and we find a missing file.
1131
1132    Meant as a signaling exception, to tell the autopack code it should try
1133    again.
1134    """
1135
1136    internal_error = True
1137
1138    _fmt = ("Pack files have changed, reload and try autopack again."
1139            " context: %(context)s %(orig_error)s")
1140
1141
1142class NoSuchExportFormat(BzrError):
1143
1144    _fmt = "Export format %(format)r not supported"
1145
1146    def __init__(self, format):
1147        BzrError.__init__(self)
1148        self.format = format
1149
1150
1151class TransportError(BzrError):
1152
1153    _fmt = "Transport error: %(msg)s %(orig_error)s"
1154
1155    def __init__(self, msg=None, orig_error=None):
1156        if msg is None and orig_error is not None:
1157            msg = str(orig_error)
1158        if orig_error is None:
1159            orig_error = ''
1160        if msg is None:
1161            msg = ''
1162        self.msg = msg
1163        self.orig_error = orig_error
1164        BzrError.__init__(self)
1165
1166
1167class TooManyConcurrentRequests(InternalBzrError):
1168
1169    _fmt = ("The medium '%(medium)s' has reached its concurrent request limit."
1170            " Be sure to finish_writing and finish_reading on the"
1171            " currently open request.")
1172
1173    def __init__(self, medium):
1174        self.medium = medium
1175
1176
1177class SmartProtocolError(TransportError):
1178
1179    _fmt = "Generic bzr smart protocol error: %(details)s"
1180
1181    def __init__(self, details):
1182        self.details = details
1183
1184
1185class UnexpectedProtocolVersionMarker(TransportError):
1186
1187    _fmt = "Received bad protocol version marker: %(marker)r"
1188
1189    def __init__(self, marker):
1190        self.marker = marker
1191
1192
1193class UnknownSmartMethod(InternalBzrError):
1194
1195    _fmt = "The server does not recognise the '%(verb)s' request."
1196
1197    def __init__(self, verb):
1198        self.verb = verb
1199
1200
1201class SmartMessageHandlerError(InternalBzrError):
1202
1203    _fmt = ("The message handler raised an exception:\n"
1204            "%(traceback_text)s")
1205
1206    def __init__(self, exc_info):
1207        import traceback
1208        # GZ 2010-08-10: Cycle with exc_tb/exc_info affects at least one test
1209        self.exc_type, self.exc_value, self.exc_tb = exc_info
1210        self.exc_info = exc_info
1211        traceback_strings = traceback.format_exception(
1212            self.exc_type, self.exc_value, self.exc_tb)
1213        self.traceback_text = ''.join(traceback_strings)
1214
1215
1216# A set of semi-meaningful errors which can be thrown
1217class TransportNotPossible(TransportError):
1218
1219    _fmt = "Transport operation not possible: %(msg)s %(orig_error)s"
1220
1221
1222class ConnectionError(TransportError):
1223
1224    _fmt = "Connection error: %(msg)s %(orig_error)s"
1225
1226
1227class SocketConnectionError(ConnectionError):
1228
1229    _fmt = "%(msg)s %(host)s%(port)s%(orig_error)s"
1230
1231    def __init__(self, host, port=None, msg=None, orig_error=None):
1232        if msg is None:
1233            msg = 'Failed to connect to'
1234        if orig_error is None:
1235            orig_error = ''
1236        else:
1237            orig_error = '; ' + str(orig_error)
1238        ConnectionError.__init__(self, msg=msg, orig_error=orig_error)
1239        self.host = host
1240        if port is None:
1241            self.port = ''
1242        else:
1243            self.port = ':%s' % port
1244
1245
1246# XXX: This is also used for unexpected end of file, which is different at the
1247# TCP level from "connection reset".
1248class ConnectionReset(TransportError):
1249
1250    _fmt = "Connection closed: %(msg)s %(orig_error)s"
1251
1252
1253class ConnectionTimeout(ConnectionError):
1254
1255    _fmt = "Connection Timeout: %(msg)s%(orig_error)s"
1256
1257
1258class InvalidRange(TransportError):
1259
1260    _fmt = "Invalid range access in %(path)s at %(offset)s: %(msg)s"
1261
1262    def __init__(self, path, offset, msg=None):
1263        TransportError.__init__(self, msg)
1264        self.path = path
1265        self.offset = offset
1266
1267
1268class InvalidHttpResponse(TransportError):
1269
1270    _fmt = "Invalid http response for %(path)s: %(msg)s%(orig_error)s"
1271
1272    def __init__(self, path, msg, orig_error=None):
1273        self.path = path
1274        if orig_error is None:
1275            orig_error = ''
1276        else:
1277            # This is reached for obscure and unusual errors so we want to
1278            # preserve as much info as possible to ease debug.
1279            orig_error = ': %r' % (orig_error,)
1280        TransportError.__init__(self, msg, orig_error=orig_error)
1281
1282
1283class UnexpectedHttpStatus(InvalidHttpResponse):
1284
1285    _fmt = "Unexpected HTTP status %(code)d for %(path)s: %(extra)s"
1286
1287    def __init__(self, path, code, extra=None):
1288        self.path = path
1289        self.code = code
1290        self.extra = extra or ''
1291        full_msg = 'status code %d unexpected' % code
1292        if extra is not None:
1293            full_msg += ': ' + extra
1294        InvalidHttpResponse.__init__(
1295            self, path, full_msg)
1296
1297
1298class BadHttpRequest(UnexpectedHttpStatus):
1299
1300    _fmt = "Bad http request for %(path)s: %(reason)s"
1301
1302    def __init__(self, path, reason):
1303        self.path = path
1304        self.reason = reason
1305        TransportError.__init__(self, reason)
1306
1307
1308class InvalidHttpRange(InvalidHttpResponse):
1309
1310    _fmt = "Invalid http range %(range)r for %(path)s: %(msg)s"
1311
1312    def __init__(self, path, range, msg):
1313        self.range = range
1314        InvalidHttpResponse.__init__(self, path, msg)
1315
1316
1317class HttpBoundaryMissing(InvalidHttpResponse):
1318    """A multipart response ends with no boundary marker.
1319
1320    This is a special case caused by buggy proxies, described in
1321    <https://bugs.launchpad.net/bzr/+bug/198646>.
1322    """
1323
1324    _fmt = "HTTP MIME Boundary missing for %(path)s: %(msg)s"
1325
1326    def __init__(self, path, msg):
1327        InvalidHttpResponse.__init__(self, path, msg)
1328
1329
1330class InvalidHttpContentType(InvalidHttpResponse):
1331
1332    _fmt = 'Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s'
1333
1334    def __init__(self, path, ctype, msg):
1335        self.ctype = ctype
1336        InvalidHttpResponse.__init__(self, path, msg)
1337
1338
1339class RedirectRequested(TransportError):
1340
1341    _fmt = '%(source)s is%(permanently)s redirected to %(target)s'
1342
1343    def __init__(self, source, target, is_permanent=False):
1344        self.source = source
1345        self.target = target
1346        if is_permanent:
1347            self.permanently = ' permanently'
1348        else:
1349            self.permanently = ''
1350        TransportError.__init__(self)
1351
1352
1353class TooManyRedirections(TransportError):
1354
1355    _fmt = "Too many redirections"
1356
1357
1358class ConflictsInTree(BzrError):
1359
1360    _fmt = "Working tree has conflicts."
1361
1362
1363class DependencyNotPresent(BzrError):
1364
1365    _fmt = 'Unable to import library "%(library)s": %(error)s'
1366
1367    def __init__(self, library, error):
1368        BzrError.__init__(self, library=library, error=error)
1369
1370
1371class WorkingTreeNotRevision(BzrError):
1372
1373    _fmt = ("The working tree for %(basedir)s has changed since"
1374            " the last commit, but weave merge requires that it be"
1375            " unchanged")
1376
1377    def __init__(self, tree):
1378        BzrError.__init__(self, basedir=tree.basedir)
1379
1380
1381class GraphCycleError(BzrError):
1382
1383    _fmt = "Cycle in graph %(graph)r"
1384
1385    def __init__(self, graph):
1386        BzrError.__init__(self)
1387        self.graph = graph
1388
1389
1390class WritingCompleted(InternalBzrError):
1391
1392    _fmt = ("The MediumRequest '%(request)s' has already had finish_writing "
1393            "called upon it - accept bytes may not be called anymore.")
1394
1395    def __init__(self, request):
1396        self.request = request
1397
1398
1399class WritingNotComplete(InternalBzrError):
1400
1401    _fmt = ("The MediumRequest '%(request)s' has not has finish_writing "
1402            "called upon it - until the write phase is complete no "
1403            "data may be read.")
1404
1405    def __init__(self, request):
1406        self.request = request
1407
1408
1409class NotConflicted(BzrError):
1410
1411    _fmt = "File %(filename)s is not conflicted."
1412
1413    def __init__(self, filename):
1414        BzrError.__init__(self)
1415        self.filename = filename
1416
1417
1418class MediumNotConnected(InternalBzrError):
1419
1420    _fmt = """The medium '%(medium)s' is not connected."""
1421
1422    def __init__(self, medium):
1423        self.medium = medium
1424
1425
1426class MustUseDecorated(Exception):
1427
1428    _fmt = "A decorating function has requested its original command be used."
1429
1430
1431class NoBundleFound(BzrError):
1432
1433    _fmt = 'No bundle was found in "%(filename)s".'
1434
1435    def __init__(self, filename):
1436        BzrError.__init__(self)
1437        self.filename = filename
1438
1439
1440class BundleNotSupported(BzrError):
1441
1442    _fmt = "Unable to handle bundle version %(version)s: %(msg)s"
1443
1444    def __init__(self, version, msg):
1445        BzrError.__init__(self)
1446        self.version = version
1447        self.msg = msg
1448
1449
1450class MissingText(BzrError):
1451
1452    _fmt = ("Branch %(base)s is missing revision"
1453            " %(text_revision)s of %(file_id)s")
1454
1455    def __init__(self, branch, text_revision, file_id):
1456        BzrError.__init__(self)
1457        self.branch = branch
1458        self.base = branch.base
1459        self.text_revision = text_revision
1460        self.file_id = file_id
1461
1462
1463class DuplicateKey(BzrError):
1464
1465    _fmt = "Key %(key)s is already present in map"
1466
1467
1468class DuplicateHelpPrefix(BzrError):
1469
1470    _fmt = "The prefix %(prefix)s is in the help search path twice."
1471
1472    def __init__(self, prefix):
1473        self.prefix = prefix
1474
1475
1476class BzrBadParameter(InternalBzrError):
1477
1478    _fmt = "Bad parameter: %(param)r"
1479
1480    # This exception should never be thrown, but it is a base class for all
1481    # parameter-to-function errors.
1482
1483    def __init__(self, param):
1484        BzrError.__init__(self)
1485        self.param = param
1486
1487
1488class BzrBadParameterNotUnicode(BzrBadParameter):
1489
1490    _fmt = "Parameter %(param)s is neither unicode nor utf8."
1491
1492
1493class BzrMoveFailedError(BzrError):
1494
1495    _fmt = ("Could not move %(from_path)s%(operator)s %(to_path)s"
1496            "%(_has_extra)s%(extra)s")
1497
1498    def __init__(self, from_path='', to_path='', extra=None):
1499        from breezy.osutils import splitpath
1500        BzrError.__init__(self)
1501        if extra:
1502            self.extra, self._has_extra = extra, ': '
1503        else:
1504            self.extra = self._has_extra = ''
1505
1506        has_from = len(from_path) > 0
1507        has_to = len(to_path) > 0
1508        if has_from:
1509            self.from_path = splitpath(from_path)[-1]
1510        else:
1511            self.from_path = ''
1512
1513        if has_to:
1514            self.to_path = splitpath(to_path)[-1]
1515        else:
1516            self.to_path = ''
1517
1518        self.operator = ""
1519        if has_from and has_to:
1520            self.operator = " =>"
1521        elif has_from:
1522            self.from_path = "from " + from_path
1523        elif has_to:
1524            self.operator = "to"
1525        else:
1526            self.operator = "file"
1527
1528
1529class BzrRenameFailedError(BzrMoveFailedError):
1530
1531    _fmt = ("Could not rename %(from_path)s%(operator)s %(to_path)s"
1532            "%(_has_extra)s%(extra)s")
1533
1534    def __init__(self, from_path, to_path, extra=None):
1535        BzrMoveFailedError.__init__(self, from_path, to_path, extra)
1536
1537
1538class BzrBadParameterNotString(BzrBadParameter):
1539
1540    _fmt = "Parameter %(param)s is not a string or unicode string."
1541
1542
1543class BzrBadParameterMissing(BzrBadParameter):
1544
1545    _fmt = "Parameter %(param)s is required but not present."
1546
1547
1548class BzrBadParameterUnicode(BzrBadParameter):
1549
1550    _fmt = ("Parameter %(param)s is unicode but"
1551            " only byte-strings are permitted.")
1552
1553
1554class BzrBadParameterContainsNewline(BzrBadParameter):
1555
1556    _fmt = "Parameter %(param)s contains a newline."
1557
1558
1559class ParamikoNotPresent(DependencyNotPresent):
1560
1561    _fmt = "Unable to import paramiko (required for sftp support): %(error)s"
1562
1563    def __init__(self, error):
1564        DependencyNotPresent.__init__(self, 'paramiko', error)
1565
1566
1567class PointlessMerge(BzrError):
1568
1569    _fmt = "Nothing to merge."
1570
1571
1572class UninitializableFormat(BzrError):
1573
1574    _fmt = "Format %(format)s cannot be initialised by this version of brz."
1575
1576    def __init__(self, format):
1577        BzrError.__init__(self)
1578        self.format = format
1579
1580
1581class BadConversionTarget(BzrError):
1582
1583    _fmt = "Cannot convert from format %(from_format)s to format %(format)s." \
1584        "    %(problem)s"
1585
1586    def __init__(self, problem, format, from_format=None):
1587        BzrError.__init__(self)
1588        self.problem = problem
1589        self.format = format
1590        self.from_format = from_format or '(unspecified)'
1591
1592
1593class NoDiffFound(BzrError):
1594
1595    _fmt = 'Could not find an appropriate Differ for file "%(path)s"'
1596
1597    def __init__(self, path):
1598        BzrError.__init__(self, path)
1599
1600
1601class ExecutableMissing(BzrError):
1602
1603    _fmt = "%(exe_name)s could not be found on this machine"
1604
1605    def __init__(self, exe_name):
1606        BzrError.__init__(self, exe_name=exe_name)
1607
1608
1609class NoDiff(BzrError):
1610
1611    _fmt = "Diff is not installed on this machine: %(msg)s"
1612
1613    def __init__(self, msg):
1614        BzrError.__init__(self, msg=msg)
1615
1616
1617class NoDiff3(BzrError):
1618
1619    _fmt = "Diff3 is not installed on this machine."
1620
1621
1622class ExistingLimbo(BzrError):
1623
1624    _fmt = """This tree contains left-over files from a failed operation.
1625    Please examine %(limbo_dir)s to see if it contains any files you wish to
1626    keep, and delete it when you are done."""
1627
1628    def __init__(self, limbo_dir):
1629        BzrError.__init__(self)
1630        self.limbo_dir = limbo_dir
1631
1632
1633class ExistingPendingDeletion(BzrError):
1634
1635    _fmt = """This tree contains left-over files from a failed operation.
1636    Please examine %(pending_deletion)s to see if it contains any files you
1637    wish to keep, and delete it when you are done."""
1638
1639    def __init__(self, pending_deletion):
1640        BzrError.__init__(self, pending_deletion=pending_deletion)
1641
1642
1643class ImmortalPendingDeletion(BzrError):
1644
1645    _fmt = ("Unable to delete transform temporary directory "
1646            "%(pending_deletion)s.  Please examine %(pending_deletion)s to see if it "
1647            "contains any files you wish to keep, and delete it when you are done.")
1648
1649    def __init__(self, pending_deletion):
1650        BzrError.__init__(self, pending_deletion=pending_deletion)
1651
1652
1653class OutOfDateTree(BzrError):
1654
1655    _fmt = "Working tree is out of date, please run 'brz update'.%(more)s"
1656
1657    def __init__(self, tree, more=None):
1658        if more is None:
1659            more = ''
1660        else:
1661            more = ' ' + more
1662        BzrError.__init__(self)
1663        self.tree = tree
1664        self.more = more
1665
1666
1667class PublicBranchOutOfDate(BzrError):
1668
1669    _fmt = 'Public branch "%(public_location)s" lacks revision '\
1670        '"%(revstring)s".'
1671
1672    def __init__(self, public_location, revstring):
1673        import breezy.urlutils as urlutils
1674        public_location = urlutils.unescape_for_display(public_location,
1675                                                        'ascii')
1676        BzrError.__init__(self, public_location=public_location,
1677                          revstring=revstring)
1678
1679
1680class MergeModifiedFormatError(BzrError):
1681
1682    _fmt = "Error in merge modified format"
1683
1684
1685class ConflictFormatError(BzrError):
1686
1687    _fmt = "Format error in conflict listings"
1688
1689
1690class CorruptRepository(BzrError):
1691
1692    _fmt = ("An error has been detected in the repository %(repo_path)s.\n"
1693            "Please run brz reconcile on this repository.")
1694
1695    def __init__(self, repo):
1696        BzrError.__init__(self)
1697        self.repo_path = repo.user_url
1698
1699
1700class InconsistentDelta(BzrError):
1701    """Used when we get a delta that is not valid."""
1702
1703    _fmt = ("An inconsistent delta was supplied involving %(path)r,"
1704            " %(file_id)r\nreason: %(reason)s")
1705
1706    def __init__(self, path, file_id, reason):
1707        BzrError.__init__(self)
1708        self.path = path
1709        self.file_id = file_id
1710        self.reason = reason
1711
1712
1713class InconsistentDeltaDelta(InconsistentDelta):
1714    """Used when we get a delta that is not valid."""
1715
1716    _fmt = ("An inconsistent delta was supplied: %(delta)r"
1717            "\nreason: %(reason)s")
1718
1719    def __init__(self, delta, reason):
1720        BzrError.__init__(self)
1721        self.delta = delta
1722        self.reason = reason
1723
1724
1725class UpgradeRequired(BzrError):
1726
1727    _fmt = "To use this feature you must upgrade your branch at %(path)s."
1728
1729    def __init__(self, path):
1730        BzrError.__init__(self)
1731        self.path = path
1732
1733
1734class RepositoryUpgradeRequired(UpgradeRequired):
1735
1736    _fmt = "To use this feature you must upgrade your repository at %(path)s."
1737
1738
1739class RichRootUpgradeRequired(UpgradeRequired):
1740
1741    _fmt = ("To use this feature you must upgrade your branch at %(path)s to"
1742            " a format which supports rich roots.")
1743
1744
1745class LocalRequiresBoundBranch(BzrError):
1746
1747    _fmt = "Cannot perform local-only commits on unbound branches."
1748
1749
1750class UnsupportedOperation(BzrError):
1751
1752    _fmt = ("The method %(mname)s is not supported on"
1753            " objects of type %(tname)s.")
1754
1755    def __init__(self, method, method_self):
1756        self.method = method
1757        self.mname = method.__name__
1758        self.tname = type(method_self).__name__
1759
1760
1761class FetchLimitUnsupported(UnsupportedOperation):
1762
1763    fmt = ("InterBranch %(interbranch)r does not support fetching limits.")
1764
1765    def __init__(self, interbranch):
1766        BzrError.__init__(self, interbranch=interbranch)
1767
1768
1769class NonAsciiRevisionId(UnsupportedOperation):
1770    """Raised when a commit is attempting to set a non-ascii revision id
1771       but cant.
1772    """
1773
1774
1775class SharedRepositoriesUnsupported(UnsupportedOperation):
1776    _fmt = "Shared repositories are not supported by %(format)r."
1777
1778    def __init__(self, format):
1779        BzrError.__init__(self, format=format)
1780
1781
1782class GhostTagsNotSupported(BzrError):
1783
1784    _fmt = "Ghost tags not supported by format %(format)r."
1785
1786    def __init__(self, format):
1787        self.format = format
1788
1789
1790class BinaryFile(BzrError):
1791
1792    _fmt = "File is binary but should be text."
1793
1794
1795class IllegalPath(BzrError):
1796
1797    _fmt = "The path %(path)s is not permitted on this platform"
1798
1799    def __init__(self, path):
1800        BzrError.__init__(self)
1801        self.path = path
1802
1803
1804class TestamentMismatch(BzrError):
1805
1806    _fmt = """Testament did not match expected value.
1807       For revision_id {%(revision_id)s}, expected {%(expected)s}, measured
1808       {%(measured)s}"""
1809
1810    def __init__(self, revision_id, expected, measured):
1811        self.revision_id = revision_id
1812        self.expected = expected
1813        self.measured = measured
1814
1815
1816class NotABundle(BzrError):
1817
1818    _fmt = "Not a bzr revision-bundle: %(text)r"
1819
1820    def __init__(self, text):
1821        BzrError.__init__(self)
1822        self.text = text
1823
1824
1825class BadBundle(BzrError):
1826
1827    _fmt = "Bad bzr revision-bundle: %(text)r"
1828
1829    def __init__(self, text):
1830        BzrError.__init__(self)
1831        self.text = text
1832
1833
1834class MalformedHeader(BadBundle):
1835
1836    _fmt = "Malformed bzr revision-bundle header: %(text)r"
1837
1838
1839class MalformedPatches(BadBundle):
1840
1841    _fmt = "Malformed patches in bzr revision-bundle: %(text)r"
1842
1843
1844class MalformedFooter(BadBundle):
1845
1846    _fmt = "Malformed footer in bzr revision-bundle: %(text)r"
1847
1848
1849class UnsupportedEOLMarker(BadBundle):
1850
1851    _fmt = "End of line marker was not \\n in bzr revision-bundle"
1852
1853    def __init__(self):
1854        # XXX: BadBundle's constructor assumes there's explanatory text,
1855        # but for this there is not
1856        BzrError.__init__(self)
1857
1858
1859class IncompatibleBundleFormat(BzrError):
1860
1861    _fmt = "Bundle format %(bundle_format)s is incompatible with %(other)s"
1862
1863    def __init__(self, bundle_format, other):
1864        BzrError.__init__(self)
1865        self.bundle_format = bundle_format
1866        self.other = other
1867
1868
1869class RootNotRich(BzrError):
1870
1871    _fmt = """This operation requires rich root data storage"""
1872
1873
1874class NoSmartMedium(InternalBzrError):
1875
1876    _fmt = "The transport '%(transport)s' cannot tunnel the smart protocol."
1877
1878    def __init__(self, transport):
1879        self.transport = transport
1880
1881
1882class UnknownSSH(BzrError):
1883
1884    _fmt = "Unrecognised value for BRZ_SSH environment variable: %(vendor)s"
1885
1886    def __init__(self, vendor):
1887        BzrError.__init__(self)
1888        self.vendor = vendor
1889
1890
1891class SSHVendorNotFound(BzrError):
1892
1893    _fmt = ("Don't know how to handle SSH connections."
1894            " Please set BRZ_SSH environment variable.")
1895
1896
1897class GhostRevisionsHaveNoRevno(BzrError):
1898    """When searching for revnos, if we encounter a ghost, we are stuck"""
1899
1900    _fmt = ("Could not determine revno for {%(revision_id)s} because"
1901            " its ancestry shows a ghost at {%(ghost_revision_id)s}")
1902
1903    def __init__(self, revision_id, ghost_revision_id):
1904        self.revision_id = revision_id
1905        self.ghost_revision_id = ghost_revision_id
1906
1907
1908class GhostRevisionUnusableHere(BzrError):
1909
1910    _fmt = "Ghost revision {%(revision_id)s} cannot be used here."
1911
1912    def __init__(self, revision_id):
1913        BzrError.__init__(self)
1914        self.revision_id = revision_id
1915
1916
1917class NotAMergeDirective(BzrError):
1918    """File starting with %(firstline)r is not a merge directive"""
1919
1920    def __init__(self, firstline):
1921        BzrError.__init__(self, firstline=firstline)
1922
1923
1924class NoMergeSource(BzrError):
1925    """Raise if no merge source was specified for a merge directive"""
1926
1927    _fmt = "A merge directive must provide either a bundle or a public"\
1928        " branch location."
1929
1930
1931class PatchVerificationFailed(BzrError):
1932    """A patch from a merge directive could not be verified"""
1933
1934    _fmt = "Preview patch does not match requested changes."
1935
1936
1937class PatchMissing(BzrError):
1938    """Raise a patch type was specified but no patch supplied"""
1939
1940    _fmt = "Patch_type was %(patch_type)s, but no patch was supplied."
1941
1942    def __init__(self, patch_type):
1943        BzrError.__init__(self)
1944        self.patch_type = patch_type
1945
1946
1947class TargetNotBranch(BzrError):
1948    """A merge directive's target branch is required, but isn't a branch"""
1949
1950    _fmt = ("Your branch does not have all of the revisions required in "
1951            "order to merge this merge directive and the target "
1952            "location specified in the merge directive is not a branch: "
1953            "%(location)s.")
1954
1955    def __init__(self, location):
1956        BzrError.__init__(self)
1957        self.location = location
1958
1959
1960class BadSubsumeSource(BzrError):
1961
1962    _fmt = "Can't subsume %(other_tree)s into %(tree)s. %(reason)s"
1963
1964    def __init__(self, tree, other_tree, reason):
1965        self.tree = tree
1966        self.other_tree = other_tree
1967        self.reason = reason
1968
1969
1970class SubsumeTargetNeedsUpgrade(BzrError):
1971
1972    _fmt = """Subsume target %(other_tree)s needs to be upgraded."""
1973
1974    def __init__(self, other_tree):
1975        self.other_tree = other_tree
1976
1977
1978class NoSuchTag(BzrError):
1979
1980    _fmt = "No such tag: %(tag_name)s"
1981
1982    def __init__(self, tag_name):
1983        self.tag_name = tag_name
1984
1985
1986class TagsNotSupported(BzrError):
1987
1988    _fmt = ("Tags not supported by %(branch)s;"
1989            " you may be able to use 'brz upgrade %(branch_url)s'.")
1990
1991    def __init__(self, branch):
1992        self.branch = branch
1993        self.branch_url = branch.user_url
1994
1995
1996class TagAlreadyExists(BzrError):
1997
1998    _fmt = "Tag %(tag_name)s already exists."
1999
2000    def __init__(self, tag_name):
2001        self.tag_name = tag_name
2002
2003
2004class UnexpectedSmartServerResponse(BzrError):
2005
2006    _fmt = "Could not understand response from smart server: %(response_tuple)r"
2007
2008    def __init__(self, response_tuple):
2009        self.response_tuple = response_tuple
2010
2011
2012class ErrorFromSmartServer(BzrError):
2013    """An error was received from a smart server.
2014
2015    :seealso: UnknownErrorFromSmartServer
2016    """
2017
2018    _fmt = "Error received from smart server: %(error_tuple)r"
2019
2020    internal_error = True
2021
2022    def __init__(self, error_tuple):
2023        self.error_tuple = error_tuple
2024        try:
2025            self.error_verb = error_tuple[0]
2026        except IndexError:
2027            self.error_verb = None
2028        self.error_args = error_tuple[1:]
2029
2030
2031class UnknownErrorFromSmartServer(BzrError):
2032    """An ErrorFromSmartServer could not be translated into a typical breezy
2033    error.
2034
2035    This is distinct from ErrorFromSmartServer so that it is possible to
2036    distinguish between the following two cases:
2037
2038    - ErrorFromSmartServer was uncaught.  This is logic error in the client
2039      and so should provoke a traceback to the user.
2040    - ErrorFromSmartServer was caught but its error_tuple could not be
2041      translated.  This is probably because the server sent us garbage, and
2042      should not provoke a traceback.
2043    """
2044
2045    _fmt = "Server sent an unexpected error: %(error_tuple)r"
2046
2047    internal_error = False
2048
2049    def __init__(self, error_from_smart_server):
2050        """Constructor.
2051
2052        :param error_from_smart_server: An ErrorFromSmartServer instance.
2053        """
2054        self.error_from_smart_server = error_from_smart_server
2055        self.error_tuple = error_from_smart_server.error_tuple
2056
2057
2058class ContainerError(BzrError):
2059    """Base class of container errors."""
2060
2061
2062class UnknownContainerFormatError(ContainerError):
2063
2064    _fmt = "Unrecognised container format: %(container_format)r"
2065
2066    def __init__(self, container_format):
2067        self.container_format = container_format
2068
2069
2070class UnexpectedEndOfContainerError(ContainerError):
2071
2072    _fmt = "Unexpected end of container stream"
2073
2074
2075class UnknownRecordTypeError(ContainerError):
2076
2077    _fmt = "Unknown record type: %(record_type)r"
2078
2079    def __init__(self, record_type):
2080        self.record_type = record_type
2081
2082
2083class InvalidRecordError(ContainerError):
2084
2085    _fmt = "Invalid record: %(reason)s"
2086
2087    def __init__(self, reason):
2088        self.reason = reason
2089
2090
2091class ContainerHasExcessDataError(ContainerError):
2092
2093    _fmt = "Container has data after end marker: %(excess)r"
2094
2095    def __init__(self, excess):
2096        self.excess = excess
2097
2098
2099class DuplicateRecordNameError(ContainerError):
2100
2101    _fmt = "Container has multiple records with the same name: %(name)s"
2102
2103    def __init__(self, name):
2104        self.name = name.decode("utf-8")
2105
2106
2107class RepositoryDataStreamError(BzrError):
2108
2109    _fmt = "Corrupt or incompatible data stream: %(reason)s"
2110
2111    def __init__(self, reason):
2112        self.reason = reason
2113
2114
2115class UncommittedChanges(BzrError):
2116
2117    _fmt = ('Working tree "%(display_url)s" has uncommitted changes'
2118            ' (See brz status).%(more)s')
2119
2120    def __init__(self, tree, more=None):
2121        if more is None:
2122            more = ''
2123        else:
2124            more = ' ' + more
2125        import breezy.urlutils as urlutils
2126        user_url = getattr(tree, "user_url", None)
2127        if user_url is None:
2128            display_url = str(tree)
2129        else:
2130            display_url = urlutils.unescape_for_display(user_url, 'ascii')
2131        BzrError.__init__(self, tree=tree, display_url=display_url, more=more)
2132
2133
2134class StoringUncommittedNotSupported(BzrError):
2135
2136    _fmt = ('Branch "%(display_url)s" does not support storing uncommitted'
2137            ' changes.')
2138
2139    def __init__(self, branch):
2140        import breezy.urlutils as urlutils
2141        user_url = getattr(branch, "user_url", None)
2142        if user_url is None:
2143            display_url = str(branch)
2144        else:
2145            display_url = urlutils.unescape_for_display(user_url, 'ascii')
2146        BzrError.__init__(self, branch=branch, display_url=display_url)
2147
2148
2149class ShelvedChanges(UncommittedChanges):
2150
2151    _fmt = ('Working tree "%(display_url)s" has shelved changes'
2152            ' (See brz shelve --list).%(more)s')
2153
2154
2155class UnableEncodePath(BzrError):
2156
2157    _fmt = ('Unable to encode %(kind)s path %(path)r in '
2158            'user encoding %(user_encoding)s')
2159
2160    def __init__(self, path, kind):
2161        from breezy.osutils import get_user_encoding
2162        self.path = path
2163        self.kind = kind
2164        self.user_encoding = get_user_encoding()
2165
2166
2167class NoSuchAlias(BzrError):
2168
2169    _fmt = ('The alias "%(alias_name)s" does not exist.')
2170
2171    def __init__(self, alias_name):
2172        BzrError.__init__(self, alias_name=alias_name)
2173
2174
2175class CannotBindAddress(BzrError):
2176
2177    _fmt = 'Cannot bind address "%(host)s:%(port)i": %(orig_error)s.'
2178
2179    def __init__(self, host, port, orig_error):
2180        # nb: in python2.4 socket.error doesn't have a useful repr
2181        BzrError.__init__(self, host=host, port=port,
2182                          orig_error=repr(orig_error.args))
2183
2184
2185class TipChangeRejected(BzrError):
2186    """A pre_change_branch_tip hook function may raise this to cleanly and
2187    explicitly abort a change to a branch tip.
2188    """
2189
2190    _fmt = u"Tip change rejected: %(msg)s"
2191
2192    def __init__(self, msg):
2193        self.msg = msg
2194
2195
2196class JailBreak(BzrError):
2197
2198    _fmt = "An attempt to access a url outside the server jail was made: '%(url)s'."
2199
2200    def __init__(self, url):
2201        BzrError.__init__(self, url=url)
2202
2203
2204class UserAbort(BzrError):
2205
2206    _fmt = 'The user aborted the operation.'
2207
2208
2209class UnresumableWriteGroup(BzrError):
2210
2211    _fmt = ("Repository %(repository)s cannot resume write group "
2212            "%(write_groups)r: %(reason)s")
2213
2214    internal_error = True
2215
2216    def __init__(self, repository, write_groups, reason):
2217        self.repository = repository
2218        self.write_groups = write_groups
2219        self.reason = reason
2220
2221
2222class UnsuspendableWriteGroup(BzrError):
2223
2224    _fmt = ("Repository %(repository)s cannot suspend a write group.")
2225
2226    internal_error = True
2227
2228    def __init__(self, repository):
2229        self.repository = repository
2230
2231
2232class LossyPushToSameVCS(BzrError):
2233
2234    _fmt = ("Lossy push not possible between %(source_branch)r and "
2235            "%(target_branch)r that are in the same VCS.")
2236
2237    internal_error = True
2238
2239    def __init__(self, source_branch, target_branch):
2240        self.source_branch = source_branch
2241        self.target_branch = target_branch
2242
2243
2244class NoRoundtrippingSupport(BzrError):
2245
2246    _fmt = ("Roundtripping is not supported between %(source_branch)r and "
2247            "%(target_branch)r.")
2248
2249    internal_error = True
2250
2251    def __init__(self, source_branch, target_branch):
2252        self.source_branch = source_branch
2253        self.target_branch = target_branch
2254
2255
2256class NoColocatedBranchSupport(BzrError):
2257
2258    _fmt = ("%(controldir)r does not support co-located branches.")
2259
2260    def __init__(self, controldir):
2261        self.controldir = controldir
2262
2263
2264class RecursiveBind(BzrError):
2265
2266    _fmt = ('Branch "%(branch_url)s" appears to be bound to itself. '
2267            'Please use `brz unbind` to fix.')
2268
2269    def __init__(self, branch_url):
2270        self.branch_url = branch_url
2271
2272
2273class UnsupportedKindChange(BzrError):
2274
2275    _fmt = ("Kind change from %(from_kind)s to %(to_kind)s for "
2276            "%(path)s not supported by format %(format)r")
2277
2278    def __init__(self, path, from_kind, to_kind, format):
2279        self.path = path
2280        self.from_kind = from_kind
2281        self.to_kind = to_kind
2282        self.format = format
2283
2284
2285class ChangesAlreadyStored(CommandError):
2286
2287    _fmt = ('Cannot store uncommitted changes because this branch already'
2288            ' stores uncommitted changes.')
2289
2290
2291class RevnoOutOfBounds(InternalBzrError):
2292
2293    _fmt = ("The requested revision number %(revno)d is outside of the "
2294            "expected boundaries (%(minimum)d <= %(maximum)d).")
2295
2296    def __init__(self, revno, bounds):
2297        InternalBzrError.__init__(
2298            self, revno=revno, minimum=bounds[0], maximum=bounds[1])
2299