288
292
get_vfs_format_classes(branch_two))
295
checked_open_data = threading.local()
298
def _install_checked_open_hook():
299
"""Install `_checked_open_pre_open_hook` as a ``pre_open`` hook.
301
This is done at module import time, but _checked_open_pre_open_hook
302
doesn't do anything unless the `checked_open_data` threading.Local object
303
has a 'checked_opener' attribute in this thread.
305
This is in a module-level function rather than performed at module level
306
so that it can be called in setUp for testing `checked_open` as
307
bzrlib.tests.TestCase.setUp clears hooks.
309
BzrDir.hooks.install_named_hook(
310
'pre_open', _checked_open_pre_open_hook, 'safe open')
313
def _checked_open_pre_open_hook(transport):
314
"""If a checked_open validate function is present in this thread, call it.
316
if not getattr(checked_open_data, 'validate', False):
318
checked_open_data.validate(transport.base)
321
_install_checked_open_hook()
324
def checked_open(validation_function, url, possible_transports=None):
325
"""Open a branch, calling `validation_function` with any URL thus found.
327
This is intended to be used to open a branch ensuring that it's not
328
stacked or a reference to something unexpected.
330
if hasattr(checked_open_data, 'validate'):
331
raise AssertionError("checked_open called recursively")
332
checked_open_data.validate = validation_function
334
return Branch.open(url, possible_transports=possible_transports)
336
del checked_open_data.validate
339
class UnsafeUrlSeen(Exception):
340
"""`safe_open` found a URL that was not on the configured scheme."""
343
def makeURLChecker(allowed_scheme):
344
"""Make a callable that rejects URLs not on the given scheme."""
347
"""Check that `url` is safe to open."""
348
if URI(url).scheme != allowed_scheme:
350
"Attempt to open %r which is not a %s URL" % (
351
url, allowed_scheme))
355
def safe_open(allowed_scheme, url, possible_transports=None):
356
"""Open the branch at `url`, only accessing URLs on `allowed_scheme`.
358
:raises UnsafeUrlSeen: An attempt was made to open a URL that was not on
362
makeURLChecker(allowed_scheme), url, possible_transports)
291
365
def get_stacked_on_url(branch):
292
366
"""Get the stacked-on URL for 'branch', or `None` if not stacked."""