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

Proposed by Curtis Hovey on 2012-08-16
Status: Merged
Approved by: j.c.sackett on 2012-08-16
Approved revision: no longer in the source branch.
Merged at revision: 15820
Proposed branch: lp:~sinzui/launchpad/change_branch-info-type
Merge into: lp:launchpad
Diff against target: 60 lines (+28/-0)
2 files modified
lib/lp/code/interfaces/branch.py (+7/-0)
lib/lp/code/model/tests/test_branch.py (+21/-0)
To merge this branch: bzr merge lp:~sinzui/launchpad/change_branch-info-type
Reviewer Review Type Date Requested Status
j.c.sackett (community) 2012-08-16 Approve on 2012-08-16
Review via email: mp+120011@code.launchpad.net

Commit Message

Export IBranch.transitionToInformationType over the API.

Description of the Change

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

To post a comment you must log in.
j.c.sackett (jcsackett) wrote :

This looks good. Thanks, Curtis.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/interfaces/branch.py'
2--- lib/lp/code/interfaces/branch.py 2012-07-16 11:09:06 +0000
3+++ lib/lp/code/interfaces/branch.py 2012-08-16 20:28:19 +0000
4@@ -53,6 +53,7 @@
5 Reference,
6 ReferenceChoice,
7 )
8+from lazr.restful.interface import copy_field
9 from zope.component import getUtility
10 from zope.interface import (
11 Attribute,
12@@ -1131,6 +1132,12 @@
13 :raise: CannotDeleteBranch if the branch cannot be deleted.
14 """
15
16+ @operation_parameters(
17+ information_type=copy_field(IBranchPublic['information_type']),
18+ )
19+ @call_with(who=REQUEST_USER, verify_policy=True)
20+ @export_write_operation()
21+ @operation_for_version("devel")
22 def transitionToInformationType(information_type, who,
23 verify_policy=True):
24 """Set the information type for this branch.
25
26=== modified file 'lib/lp/code/model/tests/test_branch.py'
27--- lib/lp/code/model/tests/test_branch.py 2012-08-13 21:33:47 +0000
28+++ lib/lp/code/model/tests/test_branch.py 2012-08-16 20:28:19 +0000
29@@ -113,6 +113,7 @@
30 from lp.codehosting.safe_open import BadUrl
31 from lp.codehosting.vfs.branchfs import get_real_branch_path
32 from lp.registry.enums import (
33+ BranchSharingPolicy,
34 InformationType,
35 PersonVisibility,
36 PRIVATE_INFORMATION_TYPES,
37@@ -3231,3 +3232,23 @@
38
39 branch2 = ws_object(launchpad, db_branch)
40 self.assertEqual(branch2.merge_queue_config, configuration)
41+
42+ def test_transitionToInformationType(self):
43+ """Test transitionToInformationType() API arguments."""
44+ product = self.factory.makeProduct()
45+ self.factory.makeCommercialSubscription(product)
46+ with celebrity_logged_in('commercial_admin') as admin:
47+ # XXX sinzui 2012-08-16: setBranchSharingPolicy() is guarded
48+ # at this moment.
49+ product.setBranchSharingPolicy(
50+ BranchSharingPolicy.PUBLIC_OR_PROPRIETARY, admin)
51+ with person_logged_in(product.owner):
52+ db_branch = self.factory.makeBranch(product=product)
53+ launchpad = launchpadlib_for('test', db_branch.owner,
54+ service_root=self.layer.appserver_root_url('api'))
55+
56+ branch = ws_object(launchpad, db_branch)
57+ branch.transitionToInformationType(information_type='Proprietary')
58+
59+ updated_branch = ws_object(launchpad, db_branch)
60+ self.assertEqual('Proprietary', updated_branch.information_type)