Merge lp:~jelmer/brz/move-errors-views into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Merged at revision: 6740
Proposed branch: lp:~jelmer/brz/move-errors-views
Merge into: lp:brz
Diff against target: 1186 lines (+297/-254)
24 files modified
breezy/builtins.py (+3/-3)
breezy/bzr/smart/medium.py (+16/-3)
breezy/bzr/smart/request.py (+9/-0)
breezy/bzr/smart/vfs.py (+1/-1)
breezy/commands.py (+29/-5)
breezy/errors.py (+0/-153)
breezy/mail_client.py (+30/-8)
breezy/shelf.py (+24/-4)
breezy/shelf_ui.py (+1/-1)
breezy/smtp_connection.py (+31/-4)
breezy/tests/__init__.py (+1/-0)
breezy/tests/per_workingtree/test_views.py (+19/-19)
breezy/tests/test_errors.py (+0/-27)
breezy/tests/test_mail_client.py (+2/-2)
breezy/tests/test_shelf.py (+11/-2)
breezy/tests/test_shelf_ui.py (+2/-1)
breezy/tests/test_smart_request.py (+8/-0)
breezy/tests/test_smart_transport.py (+1/-1)
breezy/tests/test_smtp_connection.py (+8/-8)
breezy/tests/test_treebuilder.py (+8/-4)
breezy/tests/test_views.py (+44/-0)
breezy/treebuilder.py (+12/-2)
breezy/views.py (+36/-5)
breezy/workingtree.py (+1/-1)
To merge this branch: bzr merge lp:~jelmer/brz/move-errors-views
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+327933@code.launchpad.net

Commit message

Move a few more errors out of breezy.errors.

Description of the change

