~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/launchpad/__init__.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006 - 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
"""Launchpad.net integration plugin for Bazaar.
18
 
 
19
 
This plugin provides facilities for working with Bazaar branches that are
20
 
hosted on Launchpad (http://launchpad.net).  It provides a directory service 
21
 
for referring to Launchpad branches using the "lp:" prefix.  For example,
22
 
lp:bzr refers to the Bazaar's main development branch and
23
 
lp:~username/project/branch-name can be used to refer to a specific branch.
24
 
 
25
 
This plugin provides a bug tracker so that "bzr commit --fixes lp:1234" will
26
 
record that revision as fixing Launchpad's bug 1234.
27
 
 
28
 
The plugin also provides the following commands:
29
 
 
30
 
    launchpad-login: Show or set the Launchpad user ID
31
 
    launchpad-open: Open a Launchpad branch page in your web browser
32
 
    lp-propose-merge: Propose merging a branch on Launchpad
33
 
    register-branch: Register a branch with launchpad.net
34
 
    launchpad-mirror: Ask Launchpad to mirror a branch now
35
 
 
36
 
"""
37
 
 
38
 
from __future__ import absolute_import
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Launchpad.net integration plugin for Bazaar."""
39
18
 
40
19
# The XMLRPC server address can be overridden by setting the environment
41
 
# variable $BZR_LP_XMLRPC_URL
42
 
 
43
 
# see http://wiki.bazaar.canonical.com/Specs/BranchRegistrationTool
44
 
 
45
 
from bzrlib import (
46
 
    branch as _mod_branch,
47
 
    config as _mod_config,
48
 
    lazy_regex,
49
 
    # Since we are a built-in plugin we share the bzrlib version
50
 
    trace,
51
 
    version_info,
52
 
    )
53
 
from bzrlib.commands import (
54
 
    plugin_cmds,
55
 
    )
 
20
# variable $BZR_LP_XMLRPL_URL
 
21
 
 
22
# see http://bazaar-vcs.org/Specs/BranchRegistrationTool
 
23
 
 
24
from bzrlib.branch import Branch
 
25
from bzrlib.commands import Command, Option, register_command
56
26
from bzrlib.directory_service import directories
 
27
from bzrlib.errors import BzrCommandError, NoPublicBranch, NotBranchError
57
28
from bzrlib.help_topics import topic_registry
58
29
 
59
 
for klsname, aliases in [
60
 
    ("cmd_register_branch", []),
61
 
    ("cmd_launchpad_open", ["lp-open"]),
62
 
    ("cmd_launchpad_login", ["lp-login"]),
63
 
    ("cmd_launchpad_mirror", ["lp-mirror"]),
64
 
    ("cmd_lp_propose_merge", ["lp-submit", "lp-propose"]),
65
 
    ("cmd_lp_find_proposal", [])]:
66
 
    plugin_cmds.register_lazy(klsname, aliases,
67
 
        "bzrlib.plugins.launchpad.cmds")
 
30
 
 
31
class cmd_register_branch(Command):
 
32
    """Register a branch with launchpad.net.
 
33
 
 
34
    This command lists a bzr branch in the directory of branches on
 
35
    launchpad.net.  Registration allows the branch to be associated with
 
36
    bugs or specifications.
 
37
    
 
38
    Before using this command you must register the product to which the
 
39
    branch belongs, and create an account for yourself on launchpad.net.
 
40
 
 
41
    arguments:
 
42
        public_url: The publicly visible url for the branch to register.
 
43
                    This must be an http or https url (which Launchpad can read
 
44
                    from to access the branch). Local file urls, SFTP urls, and
 
45
                    bzr+ssh urls will not work.
 
46
                    If no public_url is provided, bzr will use the configured
 
47
                    public_url if there is one for the current branch, and
 
48
                    otherwise error.
 
49
 
 
50
    example:
 
51
        bzr register-branch http://foo.com/bzr/fooproduct.mine \\
 
52
                --product fooproduct
 
