Merge lp:~jelmer/brz/move-mergeable into lp:brz
- move-mergeable
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Approved by: | Jelmer Vernooij |
Approved revision: | no longer in the source branch. |
Merge reported by: | The Breezy Bot |
Merged at revision: | not available |
Proposed branch: | lp:~jelmer/brz/move-mergeable |
Merge into: | lp:brz |
Diff against target: |
475 lines (+207/-148) 8 files modified
breezy/builtins.py (+5/-5) breezy/bundle/__init__.py (+0/-72) breezy/bundle/commands.py (+1/-1) breezy/mergeable.py (+107/-0) breezy/tests/__init__.py (+1/-0) breezy/tests/test_bundle.py (+0/-68) breezy/tests/test_mergeable.py (+91/-0) breezy/tests/test_read_bundle.py (+2/-2) |
To merge this branch: | bzr merge lp:~jelmer/brz/move-mergeable |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Packman | Approve | ||
Review via email: mp+358676@code.launchpad.net |
Commit message
Split mergeable bits out of breezy.bundle.
Description of the change
Split mergeable bits out of breezy.bundle.
To post a comment you must log in.
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Merging failed
https:/
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Merging failed
https:/
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Merging failed
https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'breezy/builtins.py' | |||
2 | --- breezy/builtins.py 2019-05-28 21:53:23 +0000 | |||
3 | +++ breezy/builtins.py 2019-05-29 03:29:58 +0000 | |||
4 | @@ -33,7 +33,6 @@ | |||
5 | 33 | from breezy import ( | 33 | from breezy import ( |
6 | 34 | branch as _mod_branch, | 34 | branch as _mod_branch, |
7 | 35 | bugtracker, | 35 | bugtracker, |
8 | 36 | bundle, | ||
9 | 37 | cache_utf8, | 36 | cache_utf8, |
10 | 38 | controldir, | 37 | controldir, |
11 | 39 | directory_service, | 38 | directory_service, |
12 | @@ -46,6 +45,7 @@ | |||
13 | 46 | lazy_regex, | 45 | lazy_regex, |
14 | 47 | log, | 46 | log, |
15 | 48 | merge as _mod_merge, | 47 | merge as _mod_merge, |
16 | 48 | mergeable as _mod_mergeable, | ||
17 | 49 | merge_directive, | 49 | merge_directive, |
18 | 50 | osutils, | 50 | osutils, |
19 | 51 | reconfigure, | 51 | reconfigure, |
20 | @@ -1210,8 +1210,8 @@ | |||
21 | 1210 | possible_transports = [] | 1210 | possible_transports = [] |
22 | 1211 | if location is not None: | 1211 | if location is not None: |
23 | 1212 | try: | 1212 | try: |
26 | 1213 | mergeable = bundle.read_mergeable_from_url(location, | 1213 | mergeable = _mod_mergeable.read_mergeable_from_url( |
27 | 1214 | possible_transports=possible_transports) | 1214 | location, possible_transports=possible_transports) |
28 | 1215 | except errors.NotABundle: | 1215 | except errors.NotABundle: |
29 | 1216 | mergeable = None | 1216 | mergeable = None |
30 | 1217 | 1217 | ||
31 | @@ -4438,8 +4438,8 @@ | |||
32 | 4438 | self.add_cleanup(tree.lock_write().unlock) | 4438 | self.add_cleanup(tree.lock_write().unlock) |
33 | 4439 | if location is not None: | 4439 | if location is not None: |
34 | 4440 | try: | 4440 | try: |
37 | 4441 | mergeable = bundle.read_mergeable_from_url(location, | 4441 | mergeable = _mod_mergeable.read_mergeable_from_url( |
38 | 4442 | possible_transports=possible_transports) | 4442 | location, possible_transports=possible_transports) |
39 | 4443 | except errors.NotABundle: | 4443 | except errors.NotABundle: |
40 | 4444 | mergeable = None | 4444 | mergeable = None |
41 | 4445 | else: | 4445 | else: |
42 | 4446 | 4446 | ||
43 | === modified file 'breezy/bundle/__init__.py' | |||
44 | --- breezy/bundle/__init__.py 2018-11-11 04:08:32 +0000 | |||
45 | +++ breezy/bundle/__init__.py 2019-05-29 03:29:58 +0000 | |||
46 | @@ -15,75 +15,3 @@ | |||
47 | 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
48 | 16 | 16 | ||
49 | 17 | from __future__ import absolute_import | 17 | from __future__ import absolute_import |
50 | 18 | |||
51 | 19 | |||
52 | 20 | from ..lazy_import import lazy_import | ||
53 | 21 | lazy_import(globals(), """ | ||
54 | 22 | from breezy import ( | ||
55 | 23 | errors, | ||
56 | 24 | transport as _mod_transport, | ||
57 | 25 | urlutils, | ||
58 | 26 | ) | ||
59 | 27 | from breezy.bundle import serializer as _serializer | ||
60 | 28 | from breezy.merge_directive import MergeDirective | ||
61 | 29 | from breezy.i18n import gettext | ||
62 | 30 | """) | ||
63 | 31 | from ..sixish import ( | ||
64 | 32 | BytesIO, | ||
65 | 33 | ) | ||
66 | 34 | from ..trace import note | ||
67 | 35 | |||
68 | 36 | |||
69 | 37 | def read_mergeable_from_url(url, _do_directive=True, possible_transports=None): | ||
70 | 38 | """Read mergable object from a given URL. | ||
71 | 39 | |||
72 | 40 | :return: An object supporting get_target_revision. Raises NotABundle if | ||
73 | 41 | the target is not a mergeable type. | ||
74 | 42 | """ | ||
75 | 43 | child_transport = _mod_transport.get_transport(url, | ||
76 | 44 | possible_transports=possible_transports) | ||
77 | 45 | transport = child_transport.clone('..') | ||
78 | 46 | filename = transport.relpath(child_transport.base) | ||
79 | 47 | mergeable, transport = read_mergeable_from_transport(transport, filename, | ||
80 | 48 | _do_directive) | ||
81 | 49 | return mergeable | ||
82 | 50 | |||
83 | 51 | |||
84 | 52 | def read_mergeable_from_transport(transport, filename, _do_directive=True): | ||
85 | 53 | def get_bundle(transport): | ||
86 | 54 | return BytesIO(transport.get_bytes(filename)), transport | ||
87 | 55 | |||
88 | 56 | def redirected_transport(transport, exception, redirection_notice): | ||
89 | 57 | note(redirection_notice) | ||
90 | 58 | url, filename = urlutils.split(exception.target, | ||
91 | 59 | exclude_trailing_slash=False) | ||
92 | 60 | if not filename: | ||
93 | 61 | raise errors.NotABundle(gettext('A directory cannot be a bundle')) | ||
94 | 62 | return _mod_transport.get_transport_from_url(url) | ||
95 | 63 | |||
96 | 64 | try: | ||
97 | 65 | bytef, transport = _mod_transport.do_catching_redirections( | ||
98 | 66 | get_bundle, transport, redirected_transport) | ||
99 | 67 | except errors.TooManyRedirections: | ||
100 | 68 | raise errors.NotABundle(transport.clone(filename).base) | ||
101 | 69 | except (errors.ConnectionReset, errors.ConnectionError) as e: | ||
102 | 70 | raise | ||
103 | 71 | except (errors.TransportError, errors.PathError) as e: | ||
104 | 72 | raise errors.NotABundle(str(e)) | ||
105 | 73 | except (IOError,) as e: | ||
106 | 74 | # jam 20060707 | ||
107 | 75 | # Abstraction leakage, SFTPTransport.get('directory') | ||
108 | 76 | # doesn't always fail at get() time. Sometimes it fails | ||
109 | 77 | # during read. And that raises a generic IOError with | ||
110 | 78 | # just the string 'Failure' | ||
111 | 79 | # StubSFTPServer does fail during get() (because of prefetch) | ||
112 | 80 | # so it has an opportunity to translate the error. | ||
113 | 81 | raise errors.NotABundle(str(e)) | ||
114 | 82 | |||
115 | 83 | if _do_directive: | ||
116 | 84 | try: | ||
117 | 85 | return MergeDirective.from_lines(bytef), transport | ||
118 | 86 | except errors.NotAMergeDirective: | ||
119 | 87 | bytef.seek(0) | ||
120 | 88 | |||
121 | 89 | return _serializer.read_bundle(bytef), transport | ||
122 | 90 | 18 | ||
123 | === modified file 'breezy/bundle/commands.py' | |||
124 | --- breezy/bundle/commands.py 2018-11-11 04:08:32 +0000 | |||
125 | +++ breezy/bundle/commands.py 2019-05-29 03:29:58 +0000 | |||
126 | @@ -53,7 +53,7 @@ | |||
127 | 53 | 53 | ||
128 | 54 | def run(self, location, verbose=False): | 54 | def run(self, location, verbose=False): |
129 | 55 | from breezy.bundle.serializer import read_bundle | 55 | from breezy.bundle.serializer import read_bundle |
131 | 56 | from breezy.bundle import read_mergeable_from_url | 56 | from breezy.mergeable import read_mergeable_from_url |
132 | 57 | from breezy import osutils | 57 | from breezy import osutils |
133 | 58 | term_encoding = osutils.get_terminal_encoding() | 58 | term_encoding = osutils.get_terminal_encoding() |
134 | 59 | bundle_info = read_mergeable_from_url(location) | 59 | bundle_info = read_mergeable_from_url(location) |
135 | 60 | 60 | ||
136 | === added file 'breezy/mergeable.py' | |||
137 | --- breezy/mergeable.py 1970-01-01 00:00:00 +0000 | |||
138 | +++ breezy/mergeable.py 2019-05-29 03:29:58 +0000 | |||
139 | @@ -0,0 +1,107 @@ | |||
140 | 1 | # Copyright (C) 2005-2010 Canonical Ltd | ||
141 | 2 | # | ||
142 | 3 | # This program is free software; you can redistribute it and/or modify | ||
143 | 4 | # it under the terms of the GNU General Public License as published by | ||
144 | 5 | # the Free Software Foundation; either version 2 of the License, or | ||
145 | 6 | # (at your option) any later version. | ||
146 | 7 | # | ||
147 | 8 | # This program is distributed in the hope that it will be useful, | ||
148 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
149 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
150 | 11 | # GNU General Public License for more details. | ||
151 | 12 | # | ||
152 | 13 | # You should have received a copy of the GNU General Public License | ||
153 | 14 | # along with this program; if not, write to the Free Software | ||
154 | 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
155 | 16 | |||
156 | 17 | from __future__ import absolute_import | ||
157 | 18 | |||
158 | 19 | from .lazy_import import lazy_import | ||
159 | 20 | lazy_import(globals(), """ | ||
160 | 21 | from breezy import ( | ||
161 | 22 | errors, | ||
162 | 23 | transport as _mod_transport, | ||
163 | 24 | urlutils, | ||
164 | 25 | ) | ||
165 | 26 | from breezy.bundle import serializer as _serializer | ||
166 | 27 | from breezy.merge_directive import MergeDirective | ||
167 | 28 | from breezy.i18n import gettext | ||
168 | 29 | """) | ||
169 | 30 | |||
170 | 31 | from .sixish import ( | ||
171 | 32 | BytesIO, | ||
172 | 33 | ) | ||
173 | 34 | from .trace import note | ||
174 | 35 | |||
175 | 36 | |||
176 | 37 | class Mergeable(object): | ||
177 | 38 | """A mergeable object.""" | ||
178 | 39 | |||
179 | 40 | def install_revisions(self, repository): | ||
180 | 41 | """Install the data from this mergeable into the specified repository. | ||
181 | 42 | |||
182 | 43 | :param repository: Repository | ||
183 | 44 | """ | ||
184 | 45 | raise NotImplementedError(self.install_revisions) | ||
185 | 46 | |||
186 | 47 | def get_merge_request(self, repository): | ||
187 | 48 | """Extract merge request data. | ||
188 | 49 | |||
189 | 50 | :return: tuple with (base_revision_id, target_revision_id, verified) | ||
190 | 51 | """ | ||
191 | 52 | raise NotImplementedError(self.get_merge_request) | ||
192 | 53 | |||
193 | 54 | |||
194 | 55 | def read_mergeable_from_url(url, _do_directive=True, possible_transports=None): | ||
195 | 56 | """Read mergable object from a given URL. | ||
196 | 57 | |||
197 | 58 | :return: An object supporting get_target_revision. Raises NotABundle if | ||
198 | 59 | the target is not a mergeable type. | ||
199 | 60 | """ | ||
200 | 61 | child_transport = _mod_transport.get_transport( | ||
201 | 62 | url, possible_transports=possible_transports) | ||
202 | 63 | transport = child_transport.clone('..') | ||
203 | 64 | filename = transport.relpath(child_transport.base) | ||
204 | 65 | mergeable, transport = read_mergeable_from_transport(transport, filename, | ||
205 | 66 | _do_directive) | ||
206 | 67 | return mergeable | ||
207 | 68 | |||
208 | 69 | |||
209 | 70 | def read_mergeable_from_transport(transport, filename, _do_directive=True): | ||
210 | 71 | def get_bundle(transport): | ||
211 | 72 | return BytesIO(transport.get_bytes(filename)), transport | ||
212 | 73 | |||
213 | 74 | def redirected_transport(transport, exception, redirection_notice): | ||
214 | 75 | note(redirection_notice) | ||
215 | 76 | url, filename = urlutils.split(exception.target, | ||
216 | 77 | exclude_trailing_slash=False) | ||
217 | 78 | if not filename: | ||
218 | 79 | raise errors.NotABundle(gettext('A directory cannot be a bundle')) | ||
219 | 80 | return _mod_transport.get_transport_from_url(url) | ||
220 | 81 | |||
221 | 82 | try: | ||
222 | 83 | bytef, transport = _mod_transport.do_catching_redirections( | ||
223 | 84 | get_bundle, transport, redirected_transport) | ||
224 | 85 | except errors.TooManyRedirections: | ||
225 | 86 | raise errors.NotABundle(transport.clone(filename).base) | ||
226 | 87 | except (errors.ConnectionReset, errors.ConnectionError) as e: | ||
227 | 88 | raise | ||
228 | 89 | except (errors.TransportError, errors.PathError) as e: | ||
229 | 90 | raise errors.NotABundle(str(e)) | ||
230 | 91 | except (IOError,) as e: | ||
231 | 92 | # jam 20060707 | ||
232 | 93 | # Abstraction leakage, SFTPTransport.get('directory') | ||
233 | 94 | # doesn't always fail at get() time. Sometimes it fails | ||
234 | 95 | # during read. And that raises a generic IOError with | ||
235 | 96 | # just the string 'Failure' | ||
236 | 97 | # StubSFTPServer does fail during get() (because of prefetch) | ||
237 | 98 | # so it has an opportunity to translate the error. | ||
238 | 99 | raise errors.NotABundle(str(e)) | ||
239 | 100 | |||
240 | 101 | if _do_directive: | ||
241 | 102 | try: | ||
242 | 103 | return MergeDirective.from_lines(bytef), transport | ||
243 | 104 | except errors.NotAMergeDirective: | ||
244 | 105 | bytef.seek(0) | ||
245 | 106 | |||
246 | 107 | return _serializer.read_bundle(bytef), transport | ||
247 | 0 | 108 | ||
248 | === modified file 'breezy/tests/__init__.py' | |||
249 | --- breezy/tests/__init__.py 2019-03-12 05:18:19 +0000 | |||
250 | +++ breezy/tests/__init__.py 2019-05-29 03:29:58 +0000 | |||
251 | @@ -4141,6 +4141,7 @@ | |||
252 | 4141 | 'breezy.tests.test_memorytree', | 4141 | 'breezy.tests.test_memorytree', |
253 | 4142 | 'breezy.tests.test_merge', | 4142 | 'breezy.tests.test_merge', |
254 | 4143 | 'breezy.tests.test_merge3', | 4143 | 'breezy.tests.test_merge3', |
255 | 4144 | 'breezy.tests.test_mergeable', | ||
256 | 4144 | 'breezy.tests.test_merge_core', | 4145 | 'breezy.tests.test_merge_core', |
257 | 4145 | 'breezy.tests.test_merge_directive', | 4146 | 'breezy.tests.test_merge_directive', |
258 | 4146 | 'breezy.tests.test_mergetools', | 4147 | 'breezy.tests.test_mergetools', |
259 | 4147 | 4148 | ||
260 | === modified file 'breezy/tests/test_bundle.py' | |||
261 | --- breezy/tests/test_bundle.py 2019-02-09 02:59:15 +0000 | |||
262 | +++ breezy/tests/test_bundle.py 2019-05-29 03:29:58 +0000 | |||
263 | @@ -17,10 +17,6 @@ | |||
264 | 17 | import bz2 | 17 | import bz2 |
265 | 18 | from io import BytesIO | 18 | from io import BytesIO |
266 | 19 | import os | 19 | import os |
267 | 20 | try: | ||
268 | 21 | import socketserver | ||
269 | 22 | except ImportError: | ||
270 | 23 | import SocketServer as socketserver | ||
271 | 24 | import sys | 20 | import sys |
272 | 25 | 21 | ||
273 | 26 | from .. import ( | 22 | from .. import ( |
274 | @@ -36,10 +32,8 @@ | |||
275 | 36 | bzrdir, | 32 | bzrdir, |
276 | 37 | inventory, | 33 | inventory, |
277 | 38 | ) | 34 | ) |
278 | 39 | from ..bundle import read_mergeable_from_url | ||
279 | 40 | from ..bundle.apply_bundle import install_bundle, merge_bundle | 35 | from ..bundle.apply_bundle import install_bundle, merge_bundle |
280 | 41 | from ..bundle.bundle_data import BundleTree | 36 | from ..bundle.bundle_data import BundleTree |
281 | 42 | from ..directory_service import directories | ||
282 | 43 | from ..bundle.serializer import write_bundle, read_bundle, v09, v4 | 37 | from ..bundle.serializer import write_bundle, read_bundle, v09, v4 |
283 | 44 | from ..bundle.serializer.v08 import BundleSerializerV08 | 38 | from ..bundle.serializer.v08 import BundleSerializerV08 |
284 | 45 | from ..bundle.serializer.v09 import BundleSerializerV09 | 39 | from ..bundle.serializer.v09 import BundleSerializerV09 |
285 | @@ -48,8 +42,6 @@ | |||
286 | 48 | from . import ( | 42 | from . import ( |
287 | 49 | features, | 43 | features, |
288 | 50 | test_commit, | 44 | test_commit, |
289 | 51 | test_read_bundle, | ||
290 | 52 | test_server, | ||
291 | 53 | ) | 45 | ) |
292 | 54 | from ..transform import TreeTransform | 46 | from ..transform import TreeTransform |
293 | 55 | 47 | ||
294 | @@ -1836,63 +1828,3 @@ | |||
295 | 1836 | self.assertEqual((None, {b'foo': b'bar', b'storage_kind': b'header'}, | 1828 | self.assertEqual((None, {b'foo': b'bar', b'storage_kind': b'header'}, |
296 | 1837 | 'info', None, None), record) | 1829 | 'info', None, None), record) |
297 | 1838 | self.assertRaises(errors.BadBundle, next, record_iter) | 1830 | self.assertRaises(errors.BadBundle, next, record_iter) |
298 | 1839 | |||
299 | 1840 | |||
300 | 1841 | class TestReadMergeableFromUrl(tests.TestCaseWithTransport): | ||
301 | 1842 | |||
302 | 1843 | def test_read_mergeable_skips_local(self): | ||
303 | 1844 | """A local bundle named like the URL should not be read. | ||
304 | 1845 | """ | ||
305 | 1846 | out, wt = test_read_bundle.create_bundle_file(self) | ||
306 | 1847 | |||
307 | 1848 | class FooService(object): | ||
308 | 1849 | """A directory service that always returns source""" | ||
309 | 1850 | |||
310 | 1851 | def look_up(self, name, url, purpose=None): | ||
311 | 1852 | return 'source' | ||
312 | 1853 | directories.register('foo:', FooService, 'Testing directory service') | ||
313 | 1854 | self.addCleanup(directories.remove, 'foo:') | ||
314 | 1855 | self.build_tree_contents([('./foo:bar', out.getvalue())]) | ||
315 | 1856 | self.assertRaises(errors.NotABundle, read_mergeable_from_url, | ||
316 | 1857 | 'foo:bar') | ||
317 | 1858 | |||
318 | 1859 | def test_infinite_redirects_are_not_a_bundle(self): | ||
319 | 1860 | """If a URL causes TooManyRedirections then NotABundle is raised. | ||
320 | 1861 | """ | ||
321 | 1862 | from .blackbox.test_push import RedirectingMemoryServer | ||
322 | 1863 | server = RedirectingMemoryServer() | ||
323 | 1864 | self.start_server(server) | ||
324 | 1865 | url = server.get_url() + 'infinite-loop' | ||
325 | 1866 | self.assertRaises(errors.NotABundle, read_mergeable_from_url, url) | ||
326 | 1867 | |||
327 | 1868 | def test_smart_server_connection_reset(self): | ||
328 | 1869 | """If a smart server connection fails during the attempt to read a | ||
329 | 1870 | bundle, then the ConnectionReset error should be propagated. | ||
330 | 1871 | """ | ||
331 | 1872 | # Instantiate a server that will provoke a ConnectionReset | ||
332 | 1873 | sock_server = DisconnectingServer() | ||
333 | 1874 | self.start_server(sock_server) | ||
334 | 1875 | # We don't really care what the url is since the server will close the | ||
335 | 1876 | # connection without interpreting it | ||
336 | 1877 | url = sock_server.get_url() | ||
337 | 1878 | self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url) | ||
338 | 1879 | |||
339 | 1880 | |||
340 | 1881 | class DisconnectingHandler(socketserver.BaseRequestHandler): | ||
341 | 1882 | """A request handler that immediately closes any connection made to it.""" | ||
342 | 1883 | |||
343 | 1884 | def handle(self): | ||
344 | 1885 | self.request.close() | ||
345 | 1886 | |||
346 | 1887 | |||
347 | 1888 | class DisconnectingServer(test_server.TestingTCPServerInAThread): | ||
348 | 1889 | |||
349 | 1890 | def __init__(self): | ||
350 | 1891 | super(DisconnectingServer, self).__init__( | ||
351 | 1892 | ('127.0.0.1', 0), | ||
352 | 1893 | test_server.TestingTCPServer, | ||
353 | 1894 | DisconnectingHandler) | ||
354 | 1895 | |||
355 | 1896 | def get_url(self): | ||
356 | 1897 | """Return the url of the server""" | ||
357 | 1898 | return "bzr://%s:%d/" % self.server.server_address | ||
358 | 1899 | 1831 | ||
359 | === added file 'breezy/tests/test_mergeable.py' | |||
360 | --- breezy/tests/test_mergeable.py 1970-01-01 00:00:00 +0000 | |||
361 | +++ breezy/tests/test_mergeable.py 2019-05-29 03:29:58 +0000 | |||
362 | @@ -0,0 +1,91 @@ | |||
363 | 1 | # Copyright (C) 2005-2013, 2016 Canonical Ltd | ||
364 | 2 | # | ||
365 | 3 | # This program is free software; you can redistribute it and/or modify | ||
366 | 4 | # it under the terms of the GNU General Public License as published by | ||
367 | 5 | # the Free Software Foundation; either version 2 of the License, or | ||
368 | 6 | # (at your option) any later version. | ||
369 | 7 | # | ||
370 | 8 | # This program is distributed in the hope that it will be useful, | ||
371 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
372 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
373 | 11 | # GNU General Public License for more details. | ||
374 | 12 | # | ||
375 | 13 | # You should have received a copy of the GNU General Public License | ||
376 | 14 | # along with this program; if not, write to the Free Software | ||
377 | 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
378 | 16 | |||
379 | 17 | try: | ||
380 | 18 | import socketserver | ||
381 | 19 | except ImportError: | ||
382 | 20 | import SocketServer as socketserver | ||
383 | 21 | |||
384 | 22 | from ..mergeable import read_mergeable_from_url | ||
385 | 23 | from ..directory_service import directories | ||
386 | 24 | from .. import ( | ||
387 | 25 | errors, | ||
388 | 26 | tests, | ||
389 | 27 | ) | ||
390 | 28 | from . import ( | ||
391 | 29 | test_read_bundle, | ||
392 | 30 | test_server, | ||
393 | 31 | ) | ||
394 | 32 | |||
395 | 33 | |||
396 | 34 | class TestReadMergeableFromUrl(tests.TestCaseWithTransport): | ||
397 | 35 | |||
398 | 36 | def test_read_mergeable_skips_local(self): | ||
399 | 37 | """A local bundle named like the URL should not be read. | ||
400 | 38 | """ | ||
401 | 39 | out, wt = test_read_bundle.create_bundle_file(self) | ||
402 | 40 | |||
403 | 41 | class FooService(object): | ||
404 | 42 | """A directory service that always returns source""" | ||
405 | 43 | |||
406 | 44 | def look_up(self, name, url): | ||
407 | 45 | return 'source' | ||
408 | 46 | directories.register('foo:', FooService, 'Testing directory service') | ||
409 | 47 | self.addCleanup(directories.remove, 'foo:') | ||
410 | 48 | self.build_tree_contents([('./foo:bar', out.getvalue())]) | ||
411 | 49 | self.assertRaises(errors.NotABundle, read_mergeable_from_url, | ||
412 | 50 | 'foo:bar') | ||
413 | 51 | |||
414 | 52 | def test_infinite_redirects_are_not_a_bundle(self): | ||
415 | 53 | """If a URL causes TooManyRedirections then NotABundle is raised. | ||
416 | 54 | """ | ||
417 | 55 | from .blackbox.test_push import RedirectingMemoryServer | ||
418 | 56 | server = RedirectingMemoryServer() | ||
419 | 57 | self.start_server(server) | ||
420 | 58 | url = server.get_url() + 'infinite-loop' | ||
421 | 59 | self.assertRaises(errors.NotABundle, read_mergeable_from_url, url) | ||
422 | 60 | |||
423 | 61 | def test_smart_server_connection_reset(self): | ||
424 | 62 | """If a smart server connection fails during the attempt to read a | ||
425 | 63 | bundle, then the ConnectionReset error should be propagated. | ||
426 | 64 | """ | ||
427 | 65 | # Instantiate a server that will provoke a ConnectionReset | ||
428 | 66 | sock_server = DisconnectingServer() | ||
429 | 67 | self.start_server(sock_server) | ||
430 | 68 | # We don't really care what the url is since the server will close the | ||
431 | 69 | # connection without interpreting it | ||
432 | 70 | url = sock_server.get_url() | ||
433 | 71 | self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url) | ||
434 | 72 | |||
435 | 73 | |||
436 | 74 | class DisconnectingHandler(socketserver.BaseRequestHandler): | ||
437 | 75 | """A request handler that immediately closes any connection made to it.""" | ||
438 | 76 | |||
439 | 77 | def handle(self): | ||
440 | 78 | self.request.close() | ||
441 | 79 | |||
442 | 80 | |||
443 | 81 | class DisconnectingServer(test_server.TestingTCPServerInAThread): | ||
444 | 82 | |||
445 | 83 | def __init__(self): | ||
446 | 84 | super(DisconnectingServer, self).__init__( | ||
447 | 85 | ('127.0.0.1', 0), | ||
448 | 86 | test_server.TestingTCPServer, | ||
449 | 87 | DisconnectingHandler) | ||
450 | 88 | |||
451 | 89 | def get_url(self): | ||
452 | 90 | """Return the url of the server""" | ||
453 | 91 | return "bzr://%s:%d/" % self.server.server_address | ||
454 | 0 | 92 | ||
455 | === modified file 'breezy/tests/test_read_bundle.py' | |||
456 | --- breezy/tests/test_read_bundle.py 2018-11-12 01:41:38 +0000 | |||
457 | +++ breezy/tests/test_read_bundle.py 2019-05-29 03:29:58 +0000 | |||
458 | @@ -16,7 +16,7 @@ | |||
459 | 16 | 16 | ||
460 | 17 | """Test read_bundle works properly across various transports.""" | 17 | """Test read_bundle works properly across various transports.""" |
461 | 18 | 18 | ||
463 | 19 | import breezy.bundle | 19 | import breezy.mergeable |
464 | 20 | from ..bundle.serializer import write_bundle | 20 | from ..bundle.serializer import write_bundle |
465 | 21 | import breezy.bzr.bzrdir | 21 | import breezy.bzr.bzrdir |
466 | 22 | from .. import errors | 22 | from .. import errors |
467 | @@ -71,7 +71,7 @@ | |||
468 | 71 | self.create_test_bundle() | 71 | self.create_test_bundle() |
469 | 72 | 72 | ||
470 | 73 | def read_mergeable_from_url(self, url): | 73 | def read_mergeable_from_url(self, url): |
472 | 74 | return breezy.bundle.read_mergeable_from_url( | 74 | return breezy.mergeable.read_mergeable_from_url( |
473 | 75 | url, possible_transports=self.possible_transports) | 75 | url, possible_transports=self.possible_transports) |
474 | 76 | 76 | ||
475 | 77 | def get_url(self, relpath=''): | 77 | def get_url(self, relpath=''): |
Thanks!