def setUp(self): TestCaseWithRepository.setUp(self) # make_bzrdir relies on this being a relative filesystem path. self._source_branch_path = 'source-branch' SafeBranchOpener.install_hook() self.worker = self.makePullerWorker( self.get_url(self._source_branch_path), self.get_url('dest-path'))
def _doImport(self): self._logger.info("Starting job.") saved_factory = bzrlib.ui.ui_factory opener = SafeBranchOpener(self._opener_policy, self.probers) bzrlib.ui.ui_factory = LoggingUIFactory(logger=self._logger) try: self._logger.info( "Getting exising bzr branch from central store.") bazaar_branch = self.getBazaarBranch() try: remote_branch = opener.open(self.source_details.url) except TooManyRedirections: self._logger.info("Too many redirections.") return CodeImportWorkerExitCode.FAILURE_INVALID except NotBranchError: self._logger.info("No branch found at remote location.") return CodeImportWorkerExitCode.FAILURE_INVALID except BadUrl as e: self._logger.info("Invalid URL: %s" % e) return CodeImportWorkerExitCode.FAILURE_FORBIDDEN except ConnectionError as e: self._logger.info("Unable to open remote branch: %s" % e) return CodeImportWorkerExitCode.FAILURE_INVALID try: remote_branch_tip = remote_branch.last_revision() inter_branch = InterBranch.get(remote_branch, bazaar_branch) self._logger.info("Importing branch.") revision_limit = self.getRevisionLimit() inter_branch.fetch(limit=revision_limit) if bazaar_branch.repository.has_revision(remote_branch_tip): pull_result = inter_branch.pull(overwrite=True) if pull_result.old_revid != pull_result.new_revid: result = CodeImportWorkerExitCode.SUCCESS else: result = CodeImportWorkerExitCode.SUCCESS_NOCHANGE else: result = CodeImportWorkerExitCode.SUCCESS_PARTIAL except Exception as e: if e.__class__ in self.unsupported_feature_exceptions: self._logger.info( "Unable to import branch because of limitations in " "Bazaar.") self._logger.info(str(e)) return ( CodeImportWorkerExitCode.FAILURE_UNSUPPORTED_FEATURE) elif e.__class__ in self.invalid_branch_exceptions: self._logger.info("Branch invalid: %s", str(e)) return CodeImportWorkerExitCode.FAILURE_INVALID elif e.__class__ in self.broken_remote_exceptions: self._logger.info("Remote branch broken: %s", str(e)) return CodeImportWorkerExitCode.FAILURE_REMOTE_BROKEN else: raise self._logger.info("Pushing local import branch to central store.") self.pushBazaarBranch(bazaar_branch) self._logger.info("Job complete.") return result finally: bzrlib.ui.ui_factory = saved_factory
def setUp(self): super(BzrSyncTestCase, self).setUp() SafeBranchOpener.install_hook() self.disable_directory_isolation() self.useBzrBranches(direct_database=True) self.makeFixtures() switch_dbuser("branchscanner") # Catch both constraints and permissions for the db user. self.addCleanup(Store.of(self.db_branch).flush)
def __init__(self, policy, protocol=None, log=None): """Construct a branch opener with 'policy'. :param policy: A `BranchOpenPolicy` that tells us what URLs are valid and similar things. :param log: A callable which can be called with a format string and arguments to log messages in the scheduler, or None, in which case log messages are discarded. """ self.policy = policy self.protocol = protocol self.opener = SafeBranchOpener(policy) if log is not None: self.log = log else: self.log = lambda *args: None
def setUp(self): super(TestSafeBranchOpenerCheckAndFollowBranchReference, self).setUp() SafeBranchOpener.install_hook()
def setUp(self): super(TestSafeOpen, self).setUp() SafeBranchOpener.install_hook()
class BranchMirrorer(object): """A `BranchMirrorer` safely makes mirrors of branches. A `BranchMirrorer` has a `BranchOpenPolicy` to tell it which URLs are safe to accesss and whether or not to follow branch references. The mirrorer knows how to follow branch references, create new mirrors, update existing mirrors, determine stacked-on branches and the like. Public methods are `open` and `mirror`. """ def __init__(self, policy, protocol=None, log=None): """Construct a branch opener with 'policy'. :param policy: A `BranchOpenPolicy` that tells us what URLs are valid and similar things. :param log: A callable which can be called with a format string and arguments to log messages in the scheduler, or None, in which case log messages are discarded. """ self.policy = policy self.protocol = protocol self.opener = SafeBranchOpener(policy) if log is not None: self.log = log else: self.log = lambda *args: None def createDestinationBranch(self, source_branch, destination_url): """Create a destination branch for 'source_branch'. Creates a branch at 'destination_url' that is a mirror of 'source_branch'. Any content already at 'destination_url' will be deleted. :param source_branch: The Bazaar branch that will be mirrored. :param destination_url: The place to make the destination branch. This URL must point to a writable location. :return: The destination branch. """ return self.opener.runWithTransformFallbackLocationHookInstalled( self.policy.createDestinationBranch, source_branch, destination_url) def openDestinationBranch(self, source_branch, destination_url): """Open or create the destination branch at 'destination_url'. :param source_branch: The Bazaar branch that will be mirrored. :param destination_url: The place to make the destination branch. This URL must point to a writable location. :return: The opened or created branch. """ try: branch = Branch.open(destination_url) except (errors.NotBranchError, errors.IncompatibleRepositories): # Make a new branch in the same format as the source branch. return self.createDestinationBranch( source_branch, destination_url) # Check that destination branch is in the same format as the source. if identical_formats(source_branch, branch): return branch self.log('Formats differ.') return self.createDestinationBranch(source_branch, destination_url) def updateBranch(self, source_branch, dest_branch): """Bring 'dest_branch' up-to-date with 'source_branch'. This method pulls 'source_branch' into 'dest_branch' and sets the stacked-on URL of 'dest_branch' to match 'source_branch'. This method assumes that 'source_branch' and 'dest_branch' both have the same format. """ stacked_on_url = self.policy.getStackedOnURLForDestinationBranch( source_branch, dest_branch.base) try: dest_branch.set_stacked_on_url(stacked_on_url) except (errors.UnstackableRepositoryFormat, errors.UnstackableBranchFormat, errors.IncompatibleRepositories): stacked_on_url = None if stacked_on_url is None: # We use stacked_on_url == '' to mean "no stacked on location" # because XML-RPC doesn't support None. stacked_on_url = '' dest_branch.pull(source_branch, overwrite=True) return stacked_on_url def mirror(self, source_branch, destination_url): """Mirror 'source_branch' to 'destination_url'.""" branch = self.openDestinationBranch(source_branch, destination_url) revid_before = branch.last_revision() # If the branch is locked, try to break it. Our special UI factory # will allow the breaking of locks that look like they were left # over from previous puller worker runs. We will block on other # locks and fail if they are not broken before the timeout expires # (currently 5 minutes). if branch.get_physical_lock_status(): branch.break_lock() stacked_on_url = self.updateBranch(source_branch, branch) return branch, revid_before, stacked_on_url def open(self, url): return self.opener.open(url)
def makeBranchOpener(self, allowed_urls, probers=None): policy = WhitelistPolicy(True, allowed_urls, True) return SafeBranchOpener(policy, probers)