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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Exceptions for bzr, and reporting of them.
20
21
from bzrlib import (
33
34
# TODO: is there any value in providing the .args field used by standard
34
# python exceptions? A list of values with no names seems less useful
35
# python exceptions? A list of values with no names seems less useful
37
# TODO: Perhaps convert the exception to a string at the moment it's
38
# TODO: Perhaps convert the exception to a string at the moment it's
38
39
# constructed to make sure it will succeed. But that says nothing about
39
40
# exceptions that are never raised.
72
73
arguments can be given. The first is for generic "user" errors which
73
74
are not intended to be caught and so do not need a specific subclass.
74
75
The second case is for use with subclasses that provide a _fmt format
75
string to print the arguments.
76
string to print the arguments.
77
Keyword arguments are taken as parameters to the error, which can
78
be inserted into the format string template. It's recommended
79
that subclasses override the __init__ method to require specific
78
Keyword arguments are taken as parameters to the error, which can
79
be inserted into the format string template. It's recommended
80
that subclasses override the __init__ method to require specific
82
83
:param msg: If given, this is the literal complete text for the error,
83
not subject to expansion. 'msg' is used instead of 'message' because
84
python evolved and, in 2.6, forbids the use of 'message'.
84
not subject to expansion.
86
86
StandardError.__init__(self)
87
87
if msg is not None:
102
102
fmt = self._get_format_string()
104
104
d = dict(self.__dict__)
105
# special case: python2.5 puts the 'message' attribute in a
106
# slot, so it isn't seen in __dict__
107
d['message'] = getattr(self, 'message', 'no message')
106
109
# __str__() should always return a 'str' object
107
110
# never a 'unicode' object.
486
486
# XXX: Should be unified with TransportError; they seem to represent the
488
488
# RBC 20060929: I think that unifiying with TransportError would be a mistake
489
# - this is finer than a TransportError - and more useful as such. It
489
# - this is finer than a TransportError - and more useful as such. It
490
490
# differentiates between 'transport has failed' and 'operation on a transport
492
492
class PathError(BzrError):
494
494
_fmt = "Generic path error: %(path)r%(extra)s)"
496
496
def __init__(self, path, extra=None):
1004
1004
class LockContention(LockError):
1006
_fmt = 'Could not acquire lock "%(lock)s": %(msg)s'
1006
_fmt = 'Could not acquire lock "%(lock)s"'
1007
1007
# TODO: show full url for lock, combining the transport and relative
1010
1010
internal_error = False
1012
def __init__(self, lock, msg=''):
1012
def __init__(self, lock):
1013
1013
self.lock = lock
1017
1016
class LockBroken(LockError):
1430
class SHA1KnitCorrupt(KnitCorrupt):
1432
_fmt = ("Knit %(filename)s corrupt: sha-1 of reconstructed text does not "
1433
"match expected sha-1. key %(key)s expected sha %(expected)s actual "
1436
def __init__(self, filename, actual, expected, key, content):
1437
KnitError.__init__(self)
1438
self.filename = filename
1439
self.actual = actual
1440
self.expected = expected
1442
self.content = content
1445
1429
class KnitDataStreamIncompatible(KnitError):
1446
1430
# Not raised anymore, as we can convert data streams. In future we may
1447
1431
# need it again for more exotic cases, so we're keeping it around for now.
1486
1470
self.options = options
1489
class RetryWithNewPacks(BzrError):
1490
"""Raised when we realize that the packs on disk have changed.
1492
This is meant as more of a signaling exception, to trap between where a
1493
local error occurred and the code that can actually handle the error and
1494
code that can retry appropriately.
1497
internal_error = True
1499
_fmt = ("Pack files have changed, reload and retry. context: %(context)s"
1502
def __init__(self, context, reload_occurred, exc_info):
1503
"""create a new RetryWithNewPacks error.
1505
:param reload_occurred: Set to True if we know that the packs have
1506
already been reloaded, and we are failing because of an in-memory
1507
cache miss. If set to True then we will ignore if a reload says
1508
nothing has changed, because we assume it has already reloaded. If
1509
False, then a reload with nothing changed will force an error.
1510
:param exc_info: The original exception traceback, so if there is a
1511
problem we can raise the original error (value from sys.exc_info())
1513
BzrError.__init__(self)
1514
self.reload_occurred = reload_occurred
1515
self.exc_info = exc_info
1516
self.orig_error = exc_info[1]
1517
# TODO: The global error handler should probably treat this by
1518
# raising/printing the original exception with a bit about
1519
# RetryWithNewPacks also not being caught
1522
class RetryAutopack(RetryWithNewPacks):
1523
"""Raised when we are autopacking and we find a missing file.
1525
Meant as a signaling exception, to tell the autopack code it should try
1529
internal_error = True
1531
_fmt = ("Pack files have changed, reload and try autopack again."
1532
" context: %(context)s %(orig_error)s")
1535
1473
class NoSuchExportFormat(BzrError):
1537
1475
_fmt = "Export format %(format)r not supported"
1539
1477
def __init__(self, format):
1594
1532
class SmartMessageHandlerError(InternalBzrError):
1596
_fmt = ("The message handler raised an exception:\n"
1597
"%(traceback_text)s")
1534
_fmt = "The message handler raised an exception: %(exc_value)s."
1599
1536
def __init__(self, exc_info):
1601
self.exc_type, self.exc_value, self.exc_tb = exc_info
1602
self.exc_info = exc_info
1603
traceback_strings = traceback.format_exception(
1604
self.exc_type, self.exc_value, self.exc_tb)
1605
self.traceback_text = ''.join(traceback_strings)
1537
self.exc_type, self.exc_value, self.tb = exc_info
1608
1540
# A set of semi-meaningful errors which can be thrown
1609
1541
class TransportNotPossible(TransportError):
1684
1614
_fmt = '%(source)s is%(permanently)s redirected to %(target)s'
1686
def __init__(self, source, target, is_permanent=False):
1616
def __init__(self, source, target, is_permanent=False, qual_proto=None):
1687
1617
self.source = source
1688
1618
self.target = target
1689
1619
if is_permanent:
1690
1620
self.permanently = ' permanently'
1692
1622
self.permanently = ''
1623
self._qualified_proto = qual_proto
1693
1624
TransportError.__init__(self)
1626
def _requalify_url(self, url):
1627
"""Restore the qualified proto in front of the url"""
1628
# When this exception is raised, source and target are in
1629
# user readable format. But some transports may use a
1630
# different proto (http+urllib:// will present http:// to
1631
# the user. If a qualified proto is specified, the code
1632
# trapping the exception can get the qualified urls to
1633
# properly handle the redirection themself (creating a
1634
# new transport object from the target url for example).
1635
# But checking that the scheme of the original and
1636
# redirected urls are the same can be tricky. (see the
1637
# FIXME in BzrDir.open_from_transport for the unique use
1639
if self._qualified_proto is None:
1642
# The TODO related to NotBranchError mention that doing
1643
# that kind of manipulation on the urls may not be the
1644
# exception object job. On the other hand, this object is
1645
# the interface between the code and the user so
1646
# presenting the urls in different ways is indeed its
1649
proto, netloc, path, query, fragment = urlparse.urlsplit(url)
1650
return urlparse.urlunsplit((self._qualified_proto, netloc, path,
1653
def get_source_url(self):
1654
return self._requalify_url(self.source)
1656
def get_target_url(self):
1657
return self._requalify_url(self.target)
1696
1660
class TooManyRedirections(TransportError):
2248
2216
self.text = text
2251
class MalformedHeader(BadBundle):
2219
class MalformedHeader(BadBundle):
2253
2221
_fmt = "Malformed bzr revision-bundle header: %(text)r"
2256
class MalformedPatches(BadBundle):
2224
class MalformedPatches(BadBundle):
2258
2226
_fmt = "Malformed patches in bzr revision-bundle: %(text)r"
2261
class MalformedFooter(BadBundle):
2229
class MalformedFooter(BadBundle):
2263
2231
_fmt = "Malformed footer in bzr revision-bundle: %(text)r"
2266
2234
class UnsupportedEOLMarker(BadBundle):
2268
_fmt = "End of line marker was not \\n in bzr revision-bundle"
2236
_fmt = "End of line marker was not \\n in bzr revision-bundle"
2270
2238
def __init__(self):
2271
# XXX: BadBundle's constructor assumes there's explanatory text,
2239
# XXX: BadBundle's constructor assumes there's explanatory text,
2272
2240
# but for this there is not
2273
2241
BzrError.__init__(self)
2276
2244
class IncompatibleBundleFormat(BzrError):
2278
2246
_fmt = "Bundle format %(bundle_format)s is incompatible with %(other)s"
2280
2248
def __init__(self, bundle_format, other):
2523
2499
self.branch = branch
2526
class InvalidLineInBugsProperty(BzrError):
2528
_fmt = ("Invalid line in bugs property: '%(line)s'")
2530
def __init__(self, line):
2534
class InvalidBugStatus(BzrError):
2536
_fmt = ("Invalid bug status: '%(status)s'")
2538
def __init__(self, status):
2539
self.status = status
2542
2502
class UnexpectedSmartServerResponse(BzrError):
2544
2504
_fmt = "Could not understand response from smart server: %(response_tuple)r"
2566
2522
self.error_args = error_tuple[1:]
2569
class UnknownErrorFromSmartServer(BzrError):
2570
"""An ErrorFromSmartServer could not be translated into a typical bzrlib
2573
This is distinct from ErrorFromSmartServer so that it is possible to
2574
distinguish between the following two cases:
2575
- ErrorFromSmartServer was uncaught. This is logic error in the client
2576
and so should provoke a traceback to the user.
2577
- ErrorFromSmartServer was caught but its error_tuple could not be
2578
translated. This is probably because the server sent us garbage, and
2579
should not provoke a traceback.
2582
_fmt = "Server sent an unexpected error: %(error_tuple)r"
2584
internal_error = False
2586
def __init__(self, error_from_smart_server):
2589
:param error_from_smart_server: An ErrorFromSmartServer instance.
2591
self.error_from_smart_server = error_from_smart_server
2592
self.error_tuple = error_from_smart_server.error_tuple
2595
2525
class ContainerError(BzrError):
2596
2526
"""Base class of container errors."""
2755
2685
_fmt = "'%(display_url)s' is already standalone."
2758
class AlreadyWithTrees(BzrDirError):
2760
_fmt = ("Shared repository '%(display_url)s' already creates "
2764
class AlreadyWithNoTrees(BzrDirError):
2766
_fmt = ("Shared repository '%(display_url)s' already doesn't create "
2770
2688
class ReconfigurationNotSupported(BzrDirError):
2772
2690
_fmt = "Requested reconfiguration of '%(display_url)s' is not supported."
2828
2746
class CommandAvailableInPlugin(StandardError):
2830
2748
internal_error = False
2832
2750
def __init__(self, cmd_name, plugin_metadata, provider):
2834
2752
self.plugin_metadata = plugin_metadata
2835
2753
self.cmd_name = cmd_name
2836
2754
self.provider = provider
2838
2756
def __str__(self):
2840
_fmt = ('"%s" is not a standard bzr command. \n'
2758
_fmt = ('"%s" is not a standard bzr command. \n'
2841
2759
'However, the following official plugin provides this command: %s\n'
2842
2760
'You can install it by going to: %s'
2843
% (self.cmd_name, self.plugin_metadata['name'],
2761
% (self.cmd_name, self.plugin_metadata['name'],
2844
2762
self.plugin_metadata['url']))
2849
2767
class NoPluginAvailable(BzrError):
2853
2771
class NotATerminal(BzrError):
2937
2854
"""A pre_change_branch_tip hook function may raise this to cleanly and
2938
2855
explicitly abort a change to a branch tip.
2941
2858
_fmt = u"Tip change rejected: %(msg)s"
2943
2860
def __init__(self, msg):
2947
class ShelfCorrupt(BzrError):
2949
_fmt = "Shelf corrupt."
2952
class NoSuchShelfId(BzrError):
2954
_fmt = 'No changes are shelved with id "%(shelf_id)d".'
2956
def __init__(self, shelf_id):
2957
BzrError.__init__(self, shelf_id=shelf_id)
2960
class InvalidShelfId(BzrError):
2962
_fmt = '"%(invalid_id)s" is not a valid shelf id, try a number instead.'
2964
def __init__(self, invalid_id):
2965
BzrError.__init__(self, invalid_id=invalid_id)
2968
class UserAbort(BzrError):
2970
_fmt = 'The user aborted the operation.'
2973
class MustHaveWorkingTree(BzrError):
2975
_fmt = ("Branching '%(url)s'(%(format)s) must create a working tree.")
2977
def __init__(self, format, url):
2978
BzrError.__init__(self, format=format, url=url)
2981
class NoSuchView(BzrError):
2982
"""A view does not exist.
2985
_fmt = u"No such view: %(view_name)s."
2987
def __init__(self, view_name):
2988
self.view_name = view_name
2991
class ViewsNotSupported(BzrError):
2992
"""Views are not supported by a tree format.
2995
_fmt = ("Views are not supported by %(tree)s;"
2996
" use 'bzr upgrade' to change your tree to a later format.")
2998
def __init__(self, tree):
3002
class FileOutsideView(BzrError):
3004
_fmt = ('Specified file "%(file_name)s" is outside the current view: '
3007
def __init__(self, file_name, view_files):
3008
self.file_name = file_name
3009
self.view_str = ", ".join(view_files)
3012
class UnresumableWriteGroup(BzrError):
3014
_fmt = ("Repository %(repository)s cannot resume write group "
3015
"%(write_groups)r: %(reason)s")
3017
internal_error = True
3019
def __init__(self, repository, write_groups, reason):
3020
self.repository = repository
3021
self.write_groups = write_groups
3022
self.reason = reason
3025
class UnsuspendableWriteGroup(BzrError):
3027
_fmt = ("Repository %(repository)s cannot suspend a write group.")
3029
internal_error = True
3031
def __init__(self, repository):
3032
self.repository = repository