def _getBranchNamespaceExtras(self, path, requester): """Get the branch namespace, branch name and callback for the path. If the path defines a full branch path including the owner and branch name, then the namespace that is returned is the namespace for the owner and the branch target specified. If the path uses an lp short name, then we only allow the requester to create a branch if they have permission to link the newly created branch to the short name target. If there is an existing branch already linked, then BranchExists is raised. The branch name that is used is determined by the namespace as the first unused name starting with 'trunk'. """ if path.startswith(BRANCH_ALIAS_PREFIX + '/'): path = path[len(BRANCH_ALIAS_PREFIX) + 1:] if not path.startswith('~'): context = getUtility(ILinkedBranchTraverser).traverse(path) target = IBranchTarget(context) namespace = target.getNamespace(requester) branch_name = namespace.findUnusedName('trunk') def link_func(new_branch): link = ICanHasLinkedBranch(context) link.setBranch(new_branch, requester) return namespace, branch_name, link_func, path namespace_name, branch_name = split_unique_name(path) namespace = lookup_branch_namespace(namespace_name) return namespace, branch_name, None, path
def _makeDefaultStackedOnBranch(self, private=False): """Make a default stacked-on branch. This creates a database product branch, makes it the default stacked-on branch for its product and creates a Bazaar branch for it. :param private: Whether the created branch should be private or not (defaults to not). :return: `IBranch`. """ # Make the branch in the database. product = self.factory.makeProduct() if private: information_type = InformationType.USERDATA else: information_type = InformationType.PUBLIC default_branch = self.factory.makeProductBranch( product=product, information_type=information_type) transaction.commit() # Create the underlying bzr branch. lp_server = self.getLPServerForUser(default_branch.owner) BzrDir.create_branch_convenience( lp_server.get_url() + default_branch.unique_name) transaction.commit() # Make it the default stacked-on branch for the product. series = removeSecurityProxy(product.development_focus) series.branch = default_branch self.assertEqual( default_branch, IBranchTarget(product).default_stacked_on_branch) return default_branch
def test_productseries_adapter(self): # Adapting a product series will make a product branch target. product = self.factory.makeProduct() series = self.factory.makeProductSeries(product) target = IBranchTarget(series) self.assertIsInstance(target, ProductBranchTarget) self.assertEqual([product], target.components)
def test_default_stacked_on_branch_unmirrored_dev_focus(self): # If the development focus hasn't been mirrored, then don't use it as # the default stacked-on branch. branch = self.factory.makeProductBranch(product=self.original) self._setDevelopmentFocus(self.original, branch) target = IBranchTarget(self.original) self.assertIs(None, target.default_stacked_on_branch)
def test_default_stacked_on_branch_has_been_mirrored(self): # If the development focus has been mirrored, then use it as the # default stacked-on branch. branch = self.factory.makeProductBranch(product=self.original) self._setDevelopmentFocus(self.original, branch) removeSecurityProxy(branch).branchChanged('', 'rev1', None, None, None) target = IBranchTarget(self.original) self.assertEqual(branch, target.default_stacked_on_branch)
def target(self): if self.product is None: if self.distroseries is None: target = self.owner else: target = self.sourcepackage else: target = self.product return IBranchTarget(target)
def test_get_stacking_policy(self): # A stacking policy control file is served underneath product # directories for products that have a default stacked-on branch. product = self.factory.makeProduct() self.factory.enableDefaultStackingForProduct(product) transport = self.getTransport() control_file = transport.get_bytes('~%s/%s/.bzr/control.conf' % (self.requester.name, product.name)) stacked_on = IBranchTarget(product).default_stacked_on_branch self.assertEqual('default_stack_on = %s' % branch_id_alias(stacked_on), control_file.strip())
def test_distrosourcepackage_adapter(self): # Adapting a distrosourcepackage will make a branch target with the # current series of the distro as the distroseries. distro = self.original.distribution distro_sourcepackage = distro.getSourcePackage( self.original.sourcepackagename) target = IBranchTarget(distro_sourcepackage) self.assertIsInstance(target, PackageBranchTarget) self.assertEqual([distro, distro.currentseries], target.components[:2]) self.assertEqual(self.original.sourcepackagename, target.components[2].sourcepackagename)
def setRenderedValue(self, value): """See IWidget.""" self.setUpSubWidgets() if IBranchTarget.providedBy(value): if IProduct.providedBy(value.context): self.default_option = 'product' self.product_widget.setRenderedValue(value.context) return elif IPerson.providedBy(value.context): self.default_option = 'personal' return else: raise AssertionError('Not a valid value: %r' % value)
def update_action(self, action, data): branch_type = data.get('branch_type') if branch_type == LINK_LP_BZR: branch_location = data.get('branch_location') if branch_location != self.context.branch: self.context.branch = branch_location # Request an initial upload of translation files. getUtility(IRosettaUploadJobSource).create( self.context.branch, NULL_REVISION) else: self.context.branch = branch_location self.request.response.addInfoNotification( 'Series code location updated.') else: branch_name = data.get('branch_name') branch_owner = data.get('branch_owner') if branch_type == IMPORT_EXTERNAL: rcs_type = data.get('rcs_type') if rcs_type == RevisionControlSystems.CVS: cvs_root = data.get('repo_url') cvs_module = data.get('cvs_module') url = None else: cvs_root = None cvs_module = None url = data.get('repo_url') rcs_item = RevisionControlSystems.items[rcs_type.name] try: code_import = getUtility(ICodeImportSet).new( owner=branch_owner, registrant=self.user, target=IBranchTarget(self.context.product), branch_name=branch_name, rcs_type=rcs_item, url=url, cvs_root=cvs_root, cvs_module=cvs_module) except BranchExists as e: self._setBranchExists(e.existing_branch, 'branch_name') self.errors_in_action = True # Abort transaction. This is normally handled # by LaunchpadFormView, but we are already in # the success handler. self._abort() return self.context.branch = code_import.branch self.request.response.addInfoNotification( 'Code import created and branch linked to the series.') else: raise UnexpectedFormData(branch_type)
def _create_import(self, data, status): """Create the code import.""" product = self.getProduct(data) cvs_root, cvs_module, url = self._getImportLocation(data) return getUtility(ICodeImportSet).new( registrant=self.user, owner=data['owner'], target=IBranchTarget(product), branch_name=data['branch_name'], rcs_type=data['rcs_type'], url=url, cvs_root=cvs_root, cvs_module=cvs_module, review_status=status)
def test_default_stacked_on_branch(self): # The default stacked-on branch for a source package is the branch # linked to the release pocket of the current series of that package. target = IBranchTarget(self.original) development_package = self.original.development_version default_branch = self.factory.makePackageBranch( sourcepackage=development_package) removeSecurityProxy(default_branch).branchChanged( '', self.factory.getUniqueString(), None, None, None) registrant = development_package.distribution.owner with person_logged_in(registrant): development_package.setBranch(PackagePublishingPocket.RELEASE, default_branch, registrant) self.assertEqual(default_branch, target.default_stacked_on_branch)
def newCodeImport(self, registrant=None, branch_name=None, rcs_type=None, url=None, cvs_root=None, cvs_module=None, owner=None): """See `IHasCodeImports`.""" return IBranchTarget(self).newCodeImport(registrant, branch_name, rcs_type, url=url, cvs_root=cvs_root, cvs_module=cvs_module, owner=owner)
def _serializeControlDirectory(self, requester, lookup): trailing_path = lookup['trailing'].lstrip('/') if not ('.bzr' == trailing_path or trailing_path.startswith('.bzr/')): return target = self._get_product_target(lookup['control_name']) if target is None: target = self._get_package_target(lookup['control_name']) if target is None: return default_branch = IBranchTarget(target).default_stacked_on_branch if default_branch is None: return if not self._canRead(requester, default_branch): return path = branch_id_alias(default_branch) return (CONTROL_TRANSPORT, { 'default_stack_on': escape(path) }, trailing_path)
def target(self): """The branch target for the context.""" return IBranchTarget(self.context.product)
def related_package_branch_info(self): branch_to_check = self.getBranch() if IBranch.providedBy(branch_to_check): branch_target = IBranchTarget(branch_to_check.target) return branch_target.getRelatedPackageBranchInfo(branch_to_check, limit_results=5)
def test_adapter(self): target = IBranchTarget(self.original) self.assertIsInstance(target, PackageBranchTarget)
def test_displayname(self): # The display name of a product branch target is the display name of # the product. target = IBranchTarget(self.original) self.assertEqual(self.original.displayname, target.displayname)
def target(self): """See `IBranchNamespace`.""" return IBranchTarget(self.owner)
def target(self): """See `IBranchNamespace`.""" return IBranchTarget(self.product)
def related_package_branch_info(self): branch_to_check = self.getBranch() return IBranchTarget( branch_to_check.target).getRelatedPackageBranchInfo( branch_to_check, limit_results=5)
def test_components(self): target = IBranchTarget(self.original) self.assertEqual([self.original], list(target.components))
def target(self): """See `IBranchNamespace`.""" return IBranchTarget(self.sourcepackage)
def test_displayname(self): # The display name of a person branch target is ~$USER/+junk. target = IBranchTarget(self.original) self.assertEqual('~%s/+junk' % self.original.name, target.displayname)
def test_default_stacked_on_branch(self): # Junk branches are not stacked by default, ever. target = IBranchTarget(self.original) self.assertIs(None, target.default_stacked_on_branch)
def test_displayname(self): # The display name of a source package target is the display name of # the source package. target = IBranchTarget(self.original) self.assertEqual(self.original.displayname, target.displayname)
def related_series_branch_info(self): branch_to_check = self.getBranch() return IBranchTarget( branch_to_check.target).getRelatedSeriesBranchInfo(branch_to_check, limit_results=5)
def test_default_stacked_on_branch_no_dev_focus(self): # The default stacked-on branch for a product target that has no # development focus is None. target = IBranchTarget(self.original) self.assertIs(None, target.default_stacked_on_branch)
def test_components(self): target = IBranchTarget(self.original) self.assertEqual([ self.original.distribution, self.original.distroseries, self.original ], list(target.components))
def new(self, registrant, context, branch_name, rcs_type, target_rcs_type, url=None, cvs_root=None, cvs_module=None, review_status=None, owner=None): """See `ICodeImportSet`.""" if rcs_type == RevisionControlSystems.CVS: assert cvs_root is not None and cvs_module is not None assert url is None elif rcs_type in NON_CVS_RCS_TYPES: assert cvs_root is None and cvs_module is None assert url is not None else: raise AssertionError( "Don't know how to sanity check source details for unknown " "rcs_type %s" % rcs_type) if owner is None: owner = registrant if target_rcs_type == TargetRevisionControlSystems.BZR: # XXX cjwatson 2016-10-15: Testing # IHasBranches.providedBy(context) would seem more in line with # the Git case, but for some reason ProductSeries doesn't # provide that. We should sync this up somehow. try: target = IBranchTarget(context) except TypeError: raise CodeImportInvalidTargetType(context, target_rcs_type) namespace = target.getNamespace(owner) elif target_rcs_type == TargetRevisionControlSystems.GIT: if not IHasGitRepositories.providedBy(context): raise CodeImportInvalidTargetType(context, target_rcs_type) if rcs_type != RevisionControlSystems.GIT: raise AssertionError( "Can't import rcs_type %s into a Git repository" % rcs_type) target = namespace = get_git_namespace(context, owner) else: raise AssertionError("Can't import to target_rcs_type %s" % target_rcs_type) if review_status is None: # Auto approve imports. review_status = CodeImportReviewStatus.REVIEWED if not target.supports_code_imports: raise AssertionError("%r doesn't support code imports" % target) # Create the branch for the CodeImport. if target_rcs_type == TargetRevisionControlSystems.BZR: import_target = namespace.createBranch( branch_type=BranchType.IMPORTED, name=branch_name, registrant=registrant) else: import_target = namespace.createRepository( repository_type=GitRepositoryType.IMPORTED, name=branch_name, registrant=registrant) hosting_path = import_target.getInternalPath() getUtility(IGitHostingClient).create(hosting_path) code_import = CodeImport(registrant=registrant, owner=owner, target=import_target, rcs_type=rcs_type, url=url, cvs_root=cvs_root, cvs_module=cvs_module, review_status=review_status) getUtility(ICodeImportEventSet).newCreate(code_import, registrant) notify(ObjectCreatedEvent(code_import)) # If created in the reviewed state, create a job. if review_status == CodeImportReviewStatus.REVIEWED: CodeImportJobWorkflow().newJob(code_import) return code_import