53
    """
 
54
    takes_args = ['public_url?']
 
55
    takes_options = [
 
56
         Option('product',
 
57
                'Launchpad product short name to associate with the branch.',
 
58
                unicode),
 
59
         Option('branch-name',
 
60
                'Short name for the branch; '
 
61
                'by default taken from the last component of the url.',
 
62
                unicode),
 
63
         Option('branch-title',
 
64
                'One-sentence description of the branch.',
 
65
                unicode),
 
66
         Option('branch-description',
 
67
                'Longer description of the purpose or contents of the branch.',
 
68
                unicode),
 
69
         Option('author',
 
70
                "Branch author's email address, if not yourself.",
 
71
                unicode),
 
72
         Option('link-bug',
 
73
                'The bug this branch fixes.',
 
74
                int),
 
75
         Option('dry-run',
 
76
                'Prepare the request but don\'t actually send it.')
 
77
        ]
 
78
 
 
79
 
 
80
    def run(self,
 
81
            public_url=None,
 
82
            product='',
 
83
            branch_name='',
 
84
            branch_title='',
 
85
            branch_description='',
 
86
            author='',
 
87
            link_bug=None,
 
88
            dry_run=False):
 
89
        from bzrlib.plugins.launchpad.lp_registration import (
 
90
            LaunchpadService, BranchRegistrationRequest, BranchBugLinkRequest,
 
91
            DryRunLaunchpadService)
 
92
        if public_url is None:
 
93
            try:
 
94
                b = Branch.open_containing('.')[0]
 
95
            except NotBranchError:
 
96
                raise BzrCommandError('register-branch requires a public '
 
97
                    'branch url - see bzr help register-branch.')
 
98
            public_url = b.get_public_branch()
 
99
            if public_url is None:
 
100
                raise NoPublicBranch(b)
 
101
 
 
102
        rego = BranchRegistrationRequest(branch_url=public_url,
 
103
                                         branch_name=branch_name,
 
104
                                         branch_title=branch_title,
 
105
                                         branch_description=branch_description,
 
106
                                         product_name=product,
 
107
                                         author_email=author,
 
108
                                         )
 
109
        linko = BranchBugLinkRequest(branch_url=public_url,
 
110
                                     bug_id=link_bug)
 
111
        if not dry_run:
 
112
            service = LaunchpadService()
 
113
            # This gives back the xmlrpc url that can be used for future
 
114
            # operations on the branch.  It's not so useful to print to the
 
115
            # user since they can't do anything with it from a web browser; it
 
116
            # might be nice for the server to tell us about an html url as
 
117
            # well.
 
118
        else:
 
119
            # Run on service entirely in memory
 
120
            service = DryRunLaunchpadService()
 
121
        service.gather_user_credentials()
 
122
        branch_object_url = rego.submit(service)
 
123
        if link_bug:
 
124
            link_bug_url = linko.submit(service)
 
125
        print 'Branch registered.'
 
126
 
 
127
register_command(cmd_register_branch)
 
128
 
 
129
 
 
130
class cmd_launchpad_login(Command):
 
131
    """Show or set the Launchpad user ID.
 
132
 
 
133
    When communicating with Launchpad, some commands need to know your
 
134
    Launchpad user ID.  This command can be used to set or show the
 
135
    user ID that Bazaar will use for such communication.
 
136
 
 
137
    :Examples:
 
138
      Show the Launchpad ID of the current user::
 
139
 
 
140
          bzr launchpad-login
 
141
 
 
142
      Set the Launchpad ID of the current user to 'bob'::
 
143
 
 
144
          bzr launchpad-login bob
 
145
    """
 
146
    aliases = ['lp-login']
 
147
    takes_args = ['name?']
 
148
    takes_options = [
 
149
        Option('no-check',
 
150
               "Don't check that the user name is valid."),
 
151
        ]
 
152
 
 
153
    def run(self, name=None, no_check=False):
 
154
        from bzrlib.plugins.launchpad import account
 
155
        check_account = not no_check
 
156
 
 
157
        if name is None:
 
158
            username = account.get_lp_login()
 
159
            if username:
 
160
                if check_account:
 
161
                    account.check_lp_login(username)
 
162
                self.outf.write(username + '\n')
 
163
            else:
 
164
                self.outf.write('No Launchpad user ID configured.\n')
 
165
                return 1
 
166
        else:
 
167
            if check_account:
 
168
                account.check_lp_login(name)
 
169
            account.set_lp_login(name)
 
170
 
 
171
register_command(cmd_launchpad_login)
68
172
 
69
173
 
70
174
def _register_directory():
71
175
    directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
72
176
                              'LaunchpadDirectory',
73
177
                              'Launchpad-based directory service',)
74
 
    directories.register_lazy(
75
 
        'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
76
 
        'LaunchpadDirectory',
77
 
        'debianlp: shortcut')
78
 
    directories.register_lazy(
79
 
        'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
80
 
        'LaunchpadDirectory',
81
 
        'ubuntu: shortcut')
82
 
 
83
178
_register_directory()
84
179
 
85
 
# This is kept in __init__ so that we don't load lp_api_lite unless the branch
86
 
# actually matches. That way we can avoid importing extra dependencies like
87
 
# json.
88
 
_package_branch = lazy_regex.lazy_compile(
89
 
    r'bazaar.launchpad.net.*?/'
90
 
    r'(?P<user>~[^/]+/)?(?P<archive>ubuntu|debian)/(?P<series>[^/]+/)?'
91
 
    r'(?P<project>[^/]+)(?P<branch>/[^/]+)?'
92
 
    )
93
 
 
94
 
def _get_package_branch_info(url):
95
 
    """Determine the packaging information for this URL.
96
 
 
97
 
    :return: If this isn't a packaging branch, return None. If it is, return
98
 
        (archive, series, project)