Move a few more errors to their respective modules, out of breezy.errors:

 * views
 * shelf
 * smtp

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Changes look okay.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'breezy/builtins.py'
--- breezy/builtins.py 2017-07-21 14:18:24 +0000
+++ breezy/builtins.py 2017-07-23 16:06:20 +0000
@@ -245,7 +245,7 @@
245 if view_files:245 if view_files:
246 for filename in file_list:246 for filename in file_list:
247 if not osutils.is_inside_any(view_files, filename):247 if not osutils.is_inside_any(view_files, filename):
248 raise errors.FileOutsideView(filename, view_files)248 raise views.FileOutsideView(filename, view_files)
249 file_list = file_list[:]249 file_list = file_list[:]
250 file_list[0] = tree.abspath(relpath)250 file_list[0] = tree.abspath(relpath)
251 else:251 else:
@@ -299,7 +299,7 @@
299 current_view = tree.views.get_view_info()[0]299 current_view = tree.views.get_view_info()[0]
300 if current_view is not None:300 if current_view is not None:
301 view_info = (current_view, tree.views.lookup_view())301 view_info = (current_view, tree.views.lookup_view())
302 except errors.ViewsNotSupported:302 except views.ViewsNotSupported:
303 pass303 pass
304 return view_info304 return view_info
305305
@@ -3040,7 +3040,7 @@
3040 else:3040 else:
3041 fullpath = fp3041 fullpath = fp
3042 views.check_path_in_view(tree, fullpath)3042 views.check_path_in_view(tree, fullpath)
3043 except errors.FileOutsideView:3043 except views.FileOutsideView:
3044 continue3044 continue
30453045
3046 # Output the entry3046 # Output the entry
30473047
=== modified file 'breezy/bzr/smart/medium.py'
--- breezy/bzr/smart/medium.py 2017-06-11 20:15:04 +0000
+++ breezy/bzr/smart/medium.py 2017-07-23 16:06:20 +0000
@@ -41,7 +41,6 @@
4141
42from breezy import (42from breezy import (
43 debug,43 debug,
44 errors,
45 trace,44 trace,
46 transport,45 transport,
47 ui,46 ui,
@@ -51,7 +50,10 @@
51from breezy.bzr.smart import client, protocol, request, signals, vfs50from breezy.bzr.smart import client, protocol, request, signals, vfs
52from breezy.transport import ssh51from breezy.transport import ssh
53""")52""")
54from ... import osutils53from ... import (
54 errors,
55 osutils,
56 )
5557
56# Throughout this module buffer size parameters are either limited to be at58# Throughout this module buffer size parameters are either limited to be at
57# most _MAX_READ_SIZE, or are ignored and _MAX_READ_SIZE is used instead.59# most _MAX_READ_SIZE, or are ignored and _MAX_READ_SIZE is used instead.
@@ -59,6 +61,17 @@
59# from non-sockets as well.61# from non-sockets as well.
60_MAX_READ_SIZE = osutils.MAX_SOCKET_CHUNK62_MAX_READ_SIZE = osutils.MAX_SOCKET_CHUNK
6163
64
65class HpssVfsRequestNotAllowed(errors.BzrError):
66
67 _fmt = ("VFS requests over the smart server are not allowed. Encountered: "
68 "%(method)s, %(arguments)s.")
69
70 def __init__(self, method, arguments):
71 self.method = method
72 self.arguments = arguments
73
74
62def _get_protocol_factory_for_bytes(bytes):75def _get_protocol_factory_for_bytes(bytes):
63 """Determine the right protocol factory for 'bytes'.76 """Determine the right protocol factory for 'bytes'.
6477
@@ -656,7 +669,7 @@
656 # A method we don't know about doesn't count as a VFS method.669 # A method we don't know about doesn't count as a VFS method.
657 return670 return
658 if issubclass(request_method, vfs.VfsRequest):671 if issubclass(request_method, vfs.VfsRequest):
659 raise errors.HpssVfsRequestNotAllowed(params.method, params.args)672 raise HpssVfsRequestNotAllowed(params.method, params.args)
660673
661674
662class _DebugCounter(object):675class _DebugCounter(object):
663676
=== modified file 'breezy/bzr/smart/request.py'
--- breezy/bzr/smart/request.py 2017-06-11 20:15:04 +0000
+++ breezy/bzr/smart/request.py 2017-07-23 16:06:20 +0000
@@ -58,6 +58,15 @@
58jail_info.transports = None58jail_info.transports = None
5959
6060
61class DisabledMethod(errors.InternalBzrError):
62
63 _fmt = "The smart server method '%(class_name)s' is disabled."
64
65 def __init__(self, class_name):
66 errors.BzrError.__init__(self)
67 self.class_name = class_name
68
69
61def _install_hook():70def _install_hook():
62 bzrdir.BzrDir.hooks.install_named_hook(71 bzrdir.BzrDir.hooks.install_named_hook(
63 'pre_open', _pre_open_hook, 'checking server jail')72 'pre_open', _pre_open_hook, 'checking server jail')
6473
=== modified file 'breezy/bzr/smart/vfs.py'
--- breezy/bzr/smart/vfs.py 2017-06-11 20:15:04 +0000
+++ breezy/bzr/smart/vfs.py 2017-07-23 16:06:20 +0000
@@ -60,7 +60,7 @@
6060
61 def _check_enabled(self):61 def _check_enabled(self):
62 if not vfs_enabled():62 if not vfs_enabled():
63 raise errors.DisabledMethod(self.__class__.__name__)63 raise request.DisabledMethod(self.__class__.__name__)
6464
65 def translate_client_path(self, relpath):65 def translate_client_path(self, relpath):
66 # VFS requests are made with escaped paths so the escaping done in66 # VFS requests are made with escaped paths so the escaping done in
6767
=== modified file 'breezy/commands.py'
--- breezy/commands.py 2017-07-20 00:00:04 +0000
+++ breezy/commands.py 2017-07-23 16:06:20 +0000
@@ -61,6 +61,27 @@
61 _fmt = "Error in command line options"61 _fmt = "Error in command line options"
6262
6363
64class CommandAvailableInPlugin(Exception):
65
66 internal_error = False
67
68 def __init__(self, cmd_name, plugin_metadata, provider):
69
70 self.plugin_metadata = plugin_metadata
71 self.cmd_name = cmd_name
72 self.provider = provider
73
74 def __str__(self):
75
76 _fmt = ('"%s" is not a standard brz command. \n'
77 'However, the following official plugin provides this command: %s\n'
78 'You can install it by going to: %s'
79 % (self.cmd_name, self.plugin_metadata['name'],
80 self.plugin_metadata['url']))
81
82 return _fmt
83
84
64class CommandInfo(object):85class CommandInfo(object):
65 """Information about a command."""86 """Information about a command."""
6687
@@ -325,13 +346,16 @@
325 return cmd346 return cmd
326347
327348
349class NoPluginAvailable(errors.BzrError):
350 pass
351
352
328def _try_plugin_provider(cmd_name):353def _try_plugin_provider(cmd_name):
329 """Probe for a plugin provider having cmd_name."""354 """Probe for a plugin provider having cmd_name."""
330 try:355 try:
331 plugin_metadata, provider = probe_for_provider(cmd_name)356 plugin_metadata, provider = probe_for_provider(cmd_name)
332 raise errors.CommandAvailableInPlugin(cmd_name,357 raise CommandAvailableInPlugin(cmd_name, plugin_metadata, provider)
333 plugin_metadata, provider)358 except NoPluginAvailable:
334 except errors.NoPluginAvailable:
335 pass359 pass
336360
337361
@@ -346,9 +370,9 @@
346 for provider in command_providers_registry:370 for provider in command_providers_registry:
347 try:371 try:
348 return provider.plugin_for_command(cmd_name), provider372 return provider.plugin_for_command(cmd_name), provider
349 except errors.NoPluginAvailable:373 except NoPluginAvailable:
350 pass374 pass
351 raise errors.NoPluginAvailable(cmd_name)375 raise NoPluginAvailable(cmd_name)
352376
353377
354def _get_bzr_command(cmd_or_None, cmd_name):378def _get_bzr_command(cmd_or_None, cmd_name):
355379
=== modified file 'breezy/errors.py'
--- breezy/errors.py 2017-07-21 14:18:24 +0000
+++ breezy/errors.py 2017-07-23 16:06:20 +0000
@@ -146,11 +146,6 @@
146 internal_error = True146 internal_error = True
147147
148148
149class AlreadyBuilding(BzrError):
150
151 _fmt = "The tree builder is already building a tree."
152
153
154class BranchError(BzrError):149class BranchError(BzrError):
155 """Base class for concrete 'errors about a branch'."""150 """Base class for concrete 'errors about a branch'."""
156151
@@ -177,15 +172,6 @@
177 self.msg = msg172 self.msg = msg
178173
179174
180class DisabledMethod(InternalBzrError):
181
182 _fmt = "The smart server method '%(class_name)s' is disabled."
183
184 def __init__(self, class_name):
185 BzrError.__init__(self)
186 self.class_name = class_name
187
188
189class IncompatibleVersion(BzrError):175class IncompatibleVersion(BzrError):
190176
191 _fmt = 'API %(api)s is not compatible; one of versions %(wanted)r '\177 _fmt = 'API %(api)s is not compatible; one of versions %(wanted)r '\
@@ -301,11 +287,6 @@
301 self.base = base287 self.base = base
302288
303289
304class NotBuilding(BzrError):
305
306 _fmt = "Not currently building a tree."
307
308
309class NotLocalUrl(BzrError):290class NotLocalUrl(BzrError):
310291
311 _fmt = "%(url)s is not a local path."292 _fmt = "%(url)s is not a local path."
@@ -2503,11 +2484,6 @@
2503 self.name = name.decode("utf-8")2484 self.name = name.decode("utf-8")
25042485
25052486
2506class NoDestinationAddress(InternalBzrError):
2507
2508 _fmt = "Message does not have a destination address."
2509
2510
2511class RepositoryDataStreamError(BzrError):2487class RepositoryDataStreamError(BzrError):
25122488
2513 _fmt = "Corrupt or incompatible data stream: %(reason)s"2489 _fmt = "Corrupt or incompatible data stream: %(reason)s"
@@ -2516,48 +2492,6 @@
2516 self.reason = reason2492 self.reason = reason
25172493
25182494
2519class SMTPError(BzrError):
2520
2521 _fmt = "SMTP error: %(error)s"
2522
2523 def __init__(self, error):
2524 self.error = error
2525
2526
2527class NoMessageSupplied(BzrError):
2528
2529 _fmt = "No message supplied."
2530
2531
2532class NoMailAddressSpecified(BzrError):
2533
2534 _fmt = "No mail-to address (--mail-to) or output (-o) specified."
2535
2536
2537class MailClientNotFound(BzrError):
2538
2539 _fmt = "Unable to find mail client with the following names:"\
2540 " %(mail_command_list_string)s"
2541
2542 def __init__(self, mail_command_list):
2543 mail_command_list_string = ', '.join(mail_command_list)
2544 BzrError.__init__(self, mail_command_list=mail_command_list,
2545 mail_command_list_string=mail_command_list_string)
2546
2547class SMTPConnectionRefused(SMTPError):
2548
2549 _fmt = "SMTP connection to %(host)s refused"
2550
2551 def __init__(self, error, host):
2552 self.error = error
2553 self.host = host
2554
2555
2556class DefaultSMTPConnectionRefused(SMTPConnectionRefused):
2557
2558 _fmt = "Please specify smtp_server. No server at default %(host)s."
2559
2560
2561class BzrDirError(BzrError):2495class BzrDirError(BzrError):
25622496
2563 def __init__(self, controldir):2497 def __init__(self, controldir):
@@ -2708,31 +2642,6 @@
2708 self.timezone = timezone2642 self.timezone = timezone
27092643
27102644
2711class CommandAvailableInPlugin(Exception):
2712
2713 internal_error = False
2714
2715 def __init__(self, cmd_name, plugin_metadata, provider):
2716
2717 self.plugin_metadata = plugin_metadata
2718 self.cmd_name = cmd_name
2719 self.provider = provider
2720
2721 def __str__(self):
2722
2723 _fmt = ('"%s" is not a standard brz command. \n'
2724 'However, the following official plugin provides this command: %s\n'
2725 'You can install it by going to: %s'
2726 % (self.cmd_name, self.plugin_metadata['name'],
2727 self.plugin_metadata['url']))
2728
2729 return _fmt
2730
2731
2732class NoPluginAvailable(BzrError):
2733 pass
2734
2735
2736class UnableEncodePath(BzrError):2645class UnableEncodePath(BzrError):
27372646
2738 _fmt = ('Unable to encode %(kind)s path %(path)r in '2647 _fmt = ('Unable to encode %(kind)s path %(path)r in '
@@ -2804,11 +2713,6 @@
2804 self.msg = msg2713 self.msg = msg
28052714
28062715
2807class ShelfCorrupt(BzrError):
2808
2809 _fmt = "Shelf corrupt."
2810
2811
2812class DecompressCorruption(BzrError):2716class DecompressCorruption(BzrError):
28132717
2814 _fmt = "Corruption while decompressing repository file%(orig_error)s"2718 _fmt = "Corruption while decompressing repository file%(orig_error)s"
@@ -2821,22 +2725,6 @@
2821 BzrError.__init__(self)2725 BzrError.__init__(self)
28222726
28232727
2824class NoSuchShelfId(BzrError):
2825
2826 _fmt = 'No changes are shelved with id "%(shelf_id)d".'
2827
2828 def __init__(self, shelf_id):
2829 BzrError.__init__(self, shelf_id=shelf_id)
2830
2831
2832class InvalidShelfId(BzrError):
2833
2834 _fmt = '"%(invalid_id)s" is not a valid shelf id, try a number instead.'
2835
2836 def __init__(self, invalid_id):
2837 BzrError.__init__(self, invalid_id=invalid_id)
2838
2839
2840class JailBreak(BzrError):2728class JailBreak(BzrError):
28412729
2842 _fmt = "An attempt to access a url outside the server jail was made: '%(url)s'."2730 _fmt = "An attempt to access a url outside the server jail was made: '%(url)s'."
@@ -2858,37 +2746,6 @@
2858 BzrError.__init__(self, format=format, url=url)2746 BzrError.__init__(self, format=format, url=url)
28592747
28602748
2861class NoSuchView(BzrError):
2862 """A view does not exist.
2863 """
2864
2865 _fmt = u"No such view: %(view_name)s."
2866
2867 def __init__(self, view_name):
2868 self.view_name = view_name
2869
2870
2871class ViewsNotSupported(BzrError):
2872 """Views are not supported by a tree format.
2873 """
2874
2875 _fmt = ("Views are not supported by %(tree)s;"
2876 " use 'brz upgrade' to change your tree to a later format.")
2877
2878 def __init__(self, tree):
2879 self.tree = tree
2880
2881
2882class FileOutsideView(BzrError):
2883
2884 _fmt = ('Specified file "%(file_name)s" is outside the current view: '
2885 '%(view_str)s')
2886
2887 def __init__(self, file_name, view_files):
2888 self.file_name = file_name
2889 self.view_str = ", ".join(view_files)
2890
2891
2892class UnresumableWriteGroup(BzrError):2749class UnresumableWriteGroup(BzrError):
28932750
2894 _fmt = ("Repository %(repository)s cannot resume write group "2751 _fmt = ("Repository %(repository)s cannot resume write group "
@@ -2953,16 +2810,6 @@
2953 self.branch_url = branch_url2810 self.branch_url = branch_url
29542811
29552812
2956class HpssVfsRequestNotAllowed(BzrError):
2957
2958 _fmt = ("VFS requests over the smart server are not allowed. Encountered: "
2959 "%(method)s, %(arguments)s.")
2960
2961 def __init__(self, method, arguments):
2962 self.method = method
2963 self.arguments = arguments
2964
2965
2966class UnsupportedKindChange(BzrError):2813class UnsupportedKindChange(BzrError):
29672814
2968 _fmt = ("Kind change from %(from_kind)s to %(to_kind)s for "2815 _fmt = ("Kind change from %(from_kind)s to %(to_kind)s for "
29692816
=== modified file 'breezy/mail_client.py'
--- breezy/mail_client.py 2017-06-05 20:48:31 +0000
+++ breezy/mail_client.py 2017-07-23 16:06:20 +0000
@@ -36,6 +36,28 @@
36mail_client_registry = registry.Registry()36mail_client_registry = registry.Registry()
3737
3838
39class MailClientNotFound(errors.BzrError):
40
41 _fmt = "Unable to find mail client with the following names:"\
42 " %(mail_command_list_string)s"
43
44 def __init__(self, mail_command_list):
45 mail_command_list_string = ', '.join(mail_command_list)
46 errors.BzrError.__init__(
47 self, mail_command_list=mail_command_list,
48 mail_command_list_string=mail_command_list_string)
49
50
51class NoMessageSupplied(errors.BzrError):
52
53 _fmt = "No message supplied."
54
55
56class NoMailAddressSpecified(errors.BzrError):
57
58 _fmt = "No mail-to address (--mail-to) or output (-o) specified."
59
60
39class MailClient(object):61class MailClient(object):
40 """A mail client that can send messages with attachements."""62 """A mail client that can send messages with attachements."""
4163
@@ -107,10 +129,10 @@
107 extension, basename=None, body=None):129 extension, basename=None, body=None):
108 """See MailClient.compose"""130 """See MailClient.compose"""
109 if not to:131 if not to:
110 raise errors.NoMailAddressSpecified()132 raise NoMailAddressSpecified()
111 body = msgeditor.edit_commit_message(prompt, start_message=body)133 body = msgeditor.edit_commit_message(prompt, start_message=body)
112 if body == '':134 if body == '':
113 raise errors.NoMessageSupplied()135 raise NoMessageSupplied()
114 email_message.EmailMessage.send(self.config,136 email_message.EmailMessage.send(self.config,
115 self.config.get('email'),137 self.config.get('email'),
116 to,138 to,
@@ -190,7 +212,7 @@
190 else:212 else:
191 break213 break
192 else:214 else:
193 raise errors.MailClientNotFound(self._client_commands)215 raise MailClientNotFound(self._client_commands)
194216
195 def _get_compose_commandline(self, to, subject, attach_path, body):217 def _get_compose_commandline(self, to, subject, attach_path, body):
196 """Determine the commandline to use for composing a message218 """Determine the commandline to use for composing a message
@@ -365,7 +387,7 @@
365 'body=' + urlutils.quote(self._encode_safe(body)))387 'body=' + urlutils.quote(self._encode_safe(body)))
366 # to must be supplied for the claws-mail --compose syntax to work.388 # to must be supplied for the claws-mail --compose syntax to work.
367 if to is None:389 if to is None:
368 raise errors.NoMailAddressSpecified()390 raise NoMailAddressSpecified()
369 compose_url = 'mailto:%s?%s' % (391 compose_url = 'mailto:%s?%s' % (
370 self._encode_safe(to), '&'.join(compose_url))392 self._encode_safe(to), '&'.join(compose_url))
371 # Collect command-line options.393 # Collect command-line options.
@@ -396,7 +418,7 @@
396 def _get_compose_commandline(self, to, subject, attach_path, body=None):418 def _get_compose_commandline(self, to, subject, attach_path, body=None):
397 """See ExternalMailClient._get_compose_commandline"""419 """See ExternalMailClient._get_compose_commandline"""
398 if not to:420 if not to:
399 raise errors.NoMailAddressSpecified()421 raise NoMailAddressSpecified()
400 commandline = [self._encode_safe(to)]422 commandline = [self._encode_safe(to)]
401 if subject is not None:423 if subject is not None:
402 commandline.extend(['--subject', self._encode_safe(subject)])424 commandline.extend(['--subject', self._encode_safe(subject)])
@@ -535,7 +557,7 @@
535 attach_path)557 attach_path)
536 except simplemapi.MAPIError as e:558 except simplemapi.MAPIError as e:
537 if e.code != simplemapi.MAPI_USER_ABORT:559 if e.code != simplemapi.MAPI_USER_ABORT:
538 raise errors.MailClientNotFound(['MAPI supported mail client'560 raise MailClientNotFound(['MAPI supported mail client'
539 ' (error %d)' % (e.code,)])561 ' (error %d)' % (e.code,)])
540mail_client_registry.register('mapi', MAPIClient,562mail_client_registry.register('mapi', MAPIClient,
541 help=MAPIClient.__doc__)563 help=MAPIClient.__doc__)
@@ -620,7 +642,7 @@
620 return self._mail_client().compose(prompt, to, subject,642 return self._mail_client().compose(prompt, to, subject,
621 attachment, mime_subtype,643 attachment, mime_subtype,
622 extension, basename, body)644 extension, basename, body)
623 except errors.MailClientNotFound:645 except MailClientNotFound:
624 return Editor(self.config).compose(prompt, to, subject,646 return Editor(self.config).compose(prompt, to, subject,
625 attachment, mime_subtype, extension, body)647 attachment, mime_subtype, extension, body)
626648
@@ -630,7 +652,7 @@
630 try:652 try:
631 return self._mail_client().compose_merge_request(to, subject,653 return self._mail_client().compose_merge_request(to, subject,
632 directive, basename=basename, body=body)654 directive, basename=basename, body=body)
633 except errors.MailClientNotFound:655 except MailClientNotFound:
634 return Editor(self.config).compose_merge_request(to, subject,656 return Editor(self.config).compose_merge_request(to, subject,
635 directive, basename=basename, body=body)657 directive, basename=basename, body=body)
636mail_client_registry.register('default', DefaultMail,658mail_client_registry.register('default', DefaultMail,
637659
=== modified file 'breezy/shelf.py'
--- breezy/shelf.py 2017-06-24 13:32:35 +0000
+++ breezy/shelf.py 2017-07-23 16:06:20 +0000
@@ -19,11 +19,11 @@
19import errno19import errno
20import re20import re
2121
22from . import errors
22from .lazy_import import lazy_import23from .lazy_import import lazy_import
23lazy_import(globals(), """24lazy_import(globals(), """
24from breezy import (25from breezy import (
25 bencode,26 bencode,
26 errors,
27 merge,27 merge,
28 merge3,28 merge3,
29 transform,29 transform,
@@ -34,6 +34,27 @@
34""")34""")
3535
3636
37class ShelfCorrupt(errors.BzrError):
38
39 _fmt = "Shelf corrupt."
40
41
42class NoSuchShelfId(errors.BzrError):
43
44 _fmt = 'No changes are shelved with id "%(shelf_id)d".'
45
46 def __init__(self, shelf_id):
47 errors.BzrError.__init__(self, shelf_id=shelf_id)
48
49
50class InvalidShelfId(errors.BzrError):
51
52 _fmt = '"%(invalid_id)s" is not a valid shelf id, try a number instead.'
53
54 def __init__(self, invalid_id):
55 errors.BzrError.__init__(self, invalid_id=invalid_id)
56
57
37class ShelfCreator(object):58class ShelfCreator(object):
38 """Create a transform to shelve objects and its inverse."""59 """Create a transform to shelve objects and its inverse."""
3960
@@ -318,7 +339,7 @@
318 def parse_metadata(records):339 def parse_metadata(records):
319 names, metadata_bytes = next(records)340 names, metadata_bytes = next(records)
320 if names[0] != ('metadata',):341 if names[0] != ('metadata',):
321 raise errors.ShelfCorrupt342 raise ShelfCorrupt
322 metadata = bencode.bdecode(metadata_bytes)343 metadata = bencode.bdecode(metadata_bytes)
323 message = metadata.get('message')344 message = metadata.get('message')
324 if message is not None:345 if message is not None:
@@ -409,8 +430,7 @@
409 except IOError as e:430 except IOError as e:
410 if e.errno != errno.ENOENT:431 if e.errno != errno.ENOENT:
411 raise432 raise
412 from . import errors433 raise NoSuchShelfId(shelf_id)
413 raise errors.NoSuchShelfId(shelf_id)
414434
415 def get_unshelver(self, shelf_id):435 def get_unshelver(self, shelf_id):
416 """Return an unshelver for a given shelf_id.436 """Return an unshelver for a given shelf_id.
417437
=== modified file 'breezy/shelf_ui.py'
--- breezy/shelf_ui.py 2017-06-24 13:32:35 +0000
+++ breezy/shelf_ui.py 2017-07-23 16:06:20 +0000
@@ -398,7 +398,7 @@
398 try:398 try:
399 shelf_id = int(shelf_id)399 shelf_id = int(shelf_id)
400 except ValueError:400 except ValueError:
401 raise errors.InvalidShelfId(shelf_id)401 raise shelf.InvalidShelfId(shelf_id)
402 else:402 else:
403 shelf_id = manager.last_shelf()403 shelf_id = manager.last_shelf()
404 if shelf_id is None:404 if shelf_id is None:
405405
=== modified file 'breezy/smtp_connection.py'
--- breezy/smtp_connection.py 2017-06-05 20:48:31 +0000
+++ breezy/smtp_connection.py 2017-07-23 16:06:20 +0000
@@ -28,10 +28,8 @@
28 osutils,28 osutils,
29 )29 )
30from .errors import (30from .errors import (
31 NoDestinationAddress,31 BzrError,
32 SMTPError,32 InternalBzrError,
33 DefaultSMTPConnectionRefused,
34 SMTPConnectionRefused,
35 )33 )
3634
3735
@@ -49,6 +47,35 @@
49''')47''')
5048
5149
50class SMTPError(BzrError):
51
52 _fmt = "SMTP error: %(error)s"
53
54 def __init__(self, error):
55 self.error = error
56
57
58class SMTPConnectionRefused(SMTPError):
59
60 _fmt = "SMTP connection to %(host)s refused"
61
62 def __init__(self, error, host):
63 self.error = error
64 self.host = host
65
66
67class DefaultSMTPConnectionRefused(SMTPConnectionRefused):
68
69 _fmt = "Please specify smtp_server. No server at default %(host)s."
70
71
72
73class NoDestinationAddress(InternalBzrError):
74
75 _fmt = "Message does not have a destination address."
76
77
78
52class SMTPConnection(object):79class SMTPConnection(object):
53 """Connect to an SMTP server and send an email.80 """Connect to an SMTP server and send an email.
5481
5582
=== modified file 'breezy/tests/__init__.py'
--- breezy/tests/__init__.py 2017-07-02 13:44:33 +0000
+++ breezy/tests/__init__.py 2017-07-23 16:06:20 +0000
@@ -4053,6 +4053,7 @@
4053 'breezy.tests.test_version_info',4053 'breezy.tests.test_version_info',
4054 'breezy.tests.test_versionedfile',4054 'breezy.tests.test_versionedfile',
4055 'breezy.tests.test_vf_search',4055 'breezy.tests.test_vf_search',
4056 'breezy.tests.test_views',
4056 'breezy.tests.test_weave',4057 'breezy.tests.test_weave',
4057 'breezy.tests.test_whitebox',4058 'breezy.tests.test_whitebox',
4058 'breezy.tests.test_win32utils',4059 'breezy.tests.test_win32utils',
40594060
=== modified file 'breezy/tests/per_workingtree/test_views.py'
--- breezy/tests/per_workingtree/test_views.py 2017-05-22 00:56:52 +0000
+++ breezy/tests/per_workingtree/test_views.py 2017-07-23 16:06:20 +0000
@@ -21,7 +21,7 @@
21"""21"""
2222
2323
24from breezy import views, errors24from breezy import views as _mod_views
25from breezy.tests import TestNotApplicable, TestSkipped25from breezy.tests import TestNotApplicable, TestSkipped
26from breezy.workingtree import WorkingTree26from breezy.workingtree import WorkingTree
2727
@@ -64,7 +64,7 @@
64 self.assertEqual(view_current, current)64 self.assertEqual(view_current, current)
65 self.assertEqual(view_dict, views)65 self.assertEqual(view_dict, views)
66 # test setting a current view which does not exist66 # test setting a current view which does not exist
67 self.assertRaises(errors.NoSuchView,67 self.assertRaises(_mod_views.NoSuchView,
68 wt.views.set_view_info, 'yet-another', view_dict)68 wt.views.set_view_info, 'yet-another', view_dict)
69 current, views = wt.views.get_view_info()69 current, views = wt.views.get_view_info()
70 self.assertEqual(view_current, current)70 self.assertEqual(view_current, current)
@@ -116,7 +116,7 @@
116 wt = self.make_branch_and_tree('wt')116 wt = self.make_branch_and_tree('wt')
117 try:117 try:
118 wt.views.lookup_view('opaque')118 wt.views.lookup_view('opaque')
119 except errors.NoSuchView as e:119 except _mod_views.NoSuchView as e:
120 self.assertEqual(e.view_name, 'opaque')120 self.assertEqual(e.view_name, 'opaque')
121 self.assertEqual(str(e), 'No such view: opaque.')121 self.assertEqual(str(e), 'No such view: opaque.')
122 else:122 else:
@@ -130,15 +130,15 @@
130 # now try to delete it130 # now try to delete it
131 wt.views.delete_view(view_name)131 wt.views.delete_view(view_name)
132 # now you can't look it up132 # now you can't look it up
133 self.assertRaises(errors.NoSuchView,133 self.assertRaises(_mod_views.NoSuchView,
134 wt.views.lookup_view, view_name)134 wt.views.lookup_view, view_name)
135 # and it's not in the dictionary135 # and it's not in the dictionary
136 self.assertEqual(wt.views.get_view_info()[1], {})136 self.assertEqual(wt.views.get_view_info()[1], {})
137 # and you can't remove it a second time137 # and you can't remove it a second time
138 self.assertRaises(errors.NoSuchView,138 self.assertRaises(_mod_views.NoSuchView,
139 wt.views.delete_view, view_name)139 wt.views.delete_view, view_name)
140 # or remove a view that never existed140 # or remove a view that never existed
141 self.assertRaises(errors.NoSuchView,141 self.assertRaises(_mod_views.NoSuchView,
142 wt.views.delete_view, view_name + '2')142 wt.views.delete_view, view_name + '2')
143143
144 def test_check_path_in_view(self):144 def test_check_path_in_view(self):
@@ -148,14 +148,14 @@
148 view_current: ['dir-1'],148 view_current: ['dir-1'],
149 'other-name': ['dir-2']}149 'other-name': ['dir-2']}
150 wt.views.set_view_info(view_current, view_dict)150 wt.views.set_view_info(view_current, view_dict)
151 self.assertEqual(views.check_path_in_view(wt, 'dir-1'), None)151 self.assertEqual(_mod_views.check_path_in_view(wt, 'dir-1'), None)
152 self.assertEqual(views.check_path_in_view(wt, 'dir-1/sub'), None)152 self.assertEqual(_mod_views.check_path_in_view(wt, 'dir-1/sub'), None)
153 self.assertRaises(errors.FileOutsideView,153 self.assertRaises(_mod_views.FileOutsideView,
154 views.check_path_in_view, wt, 'dir-2')154 _mod_views.check_path_in_view, wt, 'dir-2')
155 self.assertRaises(errors.FileOutsideView,155 self.assertRaises(_mod_views.FileOutsideView,
156 views.check_path_in_view, wt, 'dir-2/sub')156 _mod_views.check_path_in_view, wt, 'dir-2/sub')
157 self.assertRaises(errors.FileOutsideView,157 self.assertRaises(_mod_views.FileOutsideView,
158 views.check_path_in_view, wt, 'other')158 _mod_views.check_path_in_view, wt, 'other')
159159
160160
161class TestUnsupportedViews(TestCaseWithWorkingTree):161class TestUnsupportedViews(TestCaseWithWorkingTree):
@@ -176,13 +176,13 @@
176176
177 def test_view_methods_raise(self):177 def test_view_methods_raise(self):
178 wt = self.make_branch_and_tree('wt')178 wt = self.make_branch_and_tree('wt')
179 self.assertRaises(errors.ViewsNotSupported,179 self.assertRaises(_mod_views.ViewsNotSupported,
180 wt.views.set_view_info, 'bar', {'bar': ['bars/']})180 wt.views.set_view_info, 'bar', {'bar': ['bars/']})
181 self.assertRaises(errors.ViewsNotSupported,181 self.assertRaises(_mod_views.ViewsNotSupported,
182 wt.views.get_view_info)182 wt.views.get_view_info)
183 self.assertRaises(errors.ViewsNotSupported,183 self.assertRaises(_mod_views.ViewsNotSupported,
184 wt.views.lookup_view, 'foo')184 wt.views.lookup_view, 'foo')
185 self.assertRaises(errors.ViewsNotSupported,185 self.assertRaises(_mod_views.ViewsNotSupported,
186 wt.views.set_view, 'foo', 'bar')186 wt.views.set_view, 'foo', 'bar')
187 self.assertRaises(errors.ViewsNotSupported,187 self.assertRaises(_mod_views.ViewsNotSupported,
188 wt.views.delete_view, 'foo')188 wt.views.delete_view, 'foo')
189189
=== modified file 'breezy/tests/test_errors.py'
--- breezy/tests/test_errors.py 2017-07-21 14:18:24 +0000
+++ breezy/tests/test_errors.py 2017-07-23 16:06:20 +0000
@@ -77,11 +77,6 @@
77 " appears to be corrupt: trailing garbage: \"x\"",77 " appears to be corrupt: trailing garbage: \"x\"",
78 str(error))78 str(error))
7979
80 def test_disabled_method(self):
81 error = errors.DisabledMethod("class name")
82 self.assertEqualDiff(
83 "The smart server method 'class name' is disabled.", str(error))
84
85 def test_duplicate_file_id(self):80 def test_duplicate_file_id(self):
86 error = errors.DuplicateFileId('a_file_id', 'foo')81 error = errors.DuplicateFileId('a_file_id', 'foo')
87 self.assertEqualDiff('File id {a_file_id} already exists in inventory'82 self.assertEqualDiff('File id {a_file_id} already exists in inventory'
@@ -548,28 +543,6 @@
548 self.assertEqual(str(err), "Branching 'bar'(foo) must create a"543 self.assertEqual(str(err), "Branching 'bar'(foo) must create a"
549 " working tree.")544 " working tree.")
550545
551 def test_no_such_view(self):
552 err = errors.NoSuchView('foo')
553 self.assertEqual("No such view: foo.", str(err))
554
555 def test_views_not_supported(self):
556 err = errors.ViewsNotSupported('atree')
557 err_str = str(err)
558 self.assertStartsWith(err_str, "Views are not supported by ")
559 self.assertEndsWith(err_str, "; use 'brz upgrade' to change your "
560 "tree to a later format.")
561
562 def test_file_outside_view(self):
563 err = errors.FileOutsideView('baz', ['foo', 'bar'])
564 self.assertEqual('Specified file "baz" is outside the current view: '
565 'foo, bar', str(err))
566
567 def test_invalid_shelf_id(self):
568 invalid_id = "foo"
569 err = errors.InvalidShelfId(invalid_id)
570 self.assertEqual('"foo" is not a valid shelf id, '
571 'try a number instead.', str(err))
572
573 def test_unresumable_write_group(self):546 def test_unresumable_write_group(self):
574 repo = "dummy repo"547 repo = "dummy repo"
575 wg_tokens = ['token']548 wg_tokens = ['token']
576549
=== modified file 'breezy/tests/test_mail_client.py'
--- breezy/tests/test_mail_client.py 2017-05-22 00:56:52 +0000
+++ breezy/tests/test_mail_client.py 2017-07-23 16:06:20 +0000
@@ -118,7 +118,7 @@
118118
119 def test_commandline(self):119 def test_commandline(self):
120 xdg_email = mail_client.XDGEmail(None)120 xdg_email = mail_client.XDGEmail(None)
121 self.assertRaises(errors.NoMailAddressSpecified,121 self.assertRaises(mail_client.NoMailAddressSpecified,
122 xdg_email._get_compose_commandline,122 xdg_email._get_compose_commandline,
123 None, None, 'file%')123 None, None, 'file%')
124 commandline = xdg_email._get_compose_commandline(124 commandline = xdg_email._get_compose_commandline(
@@ -233,7 +233,7 @@
233233
234 def test_to_required(self):234 def test_to_required(self):
235 claws = mail_client.Claws(None)235 claws = mail_client.Claws(None)
236 self.assertRaises(errors.NoMailAddressSpecified,236 self.assertRaises(mail_client.NoMailAddressSpecified,
237 claws._get_compose_commandline,237 claws._get_compose_commandline,
238 None, None, 'file%')238 None, None, 'file%')
239239
240240
=== modified file 'breezy/tests/test_shelf.py'
--- breezy/tests/test_shelf.py 2017-06-08 23:30:31 +0000
+++ breezy/tests/test_shelf.py 2017-07-23 16:06:20 +0000
@@ -43,6 +43,15 @@
43 "17:_removed_contentsle11:_removed_idle14:_tree_path_idsdeeE")43 "17:_removed_contentsle11:_removed_idle14:_tree_path_idsdeeE")
4444
4545
46class TestErrors(tests.TestCase):
47
48 def test_invalid_shelf_id(self):
49 invalid_id = "foo"
50 err = shelf.InvalidShelfId(invalid_id)
51 self.assertEqual('"foo" is not a valid shelf id, '
52 'try a number instead.', str(err))
53
54
46class TestPrepareShelf(tests.TestCaseWithTransport):55class TestPrepareShelf(tests.TestCaseWithTransport):
4756
48 def prepare_shelve_rename(self):57 def prepare_shelve_rename(self):
@@ -622,7 +631,7 @@
622 'foo'))])631 'foo'))])
623 shelf_file = open('shelf', 'rb')632 shelf_file = open('shelf', 'rb')
624 self.addCleanup(shelf_file.close)633 self.addCleanup(shelf_file.close)
625 e = self.assertRaises(errors.ShelfCorrupt,634 e = self.assertRaises(shelf.ShelfCorrupt,
626 shelf.Unshelver.from_tree_and_shelf, tree,635 shelf.Unshelver.from_tree_and_shelf, tree,
627 shelf_file)636 shelf_file)
628 self.assertEqual('Shelf corrupt.', str(e))637 self.assertEqual('Shelf corrupt.', str(e))
@@ -733,7 +742,7 @@
733742
734 def test_read_non_existant(self):743 def test_read_non_existant(self):
735 manager = self.get_manager()744 manager = self.get_manager()
736 e = self.assertRaises(errors.NoSuchShelfId, manager.read_shelf, 1)745 e = self.assertRaises(shelf.NoSuchShelfId, manager.read_shelf, 1)
737 self.assertEqual('No changes are shelved with id "1".', str(e))746 self.assertEqual('No changes are shelved with id "1".', str(e))
738747
739 def test_shelve_changes(self):748 def test_shelve_changes(self):
740749
=== modified file 'breezy/tests/test_shelf_ui.py'
--- breezy/tests/test_shelf_ui.py 2017-05-22 00:56:52 +0000
+++ breezy/tests/test_shelf_ui.py 2017-07-23 16:06:20 +0000
@@ -23,6 +23,7 @@
23 errors,23 errors,
24 shelf_ui,24 shelf_ui,
25 revision,25 revision,
26 shelf,
26 tests,27 tests,
27 )28 )
28from ..sixish import (29from ..sixish import (
@@ -568,7 +569,7 @@
568 shelf_file.write('garbage')569 shelf_file.write('garbage')
569 finally:570 finally:
570 shelf_file.close()571 shelf_file.close()
571 self.assertRaises(errors.InvalidShelfId,572 self.assertRaises(shelf.InvalidShelfId,
572 shelf_ui.Unshelver.from_args, directory='tree',573 shelf_ui.Unshelver.from_args, directory='tree',
573 action='delete-only', shelf_id='foo')574 action='delete-only', shelf_id='foo')
574575
575576
=== modified file 'breezy/tests/test_smart_request.py'
--- breezy/tests/test_smart_request.py 2017-06-11 20:15:04 +0000
+++ breezy/tests/test_smart_request.py 2017-07-23 16:06:20 +0000
@@ -90,6 +90,14 @@
90 self.jail_transports_log.append(request.jail_info.transports)90 self.jail_transports_log.append(request.jail_info.transports)
9191
9292
93class ErrorTests(TestCase):
94
95 def test_disabled_method(self):
96 error = request.DisabledMethod("class name")
97 self.assertEqualDiff(
98 "The smart server method 'class name' is disabled.", str(error))
99
100
93class TestSmartRequest(TestCase):101class TestSmartRequest(TestCase):
94102
95 def test_request_class_without_do_body(self):103 def test_request_class_without_do_body(self):
96104
=== modified file 'breezy/tests/test_smart_transport.py'
--- breezy/tests/test_smart_transport.py 2017-06-11 20:15:04 +0000
+++ breezy/tests/test_smart_transport.py 2017-07-23 16:06:20 +0000
@@ -1796,7 +1796,7 @@
1796 # set environment variable after construction to make sure it's1796 # set environment variable after construction to make sure it's
1797 # examined.1797 # examined.
1798 self.overrideEnv('BRZ_NO_SMART_VFS', '')1798 self.overrideEnv('BRZ_NO_SMART_VFS', '')
1799 self.assertRaises(errors.DisabledMethod, handler.execute)1799 self.assertRaises(_mod_request.DisabledMethod, handler.execute)
18001800
1801 def test_readonly_exception_becomes_transport_not_possible(self):1801 def test_readonly_exception_becomes_transport_not_possible(self):
1802 """The response for a read-only error is ('ReadOnlyError')."""1802 """The response for a read-only error is ('ReadOnlyError')."""
18031803
=== modified file 'breezy/tests/test_smtp_connection.py'
--- breezy/tests/test_smtp_connection.py 2017-05-21 18:10:28 +0000
+++ breezy/tests/test_smtp_connection.py 2017-07-23 16:06:20 +0000
@@ -22,7 +22,6 @@
22from breezy import (22from breezy import (
23 config,23 config,
24 email_message,24 email_message,
25 errors,
26 smtp_connection,25 smtp_connection,
27 tests,26 tests,
28 ui,27 ui,
@@ -106,10 +105,11 @@
106105
107 def test_missing_server(self):106 def test_missing_server(self):
108 conn = self.get_connection('', smtp_factory=connection_refuser)107 conn = self.get_connection('', smtp_factory=connection_refuser)
109 self.assertRaises(errors.DefaultSMTPConnectionRefused, conn._connect)108 self.assertRaises(smtp_connection.DefaultSMTPConnectionRefused,
109 conn._connect)
110 conn = self.get_connection('smtp_server=smtp.example.com',110 conn = self.get_connection('smtp_server=smtp.example.com',
111 smtp_factory=connection_refuser)111 smtp_factory=connection_refuser)
112 self.assertRaises(errors.SMTPConnectionRefused, conn._connect)112 self.assertRaises(smtp_connection.SMTPConnectionRefused, conn._connect)
113113
114 def test_smtp_username(self):114 def test_smtp_username(self):
115 conn = self.get_connection('')115 conn = self.get_connection('')
@@ -195,7 +195,7 @@
195 # Check that we raise an exception if both EHLO and HELO fail.195 # Check that we raise an exception if both EHLO and HELO fail.
196 factory = StubSMTPFactory(fail_on=['ehlo', 'helo'])196 factory = StubSMTPFactory(fail_on=['ehlo', 'helo'])
197 conn = self.get_connection('', smtp_factory=factory)197 conn = self.get_connection('', smtp_factory=factory)
198 self.assertRaises(errors.SMTPError, conn._create_connection)198 self.assertRaises(smtp_connection.SMTPError, conn._create_connection)
199 self.assertEqual([('connect', 'localhost'),199 self.assertEqual([('connect', 'localhost'),
200 ('ehlo',),200 ('ehlo',),
201 ('helo',)], factory._calls)201 ('helo',)], factory._calls)
@@ -218,7 +218,7 @@
218 factory = StubSMTPFactory(fail_on=['starttls'],218 factory = StubSMTPFactory(fail_on=['starttls'],
219 smtp_features=['starttls'])219 smtp_features=['starttls'])
220 conn = self.get_connection('', smtp_factory=factory)220 conn = self.get_connection('', smtp_factory=factory)
221 self.assertRaises(errors.SMTPError, conn._create_connection)221 self.assertRaises(smtp_connection.SMTPError, conn._create_connection)
222 self.assertEqual([('connect', 'localhost'),222 self.assertEqual([('connect', 'localhost'),
223 ('ehlo',),223 ('ehlo',),
224 ('has_extn', 'starttls'),224 ('has_extn', 'starttls'),
@@ -257,18 +257,18 @@
257 msg = Message()257 msg = Message()
258 msg['From'] = '"J. Random Developer" <jrandom@example.com>'258 msg['From'] = '"J. Random Developer" <jrandom@example.com>'
259 self.assertRaises(259 self.assertRaises(
260 errors.NoDestinationAddress,260 smtp_connection.NoDestinationAddress,
261 smtp_connection.SMTPConnection(config.MemoryStack("")261 smtp_connection.SMTPConnection(config.MemoryStack("")
262 ).send_email, msg)262 ).send_email, msg)
263263
264 msg = email_message.EmailMessage('from@from.com', '', 'subject')264 msg = email_message.EmailMessage('from@from.com', '', 'subject')
265 self.assertRaises(265 self.assertRaises(
266 errors.NoDestinationAddress,266 smtp_connection.NoDestinationAddress,
267 smtp_connection.SMTPConnection(config.MemoryStack("")267 smtp_connection.SMTPConnection(config.MemoryStack("")
268 ).send_email, msg)268 ).send_email, msg)
269269
270 msg = email_message.EmailMessage('from@from.com', [], 'subject')270 msg = email_message.EmailMessage('from@from.com', [], 'subject')
271 self.assertRaises(271 self.assertRaises(
272 errors.NoDestinationAddress,272 smtp_connection.NoDestinationAddress,
273 smtp_connection.SMTPConnection(config.MemoryStack("")273 smtp_connection.SMTPConnection(config.MemoryStack("")
274 ).send_email, msg)274 ).send_email, msg)
275275
=== modified file 'breezy/tests/test_treebuilder.py'
--- breezy/tests/test_treebuilder.py 2017-05-21 18:10:28 +0000
+++ breezy/tests/test_treebuilder.py 2017-07-23 16:06:20 +0000
@@ -20,7 +20,11 @@
20from breezy import errors, tests20from breezy import errors, tests
21from breezy.memorytree import MemoryTree21from breezy.memorytree import MemoryTree
22from breezy.tests import TestCaseWithTransport22from breezy.tests import TestCaseWithTransport
23from breezy.treebuilder import TreeBuilder23from breezy.treebuilder import (
24 AlreadyBuilding,
25 NotBuilding,
26 TreeBuilder,
27 )
2428
2529
26class FakeTree(object):30class FakeTree(object):
@@ -63,11 +67,11 @@
63 builder = TreeBuilder()67 builder = TreeBuilder()
64 tree = FakeTree()68 tree = FakeTree()
65 builder.start_tree(tree)69 builder.start_tree(tree)
66 self.assertRaises(errors.AlreadyBuilding, builder.start_tree, tree)70 self.assertRaises(AlreadyBuilding, builder.start_tree, tree)
6771
68 def test_finish_tree_not_started_errors(self):72 def test_finish_tree_not_started_errors(self):
69 builder = TreeBuilder()73 builder = TreeBuilder()
70 self.assertRaises(errors.NotBuilding, builder.finish_tree)74 self.assertRaises(NotBuilding, builder.finish_tree)
7175
72 def test_finish_tree_unlocks(self):76 def test_finish_tree_unlocks(self):
73 builder = TreeBuilder()77 builder = TreeBuilder()
@@ -78,7 +82,7 @@
7882
79 def test_build_tree_not_started_errors(self):83 def test_build_tree_not_started_errors(self):
80 builder = TreeBuilder()84 builder = TreeBuilder()
81 self.assertRaises(errors.NotBuilding, builder.build, "foo")85 self.assertRaises(NotBuilding, builder.build, "foo")
8286
83 def test_build_tree(self):87 def test_build_tree(self):
84 """Test building works using a MemoryTree."""88 """Test building works using a MemoryTree."""
8589
=== added file 'breezy/tests/test_views.py'
--- breezy/tests/test_views.py 1970-01-01 00:00:00 +0000
+++ breezy/tests/test_views.py 2017-07-23 16:06:20 +0000
@@ -0,0 +1,44 @@
1# Copyright (C) 2005-2011 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
17from __future__ import absolute_import
18
19from . import TestCase
20
21from ..views import (
22 FileOutsideView,
23 NoSuchView,
24 ViewsNotSupported,
25 )
26
27
28class TestErrors(TestCase):
29
30 def test_no_such_view(self):
31 err = NoSuchView('foo')
32 self.assertEqual("No such view: foo.", str(err))
33
34 def test_views_not_supported(self):
35 err = ViewsNotSupported('atree')
36 err_str = str(err)
37 self.assertStartsWith(err_str, "Views are not supported by ")
38 self.assertEndsWith(err_str, "; use 'brz upgrade' to change your "
39 "tree to a later format.")
40
41 def test_file_outside_view(self):
42 err = FileOutsideView('baz', ['foo', 'bar'])
43 self.assertEqual('Specified file "baz" is outside the current view: '
44 'foo, bar', str(err))
045
=== modified file 'breezy/treebuilder.py'
--- breezy/treebuilder.py 2017-05-22 00:56:52 +0000
+++ breezy/treebuilder.py 2017-07-23 16:06:20 +0000
@@ -25,6 +25,16 @@
25from . import errors25from . import errors
2626
2727
28class AlreadyBuilding(errors.BzrError):
29
30 _fmt = "The tree builder is already building a tree."
31
32
33class NotBuilding(errors.BzrError):
34
35 _fmt = "Not currently building a tree."
36
37
28class TreeBuilder(object):38class TreeBuilder(object):
29 """A TreeBuilder allows the creation of specific content in one tree at a39 """A TreeBuilder allows the creation of specific content in one tree at a
30 time.40 time.
@@ -59,7 +69,7 @@
59 def _ensure_building(self):69 def _ensure_building(self):
60 """Raise NotBuilding if there is no current tree being built."""70 """Raise NotBuilding if there is no current tree being built."""
61 if self._tree is None:71 if self._tree is None:
62 raise errors.NotBuilding72 raise NotBuilding
6373
64 def finish_tree(self):74 def finish_tree(self):
65 """Finish building the current tree."""75 """Finish building the current tree."""
@@ -75,6 +85,6 @@
75 MutableTree interface.85 MutableTree interface.
76 """86 """
77 if self._tree is not None:87 if self._tree is not None:
78 raise errors.AlreadyBuilding88 raise AlreadyBuilding
79 self._tree = tree89 self._tree = tree
80 self._tree.lock_tree_write()90 self._tree.lock_tree_write()
8191
=== modified file 'breezy/views.py'
--- breezy/views.py 2017-05-22 00:56:52 +0000
+++ breezy/views.py 2017-07-23 16:06:20 +0000
@@ -36,6 +36,37 @@
36_VIEWS_FORMAT1_MARKER = "Bazaar views format 1\n"36_VIEWS_FORMAT1_MARKER = "Bazaar views format 1\n"
3737
3838
39class NoSuchView(errors.BzrError):
40 """A view does not exist.
41 """
42
43 _fmt = u"No such view: %(view_name)s."
44
45 def __init__(self, view_name):
46 self.view_name = view_name
47
48
49class ViewsNotSupported(errors.BzrError):
50 """Views are not supported by a tree format.
51 """
52
53 _fmt = ("Views are not supported by %(tree)s;"
54 " use 'brz upgrade' to change your tree to a later format.")
55
56 def __init__(self, tree):
57 self.tree = tree
58
59
60class FileOutsideView(errors.BzrError):
61
62 _fmt = ('Specified file "%(file_name)s" is outside the current view: '
63 '%(view_str)s')
64
65 def __init__(self, file_name, view_files):
66 self.file_name = file_name
67 self.view_str = ", ".join(view_files)
68
69
39class _Views(object):70class _Views(object):
40 """Base class for View managers."""71 """Base class for View managers."""
4172
@@ -95,7 +126,7 @@
95 :param views: a map from view name to list of files/directories126 :param views: a map from view name to list of files/directories
96 """127 """
97 if current is not None and current not in views:128 if current is not None and current not in views:
98 raise errors.NoSuchView(current)129 raise NoSuchView(current)
99 self.tree.lock_write()130 self.tree.lock_write()
100 try:131 try:
101 self._current = current132 self._current = current
@@ -119,7 +150,7 @@
119 return []150 return []
120 return self._views[view_name]151 return self._views[view_name]
121 except KeyError:152 except KeyError:
122 raise errors.NoSuchView(view_name)153 raise NoSuchView(view_name)
123154
124 def set_view(self, view_name, view_files, make_current=True):155 def set_view(self, view_name, view_files, make_current=True):
125 """Add or update a view definition.156 """Add or update a view definition.
@@ -149,7 +180,7 @@
149 try:180 try:
150 del self._views[view_name]181 del self._views[view_name]
151 except KeyError:182 except KeyError:
152 raise errors.NoSuchView(view_name)183 raise NoSuchView(view_name)
153 if view_name == self._current:184 if view_name == self._current:
154 self._current = None185 self._current = None
155 self._save_view_info()186 self._save_view_info()
@@ -256,7 +287,7 @@
256 return False287 return False
257288
258 def _not_supported(self, *a, **k):289 def _not_supported(self, *a, **k):
259 raise errors.ViewsNotSupported(self.tree)290 raise ViewsNotSupported(self.tree)
260291
261 get_view_info = _not_supported292 get_view_info = _not_supported
262 set_view_info = _not_supported293 set_view_info = _not_supported
@@ -282,4 +313,4 @@
282 if tree.supports_views():313 if tree.supports_views():
283 view_files = tree.views.lookup_view()314 view_files = tree.views.lookup_view()
284 if view_files and not osutils.is_inside_any(view_files, relpath):315 if view_files and not osutils.is_inside_any(view_files, relpath):
285 raise errors.FileOutsideView(relpath, view_files)316 raise FileOutsideView(relpath, view_files)
286317
=== modified file 'breezy/workingtree.py'
--- breezy/workingtree.py 2017-07-02 21:26:29 +0000
+++ breezy/workingtree.py 2017-07-23 16:06:20 +0000
@@ -327,7 +327,7 @@
327 for filename in file_list:327 for filename in file_list:
328 relpath = fixer(osutils.dereference_path(filename))328 relpath = fixer(osutils.dereference_path(filename))
329 if view_files and not osutils.is_inside_any(view_files, relpath):329 if view_files and not osutils.is_inside_any(view_files, relpath):
330 raise errors.FileOutsideView(filename, view_files)330 raise views.FileOutsideView(filename, view_files)
331 new_list.append(relpath)331 new_list.append(relpath)
332 return new_list332 return new_list
333333

Subscribers

People subscribed via source and target branches