Merge lp:~cjwatson/launchpad/use-bzr-policy-open into lp:launchpad
- use-bzr-policy-open
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 19008 |
Proposed branch: | lp:~cjwatson/launchpad/use-bzr-policy-open |
Merge into: | lp:launchpad |
Diff against target: |
1498 lines (+107/-835) 17 files modified
constraints.txt (+2/-1) lib/launchpad_loggerhead/app.py (+2/-2) lib/lp/code/interfaces/branch.py (+1/-1) lib/lp/code/model/branch.py (+3/-3) lib/lp/code/model/tests/test_branch.py (+3/-3) lib/lp/codehosting/codeimport/tests/test_worker.py (+20/-20) lib/lp/codehosting/codeimport/worker.py (+13/-13) lib/lp/codehosting/puller/tests/__init__.py (+1/-1) lib/lp/codehosting/puller/tests/test_errors.py (+4/-4) lib/lp/codehosting/puller/tests/test_worker.py (+24/-24) lib/lp/codehosting/puller/tests/test_worker_formats.py (+2/-2) lib/lp/codehosting/puller/worker.py (+22/-22) lib/lp/codehosting/safe_open.py (+0/-354) lib/lp/codehosting/scanner/tests/test_bzrsync.py (+2/-2) lib/lp/codehosting/tests/test_safe_open.py (+0/-378) lib/lp/codehosting/upgrade.py (+7/-4) scripts/code-import-worker.py (+1/-1) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/use-bzr-policy-open |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+368761@code.launchpad.net |
Commit message
Use new bzrlib.
Description of the change
Launchpad's safe_open API was fairly generic and has been moved into bzrlib as bzrlib.
This branch changes Launchpad to use the copy of safe_open that is present in bzrlib, and removes it from Launchpad itself.
This is a resurrection of https:/
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'constraints.txt' |
2 | --- constraints.txt 2019-06-18 16:52:56 +0000 |
3 | +++ constraints.txt 2019-07-09 12:34:22 +0000 |
4 | @@ -234,7 +234,8 @@ |
5 | beautifulsoup4[lxml]==4.7.1 |
6 | billiard==3.5.0.5 |
7 | bson==0.3.3 |
8 | -bzr==2.6.0.lp.3 |
9 | +# lp:~launchpad/bzr/lp |
10 | +bzr==2.6.0.lp.4 |
11 | celery==4.1.1 |
12 | certifi==2019.3.9 |
13 | cffi==1.11.2 |
14 | |
15 | === modified file 'lib/launchpad_loggerhead/app.py' |
16 | --- lib/launchpad_loggerhead/app.py 2018-05-16 14:38:22 +0000 |
17 | +++ lib/launchpad_loggerhead/app.py 2019-07-09 12:34:22 +0000 |
18 | @@ -14,6 +14,7 @@ |
19 | urlutils, |
20 | ) |
21 | from bzrlib.transport import get_transport |
22 | +from bzrlib.url_policy_open import open_only_scheme |
23 | from loggerhead.apps import ( |
24 | favicon_app, |
25 | static_app, |
26 | @@ -47,7 +48,6 @@ |
27 | LAUNCHPAD_ANONYMOUS, |
28 | LAUNCHPAD_SERVICES, |
29 | ) |
30 | -from lp.codehosting.safe_open import safe_open |
31 | from lp.codehosting.vfs import get_lp_server |
32 | from lp.services.config import config |
33 | from lp.services.webapp.errorlog import ErrorReportingUtility |
34 | @@ -275,7 +275,7 @@ |
35 | self.log.info("Branch is public") |
36 | |
37 | try: |
38 | - bzr_branch = safe_open( |
39 | + bzr_branch = open_only_scheme( |
40 | lp_server.get_url().strip(':/'), branch_url) |
41 | except errors.NotBranchError as err: |
42 | self.log.warning('Not a branch: %s', err) |
43 | |
44 | === modified file 'lib/lp/code/interfaces/branch.py' |
45 | --- lib/lp/code/interfaces/branch.py 2019-04-17 12:03:22 +0000 |
46 | +++ lib/lp/code/interfaces/branch.py 2019-07-09 12:34:22 +0000 |
47 | @@ -1012,7 +1012,7 @@ |
48 | You can only call this if a server returned by `get_ro_server` or |
49 | `get_rw_server` is running. |
50 | |
51 | - :raise lp.codehosting.safe_open.BadUrl: If the branch is stacked |
52 | + :raise bzrlib.url_policy_open.BadUrl: If the branch is stacked |
53 | on or a reference to an unacceptable URL. |
54 | """ |
55 | |
56 | |
57 | === modified file 'lib/lp/code/model/branch.py' |
58 | --- lib/lp/code/model/branch.py 2019-04-17 10:34:13 +0000 |
59 | +++ lib/lp/code/model/branch.py 2019-07-09 12:34:22 +0000 |
60 | @@ -16,6 +16,7 @@ |
61 | |
62 | from bzrlib import urlutils |
63 | from bzrlib.revision import NULL_REVISION |
64 | +from bzrlib.url_policy_open import open_only_scheme |
65 | from lazr.lifecycle.event import ObjectCreatedEvent |
66 | import pytz |
67 | import six |
68 | @@ -138,7 +139,6 @@ |
69 | RevisionAuthor, |
70 | ) |
71 | from lp.code.model.seriessourcepackagebranch import SeriesSourcePackageBranch |
72 | -from lp.codehosting.safe_open import safe_open |
73 | from lp.registry.enums import PersonVisibility |
74 | from lp.registry.errors import CannotChangeInformationType |
75 | from lp.registry.interfaces.accesspolicy import ( |
76 | @@ -733,11 +733,11 @@ |
77 | |
78 | def getInternalBzrUrl(self): |
79 | """See `IBranch`.""" |
80 | - return 'lp-internal:///' + self.unique_name |
81 | + return six.ensure_str('lp-internal:///' + self.unique_name) |
82 | |
83 | def getBzrBranch(self): |
84 | """See `IBranch`.""" |
85 | - return safe_open('lp-internal', self.getInternalBzrUrl()) |
86 | + return open_only_scheme('lp-internal', self.getInternalBzrUrl()) |
87 | |
88 | @property |
89 | def display_name(self): |
90 | |
91 | === modified file 'lib/lp/code/model/tests/test_branch.py' |
92 | --- lib/lp/code/model/tests/test_branch.py 2019-05-22 14:57:45 +0000 |
93 | +++ lib/lp/code/model/tests/test_branch.py 2019-07-09 12:34:22 +0000 |
94 | @@ -16,6 +16,7 @@ |
95 | from bzrlib.branch import Branch |
96 | from bzrlib.bzrdir import BzrDir |
97 | from bzrlib.revision import NULL_REVISION |
98 | +from bzrlib.url_policy_open import BadUrl |
99 | from pytz import UTC |
100 | from sqlobject import SQLObjectNotFound |
101 | from storm.exceptions import LostObjectError |
102 | @@ -116,7 +117,6 @@ |
103 | add_revision_to_branch, |
104 | BranchHostingFixture, |
105 | ) |
106 | -from lp.codehosting.safe_open import BadUrl |
107 | from lp.codehosting.vfs.branchfs import get_real_branch_path |
108 | from lp.registry.enums import ( |
109 | BranchSharingPolicy, |
110 | @@ -3271,7 +3271,7 @@ |
111 | self.useBzrBranches(direct_database=True) |
112 | |
113 | def test_simple(self): |
114 | - # safe_open returns the underlying bzr branch of a database branch in |
115 | + # open_only_scheme returns the underlying bzr branch of a database branch in |
116 | # the simple, unstacked, case. |
117 | db_branch, tree = self.create_branch_and_tree() |
118 | # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is |
119 | @@ -3283,7 +3283,7 @@ |
120 | |
121 | def test_acceptable_stacking(self): |
122 | # If the underlying bzr branch of a database branch is stacked on |
123 | - # another launchpad branch safe_open returns it. |
124 | + # another launchpad branch open_only_scheme returns it. |
125 | db_stacked_on, stacked_on_tree = self.create_branch_and_tree() |
126 | db_stacked, stacked_tree = self.create_branch_and_tree() |
127 | stacked_tree.branch.set_stacked_on_url( |
128 | |
129 | === modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py' |
130 | --- lib/lp/codehosting/codeimport/tests/test_worker.py 2019-05-22 14:57:45 +0000 |
131 | +++ lib/lp/codehosting/codeimport/tests/test_worker.py 2019-07-09 12:34:22 +0000 |
132 | @@ -36,6 +36,13 @@ |
133 | get_transport, |
134 | get_transport_from_url, |
135 | ) |
136 | +from bzrlib.url_policy_open import ( |
137 | + _BlacklistPolicy, |
138 | + AcceptAnythingPolicy, |
139 | + BadUrl, |
140 | + BranchOpener, |
141 | + BranchOpenPolicy, |
142 | + ) |
143 | from bzrlib.urlutils import ( |
144 | join as urljoin, |
145 | local_path_from_url, |
146 | @@ -76,13 +83,6 @@ |
147 | ImportDataStore, |
148 | ToBzrImportWorker, |
149 | ) |
150 | -from lp.codehosting.safe_open import ( |
151 | - AcceptAnythingPolicy, |
152 | - BadUrl, |
153 | - BlacklistPolicy, |
154 | - BranchOpenPolicy, |
155 | - SafeBranchOpener, |
156 | - ) |
157 | from lp.codehosting.tests.helpers import create_branch_with_one_revision |
158 | from lp.services.config import config |
159 | from lp.services.log.logger import BufferLogger |
160 | @@ -129,7 +129,7 @@ |
161 | def setUp(self): |
162 | super(WorkerTest, self).setUp() |
163 | self.disable_directory_isolation() |
164 | - SafeBranchOpener.install_hook() |
165 | + BranchOpener.install_hook() |
166 | |
167 | def assertDirectoryTreesEqual(self, directory1, directory2): |
168 | """Assert that `directory1` has the same structure as `directory2`. |
169 | @@ -1242,7 +1242,7 @@ |
170 | cache_dir = get_cache(uuid).create_cache_dir() |
171 | cache_dir_contents = os.listdir(cache_dir) |
172 | self.assertNotEqual([], cache_dir_contents) |
173 | - opener = SafeBranchOpener(worker._opener_policy, worker.probers) |
174 | + opener = BranchOpener(worker._opener_policy, worker.probers) |
175 | remote_branch = opener.open(worker.source_details.url) |
176 | worker.pushBazaarBranch( |
177 | self.make_branch('.'), remote_branch=remote_branch) |
178 | @@ -1331,7 +1331,7 @@ |
179 | reference_url, target_url = self.createBranchReference() |
180 | source_details = self.factory.makeCodeImportSourceDetails( |
181 | url=reference_url, rcstype='bzr') |
182 | - policy = BlacklistPolicy(True, [target_url]) |
183 | + policy = _BlacklistPolicy(True, [target_url]) |
184 | worker = self.makeImportWorker(source_details, opener_policy=policy) |
185 | self.assertEqual( |
186 | CodeImportWorkerExitCode.FAILURE_FORBIDDEN, worker.run()) |
187 | @@ -1363,15 +1363,15 @@ |
188 | self.policy = CodeImportBranchOpenPolicy("bzr", "bzr") |
189 | |
190 | def test_follows_references(self): |
191 | - self.assertEqual(True, self.policy.shouldFollowReferences()) |
192 | + self.assertEqual(True, self.policy.should_follow_references()) |
193 | |
194 | def assertBadUrl(self, url): |
195 | - self.assertRaises(BadUrl, self.policy.checkOneURL, url) |
196 | + self.assertRaises(BadUrl, self.policy.check_one_url, url) |
197 | |
198 | def assertGoodUrl(self, url): |
199 | - self.policy.checkOneURL(url) |
200 | + self.policy.check_one_url(url) |
201 | |
202 | - def test_checkOneURL(self): |
203 | + def test_check_one_url(self): |
204 | self.assertBadUrl("sftp://somehost/") |
205 | self.assertBadUrl("/etc/passwd") |
206 | self.assertBadUrl("file:///etc/passwd") |
207 | @@ -1384,7 +1384,7 @@ |
208 | self.assertGoodUrl("bzr://bzr.example.com/somebzrurl/") |
209 | self.assertBadUrl("bzr://bazaar.launchpad.test/example") |
210 | |
211 | - def test_checkOneURL_git_to_bzr(self): |
212 | + def test_check_one_url_git_to_bzr(self): |
213 | self.policy = CodeImportBranchOpenPolicy("git", "bzr") |
214 | self.assertBadUrl("/etc/passwd") |
215 | self.assertBadUrl("file:///etc/passwd") |
216 | @@ -1392,7 +1392,7 @@ |
217 | self.assertGoodUrl("git://git.example.com/repo") |
218 | self.assertGoodUrl("git://git.launchpad.test/example") |
219 | |
220 | - def test_checkOneURL_git_to_git(self): |
221 | + def test_check_one_url_git_to_git(self): |
222 | self.policy = CodeImportBranchOpenPolicy("git", "git") |
223 | self.assertBadUrl("/etc/passwd") |
224 | self.assertBadUrl("file:///etc/passwd") |
225 | @@ -1408,7 +1408,7 @@ |
226 | def setUp(self): |
227 | http_utils.TestCaseWithRedirectedWebserver.setUp(self) |
228 | self.disable_directory_isolation() |
229 | - SafeBranchOpener.install_hook() |
230 | + BranchOpener.install_hook() |
231 | tree = self.make_branch_and_tree('.') |
232 | self.revid = tree.commit("A commit") |
233 | self.bazaar_store = BazaarBranchStore( |
234 | @@ -1438,14 +1438,14 @@ |
235 | def __init__(self, new_url): |
236 | self.new_url = new_url |
237 | |
238 | - def shouldFollowReferences(self): |
239 | + def should_follow_references(self): |
240 | return True |
241 | |
242 | - def checkOneURL(self, url): |
243 | + def check_one_url(self, url): |
244 | if url.startswith(self.new_url): |
245 | raise BadUrl(url) |
246 | |
247 | - def transformFallbackLocation(self, branch, url): |
248 | + def transform_fallback_location(self, branch, url): |
249 | return urlutils.join(branch.base, url), False |
250 | |
251 | policy = NewUrlBlacklistPolicy(self.get_new_url()) |
252 | |
253 | === modified file 'lib/lp/codehosting/codeimport/worker.py' |
254 | --- lib/lp/codehosting/codeimport/worker.py 2019-06-14 14:26:30 +0000 |
255 | +++ lib/lp/codehosting/codeimport/worker.py 2019-07-09 12:34:22 +0000 |
256 | @@ -55,6 +55,11 @@ |
257 | ) |
258 | import bzrlib.ui |
259 | from bzrlib.upgrade import upgrade |
260 | +from bzrlib.url_policy_open import ( |
261 | + BadUrl, |
262 | + BranchOpener, |
263 | + BranchOpenPolicy, |
264 | + ) |
265 | from bzrlib.urlutils import ( |
266 | join as urljoin, |
267 | local_path_from_url, |
268 | @@ -81,11 +86,6 @@ |
269 | extract_tarball, |
270 | ) |
271 | from lp.codehosting.codeimport.uifactory import LoggingUIFactory |
272 | -from lp.codehosting.safe_open import ( |
273 | - BadUrl, |
274 | - BranchOpenPolicy, |
275 | - SafeBranchOpener, |
276 | - ) |
277 | from lp.services.config import config |
278 | from lp.services.propertycache import cachedproperty |
279 | from lp.services.timeout import ( |
280 | @@ -111,8 +111,8 @@ |
281 | self.rcstype = rcstype |
282 | self.target_rcstype = target_rcstype |
283 | |
284 | - def shouldFollowReferences(self): |
285 | - """See `BranchOpenPolicy.shouldFollowReferences`. |
286 | + def should_follow_references(self): |
287 | + """See `BranchOpenPolicy.should_follow_references`. |
288 | |
289 | We traverse branch references for MIRRORED branches because they |
290 | provide a useful redirection mechanism and we want to be consistent |
291 | @@ -120,16 +120,16 @@ |
292 | """ |
293 | return True |
294 | |
295 | - def transformFallbackLocation(self, branch, url): |
296 | - """See `BranchOpenPolicy.transformFallbackLocation`. |
297 | + def transform_fallback_location(self, branch, url): |
298 | + """See `BranchOpenPolicy.transform_fallback_location`. |
299 | |
300 | For mirrored branches, we stack on whatever the remote branch claims |
301 | to stack on, but this URL still needs to be checked. |
302 | """ |
303 | return urljoin(branch.base, url), True |
304 | |
305 | - def checkOneURL(self, url): |
306 | - """See `BranchOpenPolicy.checkOneURL`. |
307 | + def check_one_url(self, url): |
308 | + """See `BranchOpenPolicy.check_one_url`. |
309 | |
310 | We refuse to mirror Bazaar branches from Launchpad, or any branches |
311 | from a ssh-like or file URL. |
312 | @@ -729,7 +729,7 @@ |
313 | def _doImport(self): |
314 | self._logger.info("Starting job.") |
315 | saved_factory = bzrlib.ui.ui_factory |
316 | - opener = SafeBranchOpener(self._opener_policy, self.probers) |
317 | + opener = BranchOpener(self._opener_policy, self.probers) |
318 | bzrlib.ui.ui_factory = LoggingUIFactory(logger=self._logger) |
319 | try: |
320 | self._logger.info( |
321 | @@ -1049,7 +1049,7 @@ |
322 | def _doImport(self): |
323 | self._logger.info("Starting job.") |
324 | try: |
325 | - self._opener_policy.checkOneURL(self.source_details.url) |
326 | + self._opener_policy.check_one_url(self.source_details.url) |
327 | except BadUrl as e: |
328 | self._logger.info("Invalid URL: %s" % e) |
329 | return CodeImportWorkerExitCode.FAILURE_FORBIDDEN |
330 | |
331 | === modified file 'lib/lp/codehosting/puller/tests/__init__.py' |
332 | --- lib/lp/codehosting/puller/tests/__init__.py 2012-04-16 23:02:44 +0000 |
333 | +++ lib/lp/codehosting/puller/tests/__init__.py 2019-07-09 12:34:22 +0000 |
334 | @@ -16,6 +16,7 @@ |
335 | TestingHTTPServer, |
336 | TestingThreadingHTTPServer, |
337 | ) |
338 | +from bzrlib.url_policy_open import AcceptAnythingPolicy |
339 | |
340 | from lp.codehosting.puller.worker import ( |
341 | BranchMirrorer, |
342 | @@ -23,7 +24,6 @@ |
343 | PullerWorker, |
344 | PullerWorkerProtocol, |
345 | ) |
346 | -from lp.codehosting.safe_open import AcceptAnythingPolicy |
347 | from lp.codehosting.tests.helpers import LoomTestMixin |
348 | from lp.testing import TestCaseWithFactory |
349 | |
350 | |
351 | === modified file 'lib/lp/codehosting/puller/tests/test_errors.py' |
352 | --- lib/lp/codehosting/puller/tests/test_errors.py 2019-05-22 14:57:45 +0000 |
353 | +++ lib/lp/codehosting/puller/tests/test_errors.py 2019-07-09 12:34:22 +0000 |
354 | @@ -18,6 +18,10 @@ |
355 | UnknownFormatError, |
356 | UnsupportedFormatError, |
357 | ) |
358 | +from bzrlib.url_policy_open import ( |
359 | + BranchLoopError, |
360 | + BranchReferenceForbidden, |
361 | + ) |
362 | from lazr.uri import InvalidURIError |
363 | |
364 | from lp.code.enums import BranchType |
365 | @@ -29,10 +33,6 @@ |
366 | PullerWorker, |
367 | PullerWorkerProtocol, |
368 | ) |
369 | -from lp.codehosting.safe_open import ( |
370 | - BranchLoopError, |
371 | - BranchReferenceForbidden, |
372 | - ) |
373 | from lp.testing import TestCase |
374 | |
375 | |
376 | |
377 | === modified file 'lib/lp/codehosting/puller/tests/test_worker.py' |
378 | --- lib/lp/codehosting/puller/tests/test_worker.py 2019-05-22 14:57:45 +0000 |
379 | +++ lib/lp/codehosting/puller/tests/test_worker.py 2019-07-09 12:34:22 +0000 |
380 | @@ -22,6 +22,12 @@ |
381 | TestCaseWithTransport, |
382 | ) |
383 | from bzrlib.transport import get_transport |
384 | +from bzrlib.url_policy_open import ( |
385 | + AcceptAnythingPolicy, |
386 | + BadUrl, |
387 | + BranchOpener, |
388 | + BranchOpenPolicy, |
389 | + ) |
390 | |
391 | from lp.code.enums import BranchType |
392 | from lp.codehosting.puller.tests import ( |
393 | @@ -37,14 +43,8 @@ |
394 | install_worker_ui_factory, |
395 | MirroredBranchPolicy, |
396 | PullerWorkerProtocol, |
397 | - SafeBranchOpener, |
398 | WORKER_ACTIVITY_NETWORK, |
399 | ) |
400 | -from lp.codehosting.safe_open import ( |
401 | - AcceptAnythingPolicy, |
402 | - BadUrl, |
403 | - BranchOpenPolicy, |
404 | - ) |
405 | from lp.testing import TestCase |
406 | from lp.testing.factory import ( |
407 | LaunchpadObjectFactory, |
408 | @@ -86,7 +86,7 @@ |
409 | |
410 | def setUp(self): |
411 | super(TestPullerWorker, self).setUp() |
412 | - SafeBranchOpener.install_hook() |
413 | + BranchOpener.install_hook() |
414 | |
415 | def test_mirror_opener_with_stacked_on_url(self): |
416 | # A PullerWorker for a mirrored branch gets a MirroredBranchPolicy as |
417 | @@ -277,7 +277,7 @@ |
418 | |
419 | def setUp(self): |
420 | super(TestReferenceOpener, self).setUp() |
421 | - SafeBranchOpener.install_hook() |
422 | + BranchOpener.install_hook() |
423 | |
424 | def createBranchReference(self, url): |
425 | """Create a pure branch reference that points to the specified URL. |
426 | @@ -318,20 +318,20 @@ |
427 | self.assertEqual(opened_branch.base, target_branch.base) |
428 | |
429 | def testFollowReferenceValue(self): |
430 | - # SafeBranchOpener.followReference gives the reference value for |
431 | + # BranchOpener.follow_reference gives the reference value for |
432 | # a branch reference. |
433 | - opener = SafeBranchOpener(BranchOpenPolicy()) |
434 | + opener = BranchOpener(BranchOpenPolicy()) |
435 | reference_value = 'http://example.com/branch' |
436 | reference_url = self.createBranchReference(reference_value) |
437 | self.assertEqual( |
438 | - reference_value, opener.followReference(reference_url)) |
439 | + reference_value, opener.follow_reference(reference_url)) |
440 | |
441 | def testFollowReferenceNone(self): |
442 | - # SafeBranchOpener.followReference gives None for a normal branch. |
443 | + # BranchOpener.follow_reference gives None for a normal branch. |
444 | self.make_branch('repo') |
445 | branch_url = self.get_url('repo') |
446 | - opener = SafeBranchOpener(BranchOpenPolicy()) |
447 | - self.assertIs(None, opener.followReference(branch_url)) |
448 | + opener = BranchOpener(BranchOpenPolicy()) |
449 | + self.assertIs(None, opener.follow_reference(branch_url)) |
450 | |
451 | |
452 | class TestMirroredBranchPolicy(TestCase): |
453 | @@ -344,44 +344,44 @@ |
454 | def testNoFileURL(self): |
455 | policy = MirroredBranchPolicy() |
456 | self.assertRaises( |
457 | - BadUrlScheme, policy.checkOneURL, |
458 | + BadUrlScheme, policy.check_one_url, |
459 | self.factory.getUniqueURL(scheme='file')) |
460 | |
461 | def testNoUnknownSchemeURLs(self): |
462 | policy = MirroredBranchPolicy() |
463 | self.assertRaises( |
464 | - BadUrlScheme, policy.checkOneURL, |
465 | + BadUrlScheme, policy.check_one_url, |
466 | self.factory.getUniqueURL(scheme='decorator+scheme')) |
467 | |
468 | def testNoSSHURL(self): |
469 | policy = MirroredBranchPolicy() |
470 | self.assertRaises( |
471 | - BadUrlSsh, policy.checkOneURL, |
472 | + BadUrlSsh, policy.check_one_url, |
473 | self.factory.getUniqueURL(scheme='bzr+ssh')) |
474 | |
475 | def testNoSftpURL(self): |
476 | policy = MirroredBranchPolicy() |
477 | self.assertRaises( |
478 | - BadUrlSsh, policy.checkOneURL, |
479 | + BadUrlSsh, policy.check_one_url, |
480 | self.factory.getUniqueURL(scheme='sftp')) |
481 | |
482 | def testNoLaunchpadURL(self): |
483 | policy = MirroredBranchPolicy() |
484 | self.assertRaises( |
485 | - BadUrlLaunchpad, policy.checkOneURL, |
486 | + BadUrlLaunchpad, policy.check_one_url, |
487 | self.factory.getUniqueURL(host='bazaar.launchpad.test')) |
488 | |
489 | def testNoHTTPSLaunchpadURL(self): |
490 | policy = MirroredBranchPolicy() |
491 | self.assertRaises( |
492 | - BadUrlLaunchpad, policy.checkOneURL, |
493 | + BadUrlLaunchpad, policy.check_one_url, |
494 | self.factory.getUniqueURL( |
495 | host='bazaar.launchpad.test', scheme='https')) |
496 | |
497 | def testNoOtherHostLaunchpadURL(self): |
498 | policy = MirroredBranchPolicy() |
499 | self.assertRaises( |
500 | - BadUrlLaunchpad, policy.checkOneURL, |
501 | + BadUrlLaunchpad, policy.check_one_url, |
502 | self.factory.getUniqueURL(host='code.launchpad.test')) |
503 | |
504 | def testLocalhost(self): |
505 | @@ -389,9 +389,9 @@ |
506 | 'codehosting', blacklisted_hostnames='localhost,127.0.0.1') |
507 | policy = MirroredBranchPolicy() |
508 | localhost_url = self.factory.getUniqueURL(host='localhost') |
509 | - self.assertRaises(BadUrl, policy.checkOneURL, localhost_url) |
510 | + self.assertRaises(BadUrl, policy.check_one_url, localhost_url) |
511 | localhost_url = self.factory.getUniqueURL(host='127.0.0.1') |
512 | - self.assertRaises(BadUrl, policy.checkOneURL, localhost_url) |
513 | + self.assertRaises(BadUrl, policy.check_one_url, localhost_url) |
514 | |
515 | def test_no_stacked_on_url(self): |
516 | # By default, a MirroredBranchPolicy does not stack branches. |
517 | @@ -495,7 +495,7 @@ |
518 | |
519 | def setUp(self): |
520 | super(TestWorkerProgressReporting, self).setUp() |
521 | - SafeBranchOpener.install_hook() |
522 | + BranchOpener.install_hook() |
523 | self.saved_factory = bzrlib.ui.ui_factory |
524 | self.disable_directory_isolation() |
525 | self.addCleanup(setattr, bzrlib.ui, 'ui_factory', self.saved_factory) |
526 | |
527 | === modified file 'lib/lp/codehosting/puller/tests/test_worker_formats.py' |
528 | --- lib/lp/codehosting/puller/tests/test_worker_formats.py 2015-09-28 17:38:45 +0000 |
529 | +++ lib/lp/codehosting/puller/tests/test_worker_formats.py 2019-07-09 12:34:22 +0000 |
530 | @@ -15,10 +15,10 @@ |
531 | from bzrlib.repofmt.knitpack_repo import RepositoryFormatKnitPack5 |
532 | from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1 |
533 | from bzrlib.tests.per_repository import TestCaseWithRepository |
534 | +from bzrlib.url_policy_open import BranchOpener |
535 | |
536 | import lp.codehosting # For bzr plugins. |
537 | from lp.codehosting.puller.tests import PullerWorkerMixin |
538 | -from lp.codehosting.safe_open import SafeBranchOpener |
539 | from lp.codehosting.tests.helpers import LoomTestMixin |
540 | |
541 | |
542 | @@ -29,7 +29,7 @@ |
543 | TestCaseWithRepository.setUp(self) |
544 | # make_bzrdir relies on this being a relative filesystem path. |
545 | self._source_branch_path = 'source-branch' |
546 | - SafeBranchOpener.install_hook() |
547 | + BranchOpener.install_hook() |
548 | self.worker = self.makePullerWorker( |
549 | self.get_url(self._source_branch_path), |
550 | self.get_url('dest-path')) |
551 | |
552 | === modified file 'lib/lp/codehosting/puller/worker.py' |
553 | --- lib/lp/codehosting/puller/worker.py 2012-06-29 08:40:05 +0000 |
554 | +++ lib/lp/codehosting/puller/worker.py 2019-07-09 12:34:22 +0000 |
555 | @@ -27,6 +27,13 @@ |
556 | from bzrlib.transport import get_transport |
557 | import bzrlib.ui |
558 | from bzrlib.ui import SilentUIFactory |
559 | +from bzrlib.url_policy_open import ( |
560 | + BadUrl, |
561 | + BranchLoopError, |
562 | + BranchOpener, |
563 | + BranchOpenPolicy, |
564 | + BranchReferenceForbidden, |
565 | + ) |
566 | from lazr.uri import ( |
567 | InvalidURIError, |
568 | URI, |
569 | @@ -39,13 +46,6 @@ |
570 | from lp.code.enums import BranchType |
571 | from lp.codehosting.bzrutils import identical_formats |
572 | from lp.codehosting.puller import get_lock_id_for_branch_id |
573 | -from lp.codehosting.safe_open import ( |
574 | - BadUrl, |
575 | - BranchLoopError, |
576 | - BranchOpenPolicy, |
577 | - BranchReferenceForbidden, |
578 | - SafeBranchOpener, |
579 | - ) |
580 | from lp.services.config import config |
581 | from lp.services.webapp import errorlog |
582 | |
583 | @@ -75,7 +75,7 @@ |
584 | """Found a URL with an untrusted scheme.""" |
585 | |
586 | def __init__(self, scheme, url): |
587 | - BadUrl.__init__(self, scheme, url) |
588 | + BadUrl.__init__(self, url) |
589 | self.scheme = scheme |
590 | |
591 | |
592 | @@ -195,7 +195,7 @@ |
593 | """ |
594 | self.policy = policy |
595 | self.protocol = protocol |
596 | - self.opener = SafeBranchOpener(policy) |
597 | + self.opener = BranchOpener(policy) |
598 | if log is not None: |
599 | self.log = log |
600 | else: |
601 | @@ -213,7 +213,7 @@ |
602 | URL must point to a writable location. |
603 | :return: The destination branch. |
604 | """ |
605 | - return self.opener.runWithTransformFallbackLocationHookInstalled( |
606 | + return self.opener.run_with_transform_fallback_location_hook_installed( |
607 | self.policy.createDestinationBranch, source_branch, |
608 | destination_url) |
609 | |
610 | @@ -552,8 +552,8 @@ |
611 | return None |
612 | return self.stacked_on_url |
613 | |
614 | - def shouldFollowReferences(self): |
615 | - """See `BranchOpenPolicy.shouldFollowReferences`. |
616 | + def should_follow_references(self): |
617 | + """See `BranchOpenPolicy.should_follow_references`. |
618 | |
619 | We traverse branch references for MIRRORED branches because they |
620 | provide a useful redirection mechanism and we want to be consistent |
621 | @@ -561,16 +561,16 @@ |
622 | """ |
623 | return True |
624 | |
625 | - def transformFallbackLocation(self, branch, url): |
626 | - """See `BranchOpenPolicy.transformFallbackLocation`. |
627 | + def transform_fallback_location(self, branch, url): |
628 | + """See `BranchOpenPolicy.transform_fallback_location`. |
629 | |
630 | For mirrored branches, we stack on whatever the remote branch claims |
631 | to stack on, but this URL still needs to be checked. |
632 | """ |
633 | return urlutils.join(branch.base, url), True |
634 | |
635 | - def checkOneURL(self, url): |
636 | - """See `BranchOpenPolicy.checkOneURL`. |
637 | + def check_one_url(self, url): |
638 | + """See `BranchOpenPolicy.check_one_url`. |
639 | |
640 | We refuse to mirror from Launchpad or a ssh-like or file URL. |
641 | """ |
642 | @@ -619,23 +619,23 @@ |
643 | break |
644 | return Branch.open_from_transport(dest_transport) |
645 | |
646 | - def shouldFollowReferences(self): |
647 | - """See `BranchOpenerPolicy.shouldFollowReferences`. |
648 | + def should_follow_references(self): |
649 | + """See `BranchOpenerPolicy.should_follow_references`. |
650 | |
651 | We do not traverse references for IMPORTED branches because the |
652 | code-import system should never produce branch references. |
653 | """ |
654 | return False |
655 | |
656 | - def transformFallbackLocation(self, branch, url): |
657 | - """See `BranchOpenerPolicy.transformFallbackLocation`. |
658 | + def transform_fallback_location(self, branch, url): |
659 | + """See `BranchOpenerPolicy.transform_fallback_location`. |
660 | |
661 | Import branches should not be stacked, ever. |
662 | """ |
663 | raise AssertionError("Import branch unexpectedly stacked!") |
664 | |
665 | - def checkOneURL(self, url): |
666 | - """See `BranchOpenerPolicy.checkOneURL`. |
667 | + def check_one_url(self, url): |
668 | + """See `BranchOpenerPolicy.check_one_url`. |
669 | |
670 | If the URL we are mirroring from does not start how we expect the pull |
671 | URLs of import branches to start, something has gone badly wrong, so |
672 | |
673 | === removed file 'lib/lp/codehosting/safe_open.py' |
674 | --- lib/lp/codehosting/safe_open.py 2012-08-21 17:34:42 +0000 |
675 | +++ lib/lp/codehosting/safe_open.py 1970-01-01 00:00:00 +0000 |
676 | @@ -1,354 +0,0 @@ |
677 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
678 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
679 | - |
680 | -"""Safe branch opening.""" |
681 | - |
682 | -__metaclass__ = type |
683 | - |
684 | -import threading |
685 | - |
686 | -from bzrlib import ( |
687 | - errors, |
688 | - trace, |
689 | - urlutils, |
690 | - ) |
691 | -from bzrlib.branch import Branch |
692 | -from bzrlib.bzrdir import ( |
693 | - BzrProber, |
694 | - RemoteBzrProber, |
695 | - ) |
696 | -from bzrlib.transport import ( |
697 | - do_catching_redirections, |
698 | - get_transport, |
699 | - ) |
700 | -from lazr.uri import URI |
701 | - |
702 | - |
703 | -__all__ = [ |
704 | - 'AcceptAnythingPolicy', |
705 | - 'BadUrl', |
706 | - 'BlacklistPolicy', |
707 | - 'BranchLoopError', |
708 | - 'BranchOpenPolicy', |
709 | - 'BranchReferenceForbidden', |
710 | - 'SafeBranchOpener', |
711 | - 'WhitelistPolicy', |
712 | - 'safe_open', |
713 | - ] |
714 | - |
715 | - |
716 | -# TODO JelmerVernooij 2011-08-06: This module is generic enough to be |
717 | -# in bzrlib, and may be of use to others. bug=850843 |
718 | - |
719 | -# These are the default probers that SafeBranchOpener will try to use, |
720 | -# unless a different set was specified. |
721 | - |
722 | -DEFAULT_PROBERS = [BzrProber, RemoteBzrProber] |
723 | - |
724 | - |
725 | -class BadUrl(Exception): |
726 | - """Tried to access a branch from a bad URL.""" |
727 | - |
728 | - |
729 | -class BranchReferenceForbidden(Exception): |
730 | - """Trying to mirror a branch reference and the branch type does not allow |
731 | - references. |
732 | - """ |
733 | - |
734 | - |
735 | -class BranchLoopError(Exception): |
736 | - """Encountered a branch cycle. |
737 | - |
738 | - A URL may point to a branch reference or it may point to a stacked branch. |
739 | - In either case, it's possible for there to be a cycle in these references, |
740 | - and this exception is raised when we detect such a cycle. |
741 | - """ |
742 | - |
743 | - |
744 | -class BranchOpenPolicy: |
745 | - """Policy on how to open branches. |
746 | - |
747 | - In particular, a policy determines which branches are safe to open by |
748 | - checking their URLs and deciding whether or not to follow branch |
749 | - references. |
750 | - """ |
751 | - |
752 | - def shouldFollowReferences(self): |
753 | - """Whether we traverse references when mirroring. |
754 | - |
755 | - Subclasses must override this method. |
756 | - |
757 | - If we encounter a branch reference and this returns false, an error is |
758 | - raised. |
759 | - |
760 | - :returns: A boolean to indicate whether to follow a branch reference. |
761 | - """ |
762 | - raise NotImplementedError(self.shouldFollowReferences) |
763 | - |
764 | - def transformFallbackLocation(self, branch, url): |
765 | - """Validate, maybe modify, 'url' to be used as a stacked-on location. |
766 | - |
767 | - :param branch: The branch that is being opened. |
768 | - :param url: The URL that the branch provides for its stacked-on |
769 | - location. |
770 | - :return: (new_url, check) where 'new_url' is the URL of the branch to |
771 | - actually open and 'check' is true if 'new_url' needs to be |
772 | - validated by checkAndFollowBranchReference. |
773 | - """ |
774 | - raise NotImplementedError(self.transformFallbackLocation) |
775 | - |
776 | - def checkOneURL(self, url): |
777 | - """Check the safety of the source URL. |
778 | - |
779 | - Subclasses must override this method. |
780 | - |
781 | - :param url: The source URL to check. |
782 | - :raise BadUrl: subclasses are expected to raise this or a subclass |
783 | - when it finds a URL it deems to be unsafe. |
784 | - """ |
785 | - raise NotImplementedError(self.checkOneURL) |
786 | - |
787 | - |
788 | -class BlacklistPolicy(BranchOpenPolicy): |
789 | - """Branch policy that forbids certain URLs.""" |
790 | - |
791 | - def __init__(self, should_follow_references, unsafe_urls=None): |
792 | - if unsafe_urls is None: |
793 | - unsafe_urls = set() |
794 | - self._unsafe_urls = unsafe_urls |
795 | - self._should_follow_references = should_follow_references |
796 | - |
797 | - def shouldFollowReferences(self): |
798 | - return self._should_follow_references |
799 | - |
800 | - def checkOneURL(self, url): |
801 | - if url in self._unsafe_urls: |
802 | - raise BadUrl(url) |
803 | - |
804 | - def transformFallbackLocation(self, branch, url): |
805 | - """See `BranchOpenPolicy.transformFallbackLocation`. |
806 | - |
807 | - This class is not used for testing our smarter stacking features so we |
808 | - just do the simplest thing: return the URL that would be used anyway |
809 | - and don't check it. |
810 | - """ |
811 | - return urlutils.join(branch.base, url), False |
812 | - |
813 | - |
814 | -class AcceptAnythingPolicy(BlacklistPolicy): |
815 | - """Accept anything, to make testing easier.""" |
816 | - |
817 | - def __init__(self): |
818 | - super(AcceptAnythingPolicy, self).__init__(True, set()) |
819 | - |
820 | - |
821 | -class WhitelistPolicy(BranchOpenPolicy): |
822 | - """Branch policy that only allows certain URLs.""" |
823 | - |
824 | - def __init__(self, should_follow_references, allowed_urls=None, |
825 | - check=False): |
826 | - if allowed_urls is None: |
827 | - allowed_urls = [] |
828 | - self.allowed_urls = set(url.rstrip('/') for url in allowed_urls) |
829 | - self.check = check |
830 | - |
831 | - def shouldFollowReferences(self): |
832 | - return self._should_follow_references |
833 | - |
834 | - def checkOneURL(self, url): |
835 | - if url.rstrip('/') not in self.allowed_urls: |
836 | - raise BadUrl(url) |
837 | - |
838 | - def transformFallbackLocation(self, branch, url): |
839 | - """See `BranchOpenPolicy.transformFallbackLocation`. |
840 | - |
841 | - Here we return the URL that would be used anyway and optionally check |
842 | - it. |
843 | - """ |
844 | - return urlutils.join(branch.base, url), self.check |
845 | - |
846 | - |
847 | -class SingleSchemePolicy(BranchOpenPolicy): |
848 | - """Branch open policy that rejects URLs not on the given scheme.""" |
849 | - |
850 | - def __init__(self, allowed_scheme): |
851 | - self.allowed_scheme = allowed_scheme |
852 | - |
853 | - def shouldFollowReferences(self): |
854 | - return True |
855 | - |
856 | - def transformFallbackLocation(self, branch, url): |
857 | - return urlutils.join(branch.base, url), True |
858 | - |
859 | - def checkOneURL(self, url): |
860 | - """Check that `url` is safe to open.""" |
861 | - if URI(url).scheme != self.allowed_scheme: |
862 | - raise BadUrl(url) |
863 | - |
864 | - |
865 | -class SafeBranchOpener(object): |
866 | - """Safe branch opener. |
867 | - |
868 | - All locations that are opened (stacked-on branches, references) are |
869 | - checked against a policy object. |
870 | - |
871 | - The policy object is expected to have the following methods: |
872 | - * checkOneURL |
873 | - * shouldFollowReferences |
874 | - * transformFallbackLocation |
875 | - """ |
876 | - |
877 | - _threading_data = threading.local() |
878 | - |
879 | - def __init__(self, policy, probers=None): |
880 | - """Create a new SafeBranchOpener. |
881 | - |
882 | - :param policy: The opener policy to use. |
883 | - :param probers: Optional list of probers to allow. |
884 | - Defaults to local and remote bzr probers. |
885 | - """ |
886 | - self.policy = policy |
887 | - self._seen_urls = set() |
888 | - if probers is None: |
889 | - self.probers = list(DEFAULT_PROBERS) |
890 | - else: |
891 | - self.probers = probers |
892 | - |
893 | - @classmethod |
894 | - def install_hook(cls): |
895 | - """Install the ``transformFallbackLocation`` hook. |
896 | - |
897 | - This is done at module import time, but transformFallbackLocationHook |
898 | - doesn't do anything unless the `_active_openers` threading.Local |
899 | - object has a 'opener' attribute in this thread. |
900 | - |
901 | - This is in a module-level function rather than performed at module |
902 | - level so that it can be called in setUp for testing `SafeBranchOpener` |
903 | - as bzrlib.tests.TestCase.setUp clears hooks. |
904 | - """ |
905 | - Branch.hooks.install_named_hook( |
906 | - 'transform_fallback_location', |
907 | - cls.transformFallbackLocationHook, |
908 | - 'SafeBranchOpener.transformFallbackLocationHook') |
909 | - |
910 | - def checkAndFollowBranchReference(self, url): |
911 | - """Check URL (and possibly the referenced URL) for safety. |
912 | - |
913 | - This method checks that `url` passes the policy's `checkOneURL` |
914 | - method, and if `url` refers to a branch reference, it checks whether |
915 | - references are allowed and whether the reference's URL passes muster |
916 | - also -- recursively, until a real branch is found. |
917 | - |
918 | - :param url: URL to check |
919 | - :raise BranchLoopError: If the branch references form a loop. |
920 | - :raise BranchReferenceForbidden: If this opener forbids branch |
921 | - references. |
922 | - """ |
923 | - while True: |
924 | - if url in self._seen_urls: |
925 | - raise BranchLoopError() |
926 | - self._seen_urls.add(url) |
927 | - self.policy.checkOneURL(url) |
928 | - next_url = self.followReference(url) |
929 | - if next_url is None: |
930 | - return url |
931 | - url = next_url |
932 | - if not self.policy.shouldFollowReferences(): |
933 | - raise BranchReferenceForbidden(url) |
934 | - |
935 | - @classmethod |
936 | - def transformFallbackLocationHook(cls, branch, url): |
937 | - """Installed as the 'transform_fallback_location' Branch hook. |
938 | - |
939 | - This method calls `transformFallbackLocation` on the policy object and |
940 | - either returns the url it provides or passes it back to |
941 | - checkAndFollowBranchReference. |
942 | - """ |
943 | - try: |
944 | - opener = getattr(cls._threading_data, "opener") |
945 | - except AttributeError: |
946 | - return url |
947 | - new_url, check = opener.policy.transformFallbackLocation(branch, url) |
948 | - if check: |
949 | - return opener.checkAndFollowBranchReference(new_url) |
950 | - else: |
951 | - return new_url |
952 | - |
953 | - def runWithTransformFallbackLocationHookInstalled( |
954 | - self, callable, *args, **kw): |
955 | - assert (self.transformFallbackLocationHook in |
956 | - Branch.hooks['transform_fallback_location']) |
957 | - self._threading_data.opener = self |
958 | - try: |
959 | - return callable(*args, **kw) |
960 | - finally: |
961 | - del self._threading_data.opener |
962 | - # We reset _seen_urls here to avoid multiple calls to open giving |
963 | - # spurious loop exceptions. |
964 | - self._seen_urls = set() |
965 | - |
966 | - def followReference(self, url): |
967 | - """Get the branch-reference value at the specified url. |
968 | - |
969 | - This exists as a separate method only to be overridden in unit tests. |
970 | - """ |
971 | - bzrdir = self._open_dir(url) |
972 | - return bzrdir.get_branch_reference() |
973 | - |
974 | - def _open_dir(self, url): |
975 | - """Simple BzrDir.open clone that only uses specific probers. |
976 | - |
977 | - :param url: URL to open |
978 | - :return: ControlDir instance |
979 | - """ |
980 | - def redirected(transport, e, redirection_notice): |
981 | - self.policy.checkOneURL(e.target) |
982 | - redirected_transport = transport._redirected_to( |
983 | - e.source, e.target) |
984 | - if redirected_transport is None: |
985 | - raise errors.NotBranchError(e.source) |
986 | - trace.note('%s is%s redirected to %s', |
987 | - transport.base, e.permanently, redirected_transport.base) |
988 | - return redirected_transport |
989 | - |
990 | - def find_format(transport): |
991 | - last_error = errors.NotBranchError(transport.base) |
992 | - for prober_kls in self.probers: |
993 | - prober = prober_kls() |
994 | - try: |
995 | - return transport, prober.probe_transport(transport) |
996 | - except errors.NotBranchError as e: |
997 | - last_error = e |
998 | - else: |
999 | - raise last_error |
1000 | - transport = get_transport(url) |
1001 | - transport, format = do_catching_redirections(find_format, transport, |
1002 | - redirected) |
1003 | - return format.open(transport) |
1004 | - |
1005 | - def open(self, url, ignore_fallbacks=False): |
1006 | - """Open the Bazaar branch at url, first checking for safety. |
1007 | - |
1008 | - What safety means is defined by a subclasses `followReference` and |
1009 | - `checkOneURL` methods. |
1010 | - """ |
1011 | - url = self.checkAndFollowBranchReference(url) |
1012 | - |
1013 | - def open_branch(url, ignore_fallbacks): |
1014 | - dir = self._open_dir(url) |
1015 | - return dir.open_branch(ignore_fallbacks=ignore_fallbacks) |
1016 | - return self.runWithTransformFallbackLocationHookInstalled( |
1017 | - open_branch, url, ignore_fallbacks) |
1018 | - |
1019 | - |
1020 | -def safe_open(allowed_scheme, url, ignore_fallbacks=False): |
1021 | - """Open the branch at `url`, only accessing URLs on `allowed_scheme`. |
1022 | - |
1023 | - :raises BadUrl: An attempt was made to open a URL that was not on |
1024 | - `allowed_scheme`. |
1025 | - """ |
1026 | - return SafeBranchOpener(SingleSchemePolicy(allowed_scheme)).open(url, |
1027 | - ignore_fallbacks=ignore_fallbacks) |
1028 | - |
1029 | - |
1030 | -SafeBranchOpener.install_hook() |
1031 | |
1032 | === modified file 'lib/lp/codehosting/scanner/tests/test_bzrsync.py' |
1033 | --- lib/lp/codehosting/scanner/tests/test_bzrsync.py 2019-06-20 13:16:35 +0000 |
1034 | +++ lib/lp/codehosting/scanner/tests/test_bzrsync.py 2019-07-09 12:34:22 +0000 |
1035 | @@ -14,6 +14,7 @@ |
1036 | ) |
1037 | from bzrlib.tests import TestCaseWithTransport |
1038 | from bzrlib.uncommit import uncommit |
1039 | +from bzrlib.url_policy_open import BranchOpener |
1040 | from fixtures import ( |
1041 | FakeLogger, |
1042 | TempDir, |
1043 | @@ -48,7 +49,6 @@ |
1044 | read_locked, |
1045 | write_locked, |
1046 | ) |
1047 | -from lp.codehosting.safe_open import SafeBranchOpener |
1048 | from lp.codehosting.scanner.bzrsync import BzrSync |
1049 | from lp.services.config import config |
1050 | from lp.services.database.interfaces import IStore |
1051 | @@ -90,7 +90,7 @@ |
1052 | |
1053 | def setUp(self): |
1054 | super(BzrSyncTestCase, self).setUp() |
1055 | - SafeBranchOpener.install_hook() |
1056 | + BranchOpener.install_hook() |
1057 | self.disable_directory_isolation() |
1058 | self.useBzrBranches(direct_database=True) |
1059 | self.makeFixtures() |
1060 | |
1061 | === removed file 'lib/lp/codehosting/tests/test_safe_open.py' |
1062 | --- lib/lp/codehosting/tests/test_safe_open.py 2018-01-02 16:10:26 +0000 |
1063 | +++ lib/lp/codehosting/tests/test_safe_open.py 1970-01-01 00:00:00 +0000 |
1064 | @@ -1,378 +0,0 @@ |
1065 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
1066 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
1067 | - |
1068 | -"""Tests for the safe branch open code.""" |
1069 | - |
1070 | - |
1071 | -__metaclass__ = type |
1072 | - |
1073 | -from bzrlib.branch import ( |
1074 | - Branch, |
1075 | - BranchReferenceFormat, |
1076 | - BzrBranchFormat7, |
1077 | - ) |
1078 | -from bzrlib.bzrdir import ( |
1079 | - BzrDir, |
1080 | - BzrDirMetaFormat1, |
1081 | - BzrProber, |
1082 | - ) |
1083 | -from bzrlib.controldir import ControlDirFormat |
1084 | -from bzrlib.errors import NotBranchError |
1085 | -from bzrlib.repofmt.knitpack_repo import RepositoryFormatKnitPack1 |
1086 | -from bzrlib.tests import TestCaseWithTransport |
1087 | -from bzrlib.transport import chroot |
1088 | -from lazr.uri import URI |
1089 | - |
1090 | -from lp.codehosting.safe_open import ( |
1091 | - BadUrl, |
1092 | - BlacklistPolicy, |
1093 | - BranchLoopError, |
1094 | - BranchReferenceForbidden, |
1095 | - safe_open, |
1096 | - SafeBranchOpener, |
1097 | - WhitelistPolicy, |
1098 | - ) |
1099 | -from lp.codehosting.tests.helpers import force_stacked_on_url |
1100 | -from lp.testing import TestCase |
1101 | - |
1102 | - |
1103 | -class TestSafeBranchOpenerCheckAndFollowBranchReference(TestCase): |
1104 | - """Unit tests for `SafeBranchOpener.checkAndFollowBranchReference`.""" |
1105 | - |
1106 | - def setUp(self): |
1107 | - super(TestSafeBranchOpenerCheckAndFollowBranchReference, self).setUp() |
1108 | - SafeBranchOpener.install_hook() |
1109 | - |
1110 | - class StubbedSafeBranchOpener(SafeBranchOpener): |
1111 | - """SafeBranchOpener that provides canned answers. |
1112 | - |
1113 | - We implement the methods we need to to be able to control all the |
1114 | - inputs to the `BranchMirrorer.checkSource` method, which is what is |
1115 | - being tested in this class. |
1116 | - """ |
1117 | - |
1118 | - def __init__(self, references, policy): |
1119 | - parent_cls = TestSafeBranchOpenerCheckAndFollowBranchReference |
1120 | - super(parent_cls.StubbedSafeBranchOpener, self).__init__(policy) |
1121 | - self._reference_values = {} |
1122 | - for i in range(len(references) - 1): |
1123 | - self._reference_values[references[i]] = references[i + 1] |
1124 | - self.follow_reference_calls = [] |
1125 | - |
1126 | - def followReference(self, url): |
1127 | - self.follow_reference_calls.append(url) |
1128 | - return self._reference_values[url] |
1129 | - |
1130 | - def makeBranchOpener(self, should_follow_references, references, |
1131 | - unsafe_urls=None): |
1132 | - policy = BlacklistPolicy(should_follow_references, unsafe_urls) |
1133 | - opener = self.StubbedSafeBranchOpener(references, policy) |
1134 | - return opener |
1135 | - |
1136 | - def testCheckInitialURL(self): |
1137 | - # checkSource rejects all URLs that are not allowed. |
1138 | - opener = self.makeBranchOpener(None, [], set(['a'])) |
1139 | - self.assertRaises( |
1140 | - BadUrl, opener.checkAndFollowBranchReference, 'a') |
1141 | - |
1142 | - def testNotReference(self): |
1143 | - # When branch references are forbidden, checkAndFollowBranchReference |
1144 | - # does not raise on non-references. |
1145 | - opener = self.makeBranchOpener(False, ['a', None]) |
1146 | - self.assertEqual('a', opener.checkAndFollowBranchReference('a')) |
1147 | - self.assertEqual(['a'], opener.follow_reference_calls) |
1148 | - |
1149 | - def testBranchReferenceForbidden(self): |
1150 | - # checkAndFollowBranchReference raises BranchReferenceForbidden if |
1151 | - # branch references are forbidden and the source URL points to a |
1152 | - # branch reference. |
1153 | - opener = self.makeBranchOpener(False, ['a', 'b']) |
1154 | - self.assertRaises( |
1155 | - BranchReferenceForbidden, |
1156 | - opener.checkAndFollowBranchReference, 'a') |
1157 | - self.assertEqual(['a'], opener.follow_reference_calls) |
1158 | - |
1159 | - def testAllowedReference(self): |
1160 | - # checkAndFollowBranchReference does not raise if following references |
1161 | - # is allowed and the source URL points to a branch reference to a |
1162 | - # permitted location. |
1163 | - opener = self.makeBranchOpener(True, ['a', 'b', None]) |
1164 | - self.assertEqual('b', opener.checkAndFollowBranchReference('a')) |
1165 | - self.assertEqual(['a', 'b'], opener.follow_reference_calls) |
1166 | - |
1167 | - def testCheckReferencedURLs(self): |
1168 | - # checkAndFollowBranchReference checks if the URL a reference points |
1169 | - # to is safe. |
1170 | - opener = self.makeBranchOpener( |
1171 | - True, ['a', 'b', None], unsafe_urls=set('b')) |
1172 | - self.assertRaises( |
1173 | - BadUrl, opener.checkAndFollowBranchReference, 'a') |
1174 | - self.assertEqual(['a'], opener.follow_reference_calls) |
1175 | - |
1176 | - def testSelfReferencingBranch(self): |
1177 | - # checkAndFollowBranchReference raises BranchReferenceLoopError if |
1178 | - # following references is allowed and the source url points to a |
1179 | - # self-referencing branch reference. |
1180 | - opener = self.makeBranchOpener(True, ['a', 'a']) |
1181 | - self.assertRaises( |
1182 | - BranchLoopError, opener.checkAndFollowBranchReference, 'a') |
1183 | - self.assertEqual(['a'], opener.follow_reference_calls) |
1184 | - |
1185 | - def testBranchReferenceLoop(self): |
1186 | - # checkAndFollowBranchReference raises BranchReferenceLoopError if |
1187 | - # following references is allowed and the source url points to a loop |
1188 | - # of branch references. |
1189 | - references = ['a', 'b', 'a'] |
1190 | - opener = self.makeBranchOpener(True, references) |
1191 | - self.assertRaises( |
1192 | - BranchLoopError, opener.checkAndFollowBranchReference, 'a') |
1193 | - self.assertEqual(['a', 'b'], opener.follow_reference_calls) |
1194 | - |
1195 | - |
1196 | -class TrackingProber(BzrProber): |
1197 | - """Subclass of BzrProber which tracks URLs it has been asked to open.""" |
1198 | - |
1199 | - seen_urls = [] |
1200 | - |
1201 | - @classmethod |
1202 | - def probe_transport(klass, transport): |
1203 | - klass.seen_urls.append(transport.base) |
1204 | - return BzrProber.probe_transport(transport) |
1205 | - |
1206 | - |
1207 | -class TestSafeBranchOpenerStacking(TestCaseWithTransport): |
1208 | - |
1209 | - def setUp(self): |
1210 | - super(TestSafeBranchOpenerStacking, self).setUp() |
1211 | - SafeBranchOpener.install_hook() |
1212 | - |
1213 | - def makeBranchOpener(self, allowed_urls, probers=None): |
1214 | - policy = WhitelistPolicy(True, allowed_urls, True) |
1215 | - return SafeBranchOpener(policy, probers) |
1216 | - |
1217 | - def makeBranch(self, path, branch_format, repository_format): |
1218 | - """Make a Bazaar branch at 'path' with the given formats.""" |
1219 | - bzrdir_format = BzrDirMetaFormat1() |
1220 | - bzrdir_format.set_branch_format(branch_format) |
1221 | - bzrdir = self.make_bzrdir(path, format=bzrdir_format) |
1222 | - repository_format.initialize(bzrdir) |
1223 | - return bzrdir.create_branch() |
1224 | - |
1225 | - def testProbers(self): |
1226 | - # Only the specified probers should be used |
1227 | - b = self.make_branch('branch') |
1228 | - opener = self.makeBranchOpener([b.base], probers=[]) |
1229 | - self.assertRaises(NotBranchError, opener.open, b.base) |
1230 | - opener = self.makeBranchOpener([b.base], probers=[BzrProber]) |
1231 | - self.assertEqual(b.base, opener.open(b.base).base) |
1232 | - |
1233 | - def testDefaultProbers(self): |
1234 | - # If no probers are specified to the constructor |
1235 | - # of SafeBranchOpener, then a safe set will be used, |
1236 | - # rather than all probers registered in bzr. |
1237 | - self.addCleanup(ControlDirFormat.unregister_prober, TrackingProber) |
1238 | - ControlDirFormat.register_prober(TrackingProber) |
1239 | - # Open a location without any branches, so that all probers are |
1240 | - # tried. |
1241 | - # First, check that the TrackingProber tracks correctly. |
1242 | - TrackingProber.seen_urls = [] |
1243 | - opener = self.makeBranchOpener(["."], probers=[TrackingProber]) |
1244 | - self.assertRaises(NotBranchError, opener.open, ".") |
1245 | - self.assertEqual(1, len(TrackingProber.seen_urls)) |
1246 | - TrackingProber.seen_urls = [] |
1247 | - # And make sure it's registered in such a way that BzrDir.open would |
1248 | - # use it. |
1249 | - self.assertRaises(NotBranchError, BzrDir.open, ".") |
1250 | - self.assertEqual(1, len(TrackingProber.seen_urls)) |
1251 | - TrackingProber.seen_urls = [] |
1252 | - # Make sure that SafeBranchOpener doesn't use it if no |
1253 | - # probers were specified |
1254 | - opener = self.makeBranchOpener(["."]) |
1255 | - self.assertRaises(NotBranchError, opener.open, ".") |
1256 | - self.assertEqual(0, len(TrackingProber.seen_urls)) |
1257 | - |
1258 | - def testAllowedURL(self): |
1259 | - # checkSource does not raise an exception for branches stacked on |
1260 | - # branches with allowed URLs. |
1261 | - stacked_on_branch = self.make_branch('base-branch') |
1262 | - stacked_branch = self.make_branch('stacked-branch') |
1263 | - stacked_branch.set_stacked_on_url(stacked_on_branch.base) |
1264 | - opener = self.makeBranchOpener( |
1265 | - [stacked_branch.base, stacked_on_branch.base]) |
1266 | - # This doesn't raise an exception. |
1267 | - opener.open(stacked_branch.base) |
1268 | - |
1269 | - def testUnstackableRepository(self): |
1270 | - # checkSource treats branches with UnstackableRepositoryFormats as |
1271 | - # being not stacked. |
1272 | - branch = self.makeBranch( |
1273 | - 'unstacked', BzrBranchFormat7(), RepositoryFormatKnitPack1()) |
1274 | - opener = self.makeBranchOpener([branch.base]) |
1275 | - # This doesn't raise an exception. |
1276 | - opener.open(branch.base) |
1277 | - |
1278 | - def testAllowedRelativeURL(self): |
1279 | - # checkSource passes on absolute urls to checkOneURL, even if the |
1280 | - # value of stacked_on_location in the config is set to a relative URL. |
1281 | - stacked_on_branch = self.make_branch('base-branch') |
1282 | - stacked_branch = self.make_branch('stacked-branch') |
1283 | - stacked_branch.set_stacked_on_url('../base-branch') |
1284 | - opener = self.makeBranchOpener( |
1285 | - [stacked_branch.base, stacked_on_branch.base]) |
1286 | - # Note that stacked_on_branch.base is not '../base-branch', it's an |
1287 | - # absolute URL. |
1288 | - self.assertNotEqual('../base-branch', stacked_on_branch.base) |
1289 | - # This doesn't raise an exception. |
1290 | - opener.open(stacked_branch.base) |
1291 | - |
1292 | - def testAllowedRelativeNested(self): |
1293 | - # Relative URLs are resolved relative to the stacked branch. |
1294 | - self.get_transport().mkdir('subdir') |
1295 | - a = self.make_branch('subdir/a') |
1296 | - b = self.make_branch('b') |
1297 | - b.set_stacked_on_url('../subdir/a') |
1298 | - c = self.make_branch('subdir/c') |
1299 | - c.set_stacked_on_url('../../b') |
1300 | - opener = self.makeBranchOpener([c.base, b.base, a.base]) |
1301 | - # This doesn't raise an exception. |
1302 | - opener.open(c.base) |
1303 | - |
1304 | - def testForbiddenURL(self): |
1305 | - # checkSource raises a BadUrl exception if a branch is stacked on a |
1306 | - # branch with a forbidden URL. |
1307 | - stacked_on_branch = self.make_branch('base-branch') |
1308 | - stacked_branch = self.make_branch('stacked-branch') |
1309 | - stacked_branch.set_stacked_on_url(stacked_on_branch.base) |
1310 | - opener = self.makeBranchOpener([stacked_branch.base]) |
1311 | - self.assertRaises(BadUrl, opener.open, stacked_branch.base) |
1312 | - |
1313 | - def testForbiddenURLNested(self): |
1314 | - # checkSource raises a BadUrl exception if a branch is stacked on a |
1315 | - # branch that is in turn stacked on a branch with a forbidden URL. |
1316 | - a = self.make_branch('a') |
1317 | - b = self.make_branch('b') |
1318 | - b.set_stacked_on_url(a.base) |
1319 | - c = self.make_branch('c') |
1320 | - c.set_stacked_on_url(b.base) |
1321 | - opener = self.makeBranchOpener([c.base, b.base]) |
1322 | - self.assertRaises(BadUrl, opener.open, c.base) |
1323 | - |
1324 | - def testSelfStackedBranch(self): |
1325 | - # checkSource raises StackingLoopError if a branch is stacked on |
1326 | - # itself. This avoids infinite recursion errors. |
1327 | - a = self.make_branch('a') |
1328 | - force_stacked_on_url(a, a.base) |
1329 | - opener = self.makeBranchOpener([a.base]) |
1330 | - self.assertRaises(BranchLoopError, opener.open, a.base) |
1331 | - |
1332 | - def testLoopStackedBranch(self): |
1333 | - # checkSource raises StackingLoopError if a branch is stacked in such |
1334 | - # a way so that it is ultimately stacked on itself. e.g. a stacked on |
1335 | - # b stacked on a. |
1336 | - a = self.make_branch('a') |
1337 | - b = self.make_branch('b') |
1338 | - a.set_stacked_on_url(b.base) |
1339 | - b.set_stacked_on_url(a.base) |
1340 | - opener = self.makeBranchOpener([a.base, b.base]) |
1341 | - self.assertRaises(BranchLoopError, opener.open, a.base) |
1342 | - self.assertRaises(BranchLoopError, opener.open, b.base) |
1343 | - |
1344 | - def testCustomOpener(self): |
1345 | - # A custom function for opening a control dir can be specified. |
1346 | - a = self.make_branch('a') |
1347 | - b = self.make_branch('b') |
1348 | - b.set_stacked_on_url(a.base) |
1349 | - |
1350 | - TrackingProber.seen_urls = [] |
1351 | - opener = self.makeBranchOpener( |
1352 | - [a.base, b.base], probers=[TrackingProber]) |
1353 | - opener.open(b.base) |
1354 | - self.assertEqual(set(TrackingProber.seen_urls), set([b.base, a.base])) |
1355 | - |
1356 | - def testCustomOpenerWithBranchReference(self): |
1357 | - # A custom function for opening a control dir can be specified. |
1358 | - a = self.make_branch('a') |
1359 | - b_dir = self.make_bzrdir('b') |
1360 | - b = BranchReferenceFormat().initialize(b_dir, target_branch=a) |
1361 | - TrackingProber.seen_urls = [] |
1362 | - opener = self.makeBranchOpener( |
1363 | - [a.base, b.base], probers=[TrackingProber]) |
1364 | - opener.open(b.base) |
1365 | - self.assertEqual(set(TrackingProber.seen_urls), set([b.base, a.base])) |
1366 | - |
1367 | - def test_ignore_fallbacks(self): |
1368 | - """"Cross-format stacking doesn't error with ignore_fallbacks.""" |
1369 | - stacked, stacked_on = make_cross_format_stacked(self) |
1370 | - opener = self.makeBranchOpener([stacked.base, stacked_on.base]) |
1371 | - opener.open(stacked.base, ignore_fallbacks=True) |
1372 | - |
1373 | - |
1374 | -def make_cross_format_stacked(test_case): |
1375 | - test_case.get_transport().mkdir('inside') |
1376 | - stacked = test_case.make_branch('inside/stacked', format='1.6') |
1377 | - stacked_on = test_case.make_branch('inside/stacked-on', format='2a') |
1378 | - force_stacked_on_url(stacked, stacked_on.base) |
1379 | - return stacked, stacked_on |
1380 | - |
1381 | - |
1382 | -class TestSafeOpen(TestCaseWithTransport): |
1383 | - """Tests for `safe_open`.""" |
1384 | - |
1385 | - def setUp(self): |
1386 | - super(TestSafeOpen, self).setUp() |
1387 | - SafeBranchOpener.install_hook() |
1388 | - |
1389 | - def test_hook_does_not_interfere(self): |
1390 | - # The transform_fallback_location hook does not interfere with regular |
1391 | - # stacked branch access outside of safe_open. |
1392 | - self.make_branch('stacked') |
1393 | - self.make_branch('stacked-on') |
1394 | - Branch.open('stacked').set_stacked_on_url('../stacked-on') |
1395 | - Branch.open('stacked') |
1396 | - |
1397 | - def get_chrooted_scheme(self, relpath): |
1398 | - """Create a server that is chrooted to `relpath`. |
1399 | - |
1400 | - :return: ``(scheme, get_url)`` where ``scheme`` is the scheme of the |
1401 | - chroot server and ``get_url`` returns URLs on said server. |
1402 | - """ |
1403 | - transport = self.get_transport(relpath) |
1404 | - chroot_server = chroot.ChrootServer(transport) |
1405 | - chroot_server.start_server() |
1406 | - self.addCleanup(chroot_server.stop_server) |
1407 | - |
1408 | - def get_url(relpath): |
1409 | - return chroot_server.get_url() + relpath |
1410 | - |
1411 | - return URI(chroot_server.get_url()).scheme, get_url |
1412 | - |
1413 | - def test_stacked_within_scheme(self): |
1414 | - # A branch that is stacked on a URL of the same scheme is safe to |
1415 | - # open. |
1416 | - self.get_transport().mkdir('inside') |
1417 | - self.make_branch('inside/stacked') |
1418 | - self.make_branch('inside/stacked-on') |
1419 | - scheme, get_chrooted_url = self.get_chrooted_scheme('inside') |
1420 | - Branch.open(get_chrooted_url('stacked')).set_stacked_on_url( |
1421 | - get_chrooted_url('stacked-on')) |
1422 | - safe_open(scheme, get_chrooted_url('stacked')) |
1423 | - |
1424 | - def test_stacked_outside_scheme(self): |
1425 | - # A branch that is stacked on a URL that is not of the same scheme is |
1426 | - # not safe to open. |
1427 | - self.get_transport().mkdir('inside') |
1428 | - self.get_transport().mkdir('outside') |
1429 | - self.make_branch('inside/stacked') |
1430 | - self.make_branch('outside/stacked-on') |
1431 | - scheme, get_chrooted_url = self.get_chrooted_scheme('inside') |
1432 | - Branch.open(get_chrooted_url('stacked')).set_stacked_on_url( |
1433 | - self.get_url('outside/stacked-on')) |
1434 | - self.assertRaises( |
1435 | - BadUrl, safe_open, scheme, get_chrooted_url('stacked')) |
1436 | - |
1437 | - def test_ignore_fallbacks(self): |
1438 | - """"Cross-format stacking doesn't error with ignore_fallbacks.""" |
1439 | - scheme, get_chrooted_url = self.get_chrooted_scheme('inside') |
1440 | - stacked, stacked_on = make_cross_format_stacked(self) |
1441 | - force_stacked_on_url(stacked, get_chrooted_url('stacked-on')) |
1442 | - safe_open(scheme, get_chrooted_url('stacked'), ignore_fallbacks=True) |
1443 | |
1444 | === modified file 'lib/lp/codehosting/upgrade.py' |
1445 | --- lib/lp/codehosting/upgrade.py 2014-01-30 15:04:06 +0000 |
1446 | +++ lib/lp/codehosting/upgrade.py 2019-07-09 12:34:22 +0000 |
1447 | @@ -29,6 +29,10 @@ |
1448 | ) |
1449 | from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2aSubtree |
1450 | from bzrlib.upgrade import upgrade |
1451 | +from bzrlib.url_policy_open import ( |
1452 | + BranchOpener, |
1453 | + SingleSchemePolicy, |
1454 | + ) |
1455 | |
1456 | from lp.code.bzr import ( |
1457 | branch_changed, |
1458 | @@ -36,7 +40,6 @@ |
1459 | ) |
1460 | from lp.code.model.branch import Branch |
1461 | from lp.codehosting.bzrutils import read_locked |
1462 | -from lp.codehosting.safe_open import safe_open |
1463 | from lp.codehosting.vfs.branchfs import get_real_branch_path |
1464 | from lp.services.database.interfaces import IStore |
1465 | |
1466 | @@ -52,9 +55,9 @@ |
1467 | self.branch = branch |
1468 | self.bzr_branch = bzr_branch |
1469 | if self.bzr_branch is None: |
1470 | - self.bzr_branch = safe_open('lp-internal', |
1471 | - self.branch.getInternalBzrUrl(), |
1472 | - ignore_fallbacks=True) |
1473 | + opener = BranchOpener(SingleSchemePolicy('lp-internal')) |
1474 | + self.bzr_branch = opener.open( |
1475 | + self.branch.getInternalBzrUrl(), ignore_fallbacks=True) |
1476 | self.target_dir = target_dir |
1477 | self.target_subdir = os.path.join( |
1478 | self.target_dir, str(self.branch.id)) |
1479 | |
1480 | === modified file 'scripts/code-import-worker.py' |
1481 | --- scripts/code-import-worker.py 2016-11-03 17:31:43 +0000 |
1482 | +++ scripts/code-import-worker.py 2019-07-09 12:34:22 +0000 |
1483 | @@ -21,6 +21,7 @@ |
1484 | import sys |
1485 | |
1486 | from bzrlib.transport import get_transport |
1487 | +from bzrlib.url_policy_open import AcceptAnythingPolicy |
1488 | |
1489 | from lp.codehosting.codeimport.worker import ( |
1490 | BzrImportWorker, |
1491 | @@ -32,7 +33,6 @@ |
1492 | GitImportWorker, |
1493 | GitToGitImportWorker, |
1494 | ) |
1495 | -from lp.codehosting.safe_open import AcceptAnythingPolicy |
1496 | from lp.services import scripts |
1497 | from lp.services.config import config |
1498 | from lp.services.timeout import set_default_timeout_function |