99
 
    """
100
 
    if url is None:
101
 
        return None
102
 
    m = _package_branch.search(url)
103
 
    if m is None:
104
 
        return None
105
 
    archive, series, project, user = m.group('archive', 'series',
106
 
                                             'project', 'user')
107
 
    if series is not None:
108
 
        # series is optional, so the regex includes the extra '/', we don't
109
 
        # want to send that on (it causes Internal Server Errors.)
110
 
        series = series.strip('/')
111
 
    if user is not None:
112
 
        user = user.strip('~/')
113
 
        if user != 'ubuntu-branches':
114
 
            return None
115
 
    return archive, series, project
116
 
 
117
 
 
118
 
def _check_is_up_to_date(the_branch):
119
 
    info = _get_package_branch_info(the_branch.base)
120
 
    if info is None:
121
 
        return
122
 
    c = the_branch.get_config_stack()
123
 
    verbosity = c.get('launchpad.packaging_verbosity')
124
 
    if not verbosity:
125
 
        trace.mutter('not checking %s because verbosity is turned off'
126
 
                     % (the_branch.base,))
127
 
        return
128
 
    archive, series, project = info
129
 
    from bzrlib.plugins.launchpad import lp_api_lite
130
 
    latest_pub = lp_api_lite.LatestPublication(archive, series, project)
131
 
    lp_api_lite.report_freshness(the_branch, verbosity, latest_pub)
132
 
 
133
 
 
134
 
def _register_hooks():
135
 
    _mod_branch.Branch.hooks.install_named_hook('open',
136
 
        _check_is_up_to_date, 'package-branch-up-to-date')
137
 
 
138
 
 
139
 
_register_hooks()
140
 
 
141
 
def load_tests(basic_tests, module, loader):
142
 
    testmod_names = [
143
 
        'test_account',
144
 
        'test_register',
145
 
        'test_lp_api',
146
 
        'test_lp_api_lite',
147
 
        'test_lp_directory',
148
 
        'test_lp_login',
149
 
        'test_lp_open',
150
 
        'test_lp_service',
151
 
        ]
152
 
    basic_tests.addTest(loader.loadTestsFromModuleNames(
153
 
            ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
154
 
    return basic_tests
155
 
 
 
180
 
 
181
def test_suite():
 
182
    """Called by bzrlib to fetch tests for this plugin"""
 
183
    from unittest import TestSuite, TestLoader
 
184
    from bzrlib.plugins.launchpad import (
 
185
         test_account, test_lp_directory, test_lp_service, test_register,
 
186
         )
 
187
 
 
188
    loader = TestLoader()
 
189
    suite = TestSuite()
 
190
    for module in [
 
191
        test_account,
 
192
        test_register,
 
193
        test_lp_directory,
 
194
        test_lp_service,
 
195
        ]:
 
196
        suite.addTests(loader.loadTestsFromModule(module))
 
197
    return suite
156
198
 
157
199
_launchpad_help = """Integration with Launchpad.net
158
200
 
166
208
      is then used by the 'lp:' transport to download your branches using
167
209
      bzr+ssh://.
168
210
 
169
 
    * The 'lp:' transport uses Launchpad as a directory service: for example
170
 
      'lp:bzr' and 'lp:python' refer to the main branches of the relevant
171
 
      projects and may be branched, logged, etc. You can also use the 'lp:'
172
 
      transport to refer to specific branches, e.g. lp:~bzr/bzr/trunk.
173
 
 
174
 
    * The 'lp:' bug tracker alias can expand launchpad bug numbers to their
175
 
      URLs for use with 'bzr commit --fixes', e.g. 'bzr commit --fixes lp:12345'
176
 
      will record a revision property that marks that revision as fixing
177
 
      Launchpad bug 12345. When you push that branch to Launchpad it will
178
 
      automatically be linked to the bug report.
179
 
 
180
211
    * The register-branch command tells Launchpad about the url of a
181
212
      public branch.  Launchpad will then mirror the branch, display
182
213
      its contents and allow it to be attached to bugs and other
183
214
      objects.
184
215
 
 
216
    * The 'lp:' transport uses Launchpad as a directory service: for example
 
217
      'lp:bzr' and 'lp:python' refer to the main branches of the relevant
 
218
      projects and may be branched, logged, etc. You can also use the 'lp:'
 
219
      transport to refer to specific branches, e.g. lp:///~bzr/bzr/trunk.
 
220
 
185
221
For more information see http://help.launchpad.net/
186
222
"""
187
223
topic_registry.register('launchpad',
188
224
    _launchpad_help,
189
225
    'Using Bazaar with Launchpad.net')
190
 
 
191
 
_mod_config.option_registry.register(
192
 
    _mod_config.Option('launchpad.packaging_verbosity', default=True,
193
 
          from_unicode=_mod_config.bool_from_store,
194
 
          help="""\
195
 
Whether to warn if a UDD package import branch is accessed that is out of date.
196
 
 
197
 
Setting this option to 'off' will disable verbosity.
198
 
"""))
199
 
_mod_config.option_registry.register(
200
 
    _mod_config.Option('launchpad_username', default=None,
201
 
        help="The username to login with when conneting to Launchpad."))