← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/change_branch-info-type into lp:launchpad

 

Curtis Hovey has proposed merging lp:~sinzui/launchpad/change_branch-info-type into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1037730 in Launchpad itself: "API does not support changing branch.information_type"
  https://bugs.launchpad.net/launchpad/+bug/1037730

For more details, see:
https://code.launchpad.net/~sinzui/launchpad/change_branch-info-type/+merge/120011

It is not possible to change branch information types over the API to
match permitted types in the project's branch_sharing_policy. It is
not possible to for projects to migrate their branches to match
the policy.

--------------------------------------------------------------------

RULES

    Pre-implementation: no one
    * Export IBranch.transitionToInformationType following the pattern
      established by IBug.transitionToInformationType.


QA

    * Visit https://code.qastaging.launchpad.net/lp-dev-utils
    * Verify the private branches say they are Private.
    * Run this example script
    * Verify the private branches are now Proprietary.

{{{

#!/usr/bin/python

from optparse import OptionParser
import logging
import sys

from launchpadlib.launchpad import Launchpad

SCRIPT_NAME = 'migrate-lp-projects'

logging.basicConfig()
log = logging.getLogger(SCRIPT_NAME)
log.setLevel(logging.INFO)


class LpProjectMigrator(object):
    """Migrate a ~launchpad project to use sharing."""

    def __init__(self, lp, service, project, trusted_teams):
        self.lp = lp
        self.service = service
        self.project = project
        self.trusted_teams = trusted_teams

    def migrate(self):
        self.change_sharing_polcies()
        self.share_with_trusted_teams()
        self.change_private_branches_to_proprietary()

    def change_sharing_polcies(self):
        log.info(
            'Setting %s Bugs Sharing Policy to Public, can be proprietary.',
            self.project.name)
        log.info(
            'Setting %s Branch Sharing Policy to Public, can be proprietary.',
            self.project.name)
        self.project.bug_sharing_policy = "Public, can be proprietary"
        self.project.branch_sharing_policy = "Public, can be proprietary"
        self.project.lp_save()

    def share_with_trusted_teams(self):
        permissions = {
            'Private': 'All', 'Private Security': 'All', 'Proprietary': 'All'}
        for team in self.trusted_teams:
            log.info(
                'Sharing Private, Private Security, and Proprietary with %s.',
                team.name)
            self.service.sharePillarInformation(
                pillar=self.project, grantee=team, permissions=permissions)

    def change_private_branches_to_proprietary(self):
        statuses = [
            'Experimental', 'Development', 'Mature', 'Merged', 'Abandoned']
        for branch in self.project.getBranches(status=statuses):
            if branch.information_type == 'Private':
                log.info(
                    'Changing %s information type to Proprietary',
                    branch.unique_name)
                branch.transitionToInformationType(
                    information_type='Proprietary')


def get_trusted_teams(lp):
    log.info('Getting trusted teams.')
    return [
        lp.people['launchpad'],
        lp.people['canonical'],
        ]


def get_pmteam_projects(lp):
    log.info('Getting launchpad projects.')
    return [lp.projects['lp-dev-utils']]


def get_option_parser():
    """Return the option parser for this program."""
    usage = "usage: %%prog [options] \n"
    parser = OptionParser(usage=usage)
    parser.add_option(
        "-e", "--environment", dest="env",
        help="The environment to use")
    parser.set_defaults(
        env='https://api.qastaging.launchpad.net',
        test=True)
    return parser


def main(argv):
    parser = get_option_parser()
    (options, args_) = parser.parse_args(args=argv[1:])
    lp = Launchpad.login_with(
        SCRIPT_NAME, service_root=options.env, version='devel')
    service = lp.load('/+services/sharing')
    trusted_teams = get_trusted_teams(lp)
    for project in get_pmteam_projects(lp):
        migrator = LpProjectMigrator(lp, service, project, trusted_teams)
        migrator.migrate()


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

}}}


LINT

    lib/lp/code/interfaces/branch.py
    lib/lp/code/model/tests/test_branch.py


TEST

    ./bin/test -vvc -t TestWebservice lp.code.model.tests.test_branch


IMPLEMENTATION

Exported the interface to only require the information type kwarg.
    lib/lp/code/interfaces/branch.py
    lib/lp/code/model/tests/test_branch.py
-- 
https://code.launchpad.net/~sinzui/launchpad/change_branch-info-type/+merge/120011
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/change_branch-info-type into lp:launchpad.
=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py	2012-07-16 11:09:06 +0000
+++ lib/lp/code/interfaces/branch.py	2012-08-16 20:28:19 +0000
@@ -53,6 +53,7 @@
     Reference,
     ReferenceChoice,
     )
+from lazr.restful.interface import copy_field
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -1131,6 +1132,12 @@
         :raise: CannotDeleteBranch if the branch cannot be deleted.
         """
 
+    @operation_parameters(
+        information_type=copy_field(IBranchPublic['information_type']),
+        )
+    @call_with(who=REQUEST_USER, verify_policy=True)
+    @export_write_operation()
+    @operation_for_version("devel")
     def transitionToInformationType(information_type, who,
                                     verify_policy=True):
         """Set the information type for this branch.

=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py	2012-08-13 21:33:47 +0000
+++ lib/lp/code/model/tests/test_branch.py	2012-08-16 20:28:19 +0000
@@ -113,6 +113,7 @@
 from lp.codehosting.safe_open import BadUrl
 from lp.codehosting.vfs.branchfs import get_real_branch_path
 from lp.registry.enums import (
+    BranchSharingPolicy,
     InformationType,
     PersonVisibility,
     PRIVATE_INFORMATION_TYPES,
@@ -3231,3 +3232,23 @@
 
         branch2 = ws_object(launchpad, db_branch)
         self.assertEqual(branch2.merge_queue_config, configuration)
+
+    def test_transitionToInformationType(self):
+        """Test transitionToInformationType() API arguments."""
+        product = self.factory.makeProduct()
+        self.factory.makeCommercialSubscription(product)
+        with celebrity_logged_in('commercial_admin') as admin:
+            # XXX sinzui 2012-08-16: setBranchSharingPolicy() is guarded
+            # at this moment.
+            product.setBranchSharingPolicy(
+                BranchSharingPolicy.PUBLIC_OR_PROPRIETARY, admin)
+        with person_logged_in(product.owner):
+            db_branch = self.factory.makeBranch(product=product)
+            launchpad = launchpadlib_for('test', db_branch.owner,
+                service_root=self.layer.appserver_root_url('api'))
+
+        branch = ws_object(launchpad, db_branch)
+        branch.transitionToInformationType(information_type='Proprietary')
+
+        updated_branch = ws_object(launchpad, db_branch)
+        self.assertEqual('Proprietary', updated_branch.information_type)


Follow ups