示例#1
0
    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
示例#2
0
    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
示例#3
0
    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
示例#4
0
 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)
示例#5
0
 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)
示例#6
0
 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)
示例#7
0
 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)
示例#8
0
 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())
示例#9
0
 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)
示例#10
0
 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)
示例#11
0
 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)
示例#12
0
    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)
示例#13
0
 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)
示例#14
0
 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)
示例#15
0
 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)
示例#16
0
 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)
示例#17
0
 def target(self):
     """The branch target for the context."""
     return IBranchTarget(self.context.product)
示例#18
0
 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)
示例#19
0
 def test_adapter(self):
     target = IBranchTarget(self.original)
     self.assertIsInstance(target, PackageBranchTarget)
示例#20
0
 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)
示例#21
0
 def target(self):
     """See `IBranchNamespace`."""
     return IBranchTarget(self.owner)
示例#22
0
 def target(self):
     """See `IBranchNamespace`."""
     return IBranchTarget(self.product)
示例#23
0
 def related_package_branch_info(self):
     branch_to_check = self.getBranch()
     return IBranchTarget(
         branch_to_check.target).getRelatedPackageBranchInfo(
             branch_to_check, limit_results=5)
示例#24
0
 def test_components(self):
     target = IBranchTarget(self.original)
     self.assertEqual([self.original], list(target.components))
示例#25
0
 def target(self):
     """See `IBranchNamespace`."""
     return IBranchTarget(self.sourcepackage)
示例#26
0
 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)
示例#27
0
 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)
示例#28
0
 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)
示例#29
0
 def related_series_branch_info(self):
     branch_to_check = self.getBranch()
     return IBranchTarget(
         branch_to_check.target).getRelatedSeriesBranchInfo(branch_to_check,
                                                            limit_results=5)
示例#30
0
 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)
示例#31
0
 def test_components(self):
     target = IBranchTarget(self.original)
     self.assertEqual([
         self.original.distribution, self.original.distroseries,
         self.original
     ], list(target.components))
示例#32
0
    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