~bzr-pqm/bzr/bzr.dev

5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2006-2011 Canonical Ltd
0.4.1 by Martin Pool
Start lp-register command
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.4.1 by Martin Pool
Start lp-register command
16
5459.3.1 by Neil Martinsen-Burrell
add more detailed help for Launchpad plugin
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 
5459.3.2 by Neil Martinsen-Burrell
address James Westbys review comments
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
5459.3.1 by Neil Martinsen-Burrell
add more detailed help for Launchpad plugin
33
    register-branch: Register a branch with launchpad.net
34
    launchpad-mirror: Ask Launchpad to mirror a branch now
35
36
"""
0.4.1 by Martin Pool
Start lp-register command
37
0.4.17 by Martin Pool
Allow xmlrpc service url to be overridden by $BZR_LP_XMLRPC_URL
38
# The XMLRPC server address can be overridden by setting the environment
5053.1.1 by Martin Pool
Merge 2.1 back to trunk
39
# variable $BZR_LP_XMLRPC_URL
0.4.17 by Martin Pool
Allow xmlrpc service url to be overridden by $BZR_LP_XMLRPC_URL
40
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
41
# see http://wiki.bazaar.canonical.com/Specs/BranchRegistrationTool
0.4.9 by Martin Pool
Don't transmit non-standard xmlrpc <nil> value.
42
4283.3.1 by Vincent Ladeuil
Make built-in plugins display the same version than bzrlib.
43
# Since we are a built-in plugin we share the bzrlib version
44
from bzrlib import version_info
45
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
46
from bzrlib.lazy_import import lazy_import
47
lazy_import(globals(), """
48
from bzrlib import (
49
    branch as _mod_branch,
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
50
    ui,
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
51
    trace,
52
    )
53
""")
54
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
55
from bzrlib import bzrdir
56
from bzrlib.commands import (
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
57
    Command,
58
    register_command,
59
    )
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
60
from bzrlib.directory_service import directories
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
61
from bzrlib.errors import (
62
    BzrCommandError,
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
63
    InvalidRevisionSpec,
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
64
    InvalidURL,
65
    NoPublicBranch,
66
    NotBranchError,
67
    )
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
68
from bzrlib.help_topics import topic_registry
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
69
from bzrlib.option import (
4969.2.10 by Aaron Bentley
Cleanup and docs.
70
        Option,
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
71
        ListOption,
72
)
0.4.4 by Martin Pool
Start forming xmlrpc requests
73
74
0.4.2 by Martin Pool
Rename command to 'register-branch'
75
class cmd_register_branch(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
76
    __doc__ = """Register a branch with launchpad.net.
0.4.1 by Martin Pool
Start lp-register command
77
78
    This command lists a bzr branch in the directory of branches on
2400.2.4 by Robert Collins
(robertc) Typo in the help for ``register-branch`` fixed. (Robert Collins, #96770)
79
    launchpad.net.  Registration allows the branch to be associated with
0.4.1 by Martin Pool
Start lp-register command
80
    bugs or specifications.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
81
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
82
    Before using this command you must register the project to which the
0.4.1 by Martin Pool
Start lp-register command
83
    branch belongs, and create an account for yourself on launchpad.net.
0.4.3 by Martin Pool
More command line processing
84
85
    arguments:
3200.2.3 by Robert Collins
Tweak wording.
86
        public_url: The publicly visible url for the branch to register.
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
87
                    This must be an http or https url (which Launchpad can read
88
                    from to access the branch). Local file urls, SFTP urls, and
89
                    bzr+ssh urls will not work.
90
                    If no public_url is provided, bzr will use the configured
3200.2.3 by Robert Collins
Tweak wording.
91
                    public_url if there is one for the current branch, and
92
                    otherwise error.
0.4.3 by Martin Pool
More command line processing
93
94
    example:
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
95
        bzr register-branch http://foo.com/bzr/fooproject.mine \\
96
                --project fooproject
0.4.1 by Martin Pool
Start lp-register command
97
    """
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
98
    takes_args = ['public_url?']
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
99
    takes_options = [
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
100
         Option('project',
101
                'Launchpad project short name to associate with the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
102
                unicode),
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
103
         Option('product',
104
                'Launchpad product short name to associate with the branch.', 
105
                unicode,
106
                hidden=True),
0.4.15 by Martin Pool
(register-branch) Add command-line options
107
         Option('branch-name',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
108
                'Short name for the branch; '
109
                'by default taken from the last component of the url.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
110
                unicode),
111
         Option('branch-title',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
112
                'One-sentence description of the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
113
                unicode),
114
         Option('branch-description',
2598.1.5 by Martin Pool
Fix one more option message.
115
                'Longer description of the purpose or contents of the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
116
                unicode),
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
117
         Option('author',
118
                "Branch author's email address, if not yourself.",
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
119
                unicode),
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
120
         Option('link-bug',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
121
                'The bug this branch fixes.',
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
122
                int),
0.4.15 by Martin Pool
(register-branch) Add command-line options
123
         Option('dry-run',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
124
                'Prepare the request but don\'t actually send it.')
0.4.15 by Martin Pool
(register-branch) Add command-line options
125
        ]
126
127
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
128
    def run(self,
129
            public_url=None,
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
130
            project='',
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
131
            product=None,
0.4.15 by Martin Pool
(register-branch) Add command-line options
132
            branch_name='',
133
            branch_title='',
134
            branch_description='',
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
135
            author='',
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
136
            link_bug=None,
0.4.15 by Martin Pool
(register-branch) Add command-line options
137
            dry_run=False):
2898.3.8 by James Henstridge
Get rid of relative imports in Launchpad plugin.
138
        from bzrlib.plugins.launchpad.lp_registration import (
4505.6.4 by Jonathan Lange
Remove unnecessary import.
139
            BranchRegistrationRequest, BranchBugLinkRequest,
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
140
            DryRunLaunchpadService, LaunchpadService)
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
141
        if public_url is None:
142
            try:
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
143
                b = _mod_branch.Branch.open_containing('.')[0]
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
144
            except NotBranchError:
145
                raise BzrCommandError('register-branch requires a public '
146
                    'branch url - see bzr help register-branch.')
147
            public_url = b.get_public_branch()
148
            if public_url is None:
149
                raise NoPublicBranch(b)
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
150
        if product is not None:
151
            project = product
152
            trace.note('--product is deprecated; please use --project.')
153
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
154
155
        rego = BranchRegistrationRequest(branch_url=public_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
156
                                         branch_name=branch_name,
157
                                         branch_title=branch_title,
158
                                         branch_description=branch_description,
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
159
                                         product_name=project,
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
160
                                         author_email=author,
0.4.15 by Martin Pool
(register-branch) Add command-line options
161
                                         )
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
162
        linko = BranchBugLinkRequest(branch_url=public_url,
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
163
                                     bug_id=link_bug)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
164
        if not dry_run:
165
            service = LaunchpadService()
166
            # This gives back the xmlrpc url that can be used for future
167
            # operations on the branch.  It's not so useful to print to the
168
            # user since they can't do anything with it from a web browser; it
169
            # might be nice for the server to tell us about an html url as
170
            # well.
171
        else:
172
            # Run on service entirely in memory
173
            service = DryRunLaunchpadService()
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
174
        service.gather_user_credentials()
4505.6.21 by Jonathan Lange
Clean up flakes.
175
        rego.submit(service)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
176
        if link_bug:
4505.6.21 by Jonathan Lange
Clean up flakes.
177
            linko.submit(service)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
178
        print 'Branch registered.'
0.4.1 by Martin Pool
Start lp-register command
179
0.4.2 by Martin Pool
Rename command to 'register-branch'
180
register_command(cmd_register_branch)
2245.8.4 by Martin Pool
lp:/// indirection works
181
2898.3.3 by James Henstridge
Add launchpad-login command.
182
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
183
class cmd_launchpad_open(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
184
    __doc__ = """Open a Launchpad branch page in your web browser."""
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
185
186
    aliases = ['lp-open']
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
187
    takes_options = [
188
        Option('dry-run',
189
               'Do not actually open the browser. Just say the URL we would '
190
               'use.'),
191
        ]
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
192
    takes_args = ['location?']
193
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
194
    def _possible_locations(self, location):
195
        """Yield possible external locations for the branch at 'location'."""
196
        yield location
197
        try:
4867.2.1 by Neil Martinsen-Burrell
launchpad-open works from a subdirectory of a branch
198
            branch = _mod_branch.Branch.open_containing(location)[0]
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
199
        except NotBranchError:
200
            return
201
        branch_url = branch.get_public_branch()
202
        if branch_url is not None:
203
            yield branch_url
204
        branch_url = branch.get_push_location()
205
        if branch_url is not None:
206
            yield branch_url
207
208
    def _get_web_url(self, service, location):
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
209
        from bzrlib.plugins.launchpad.lp_registration import (
210
            NotLaunchpadBranch)
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
211
        for branch_url in self._possible_locations(location):
212
            try:
213
                return service.get_web_url_from_branch_url(branch_url)
214
            except (NotLaunchpadBranch, InvalidURL):
215
                pass
216
        raise NotLaunchpadBranch(branch_url)
217
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
218
    def run(self, location=None, dry_run=False):
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
219
        from bzrlib.plugins.launchpad.lp_registration import (
220
            LaunchpadService)
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
221
        if location is None:
222
            location = u'.'
4505.6.21 by Jonathan Lange
Clean up flakes.
223
        web_url = self._get_web_url(LaunchpadService(), location)
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
224
        trace.note('Opening %s in web browser' % web_url)
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
225
        if not dry_run:
4511.1.1 by Alexander Belchenko
launchpad plugin: import webbrowse should be explicit and never lazy, otherwise bzr.exe lacks this module.
226
            import webbrowser   # this import should not be lazy
227
                                # otherwise bzr.exe lacks this module
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
228
            webbrowser.open(web_url)
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
229
230
register_command(cmd_launchpad_open)
231
232
2898.3.3 by James Henstridge
Add launchpad-login command.
233
class cmd_launchpad_login(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
234
    __doc__ = """Show or set the Launchpad user ID.
2898.3.3 by James Henstridge
Add launchpad-login command.
235
236
    When communicating with Launchpad, some commands need to know your
237
    Launchpad user ID.  This command can be used to set or show the
238
    user ID that Bazaar will use for such communication.
239
240
    :Examples:
241
      Show the Launchpad ID of the current user::
242
243
          bzr launchpad-login
244
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
245
      Set the Launchpad ID of the current user to 'bob'::
2898.3.3 by James Henstridge
Add launchpad-login command.
246
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
247
          bzr launchpad-login bob
2898.3.3 by James Henstridge
Add launchpad-login command.
248
    """
249
    aliases = ['lp-login']
250
    takes_args = ['name?']
251
    takes_options = [
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
252
        'verbose',
2898.3.4 by James Henstridge
Cleanups from mini-review by Tim.
253
        Option('no-check',
254
               "Don't check that the user name is valid."),
2898.3.3 by James Henstridge
Add launchpad-login command.
255
        ]
256
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
257
    def run(self, name=None, no_check=False, verbose=False):
4505.6.13 by Jonathan Lange
Clarify the comment.
258
        # This is totally separate from any launchpadlib login system.
2898.3.8 by James Henstridge
Get rid of relative imports in Launchpad plugin.
259
        from bzrlib.plugins.launchpad import account
2898.3.3 by James Henstridge
Add launchpad-login command.
260
        check_account = not no_check
261
262
        if name is None:
263
            username = account.get_lp_login()
264
            if username:
2898.3.4 by James Henstridge
Cleanups from mini-review by Tim.
265
                if check_account:
266
                    account.check_lp_login(username)
4505.1.3 by Jonathan Lange
Add some extra untested verbosity.
267
                    if verbose:
268
                        self.outf.write(
269
                            "Launchpad user ID exists and has SSH keys.\n")
2898.3.3 by James Henstridge
Add launchpad-login command.
270
                self.outf.write(username + '\n')
271
            else:
272
                self.outf.write('No Launchpad user ID configured.\n')
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
273
                return 1
2898.3.3 by James Henstridge
Add launchpad-login command.
274
        else:
4216.2.1 by Michael Hudson
well this is it
275
            name = name.lower()
2898.3.3 by James Henstridge
Add launchpad-login command.
276
            if check_account:
277
                account.check_lp_login(name)
4505.1.3 by Jonathan Lange
Add some extra untested verbosity.
278
                if verbose:
279
                    self.outf.write(
280
                        "Launchpad user ID exists and has SSH keys.\n")
2898.3.3 by James Henstridge
Add launchpad-login command.
281
            account.set_lp_login(name)
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
282
            if verbose:
283
                self.outf.write("Launchpad user ID set to '%s'.\n" % (name,))
2898.3.3 by James Henstridge
Add launchpad-login command.
284
285
register_command(cmd_launchpad_login)
286
287
4505.6.9 by Jonathan Lange
Add some XXX comments based on the review.
288
# XXX: cmd_launchpad_mirror is untested
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
289
class cmd_launchpad_mirror(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
290
    __doc__ = """Ask Launchpad to mirror a branch now."""
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
291
292
    aliases = ['lp-mirror']
293
    takes_args = ['location?']
294
295
    def run(self, location='.'):
4505.6.25 by Jonathan Lange
Add a test to check what happens if launchpadlib not available.
296
        from bzrlib.plugins.launchpad import lp_api
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
297
        from bzrlib.plugins.launchpad.lp_registration import LaunchpadService
5657.1.2 by Max Bowsher
Also make lp-mirror use open_containing, so it still works when in a subdirectory of a branch.
298
        branch, _ = _mod_branch.Branch.open_containing(location)
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
299
        service = LaunchpadService()
300
        launchpad = lp_api.login(service)
5657.1.1 by Max Bowsher
Fix bzr lp-mirror to work on command line branch URLs and branches
301
        lp_branch = lp_api.LaunchpadBranch.from_bzr(launchpad, branch,
302
                create_missing=False)
303
        lp_branch.lp.requestMirror()
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
304
305
4505.6.8 by Jonathan Lange
Always register the lp-mirror command. Only try to load launchpadlib if
306
register_command(cmd_launchpad_mirror)
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
307
308
4969.2.16 by Aaron Bentley
Updates from review.
309
class cmd_lp_propose_merge(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
310
    __doc__ = """Propose merging a branch on Launchpad.
4969.2.16 by Aaron Bentley
Updates from review.
311
312
    This will open your usual editor to provide the initial comment.  When it
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
313
    has created the proposal, it will open it in your default web browser.
4969.2.16 by Aaron Bentley
Updates from review.
314
315
    The branch will be proposed to merge into SUBMIT_BRANCH.  If SUBMIT_BRANCH
316
    is not supplied, the remembered submit branch will be used.  If no submit
317
    branch is remembered, the development focus will be used.
318
319
    By default, the SUBMIT_BRANCH's review team will be requested to review
320
    the merge proposal.  This can be overriden by specifying --review (-R).
321
    The parameter the launchpad account name of the desired reviewer.  This
322
    may optionally be followed by '=' and the review type.  For example:
323
324
      bzr lp-propose-merge --review jrandom --review review-team=qa
325
326
    This will propose a merge,  request "jrandom" to perform a review of
327
    unspecified type, and request "review-team" to perform a "qa" review.
328
    """
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
329
330
    takes_options = [Option('staging',
331
                            help='Propose the merge on staging.'),
332
                     Option('message', short_name='m', type=unicode,
333
                            help='Commit message.'),
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
334
                     Option('approve',
335
                            help='Mark the proposal as approved immediately.'),
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
336
                     ListOption('review', short_name='R', type=unicode,
337
                            help='Requested reviewer and optional type.')]
338
339
    takes_args = ['submit_branch?']
340
4969.2.16 by Aaron Bentley
Updates from review.
341
    aliases = ['lp-submit', 'lp-propose']
342
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
343
    def run(self, submit_branch=None, review=None, staging=False,
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
344
            message=None, approve=False):
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
345
        from bzrlib.plugins.launchpad import lp_propose
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
346
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
347
            '.')
348
        if review is None:
349
            reviews = None
350
        else:
351
            reviews = []
352
            for review in review:
353
                if '=' in review:
354
                    reviews.append(review.split('=', 2))
355
                else:
356
                    reviews.append((review, ''))
357
            if submit_branch is None:
358
                submit_branch = branch.get_submit_branch()
359
        if submit_branch is None:
360
            target = None
361
        else:
362
            target = _mod_branch.Branch.open(submit_branch)
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
363
        proposer = lp_propose.Proposer(tree, branch, target, message,
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
364
                                       reviews, staging, approve=approve)
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
365
        proposer.check_proposal()
366
        proposer.create_proposal()
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
367
368
4969.2.16 by Aaron Bentley
Updates from review.
369
register_command(cmd_lp_propose_merge)
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
370
371
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
372
class cmd_lp_find_proposal(Command):
373
374
    __doc__ = """Find the proposal to merge this revision.
375
376
    Finds the merge proposal(s) that discussed landing the specified revision.
377
    This works only if the selected branch was the merge proposal target, and
378
    if the merged_revno is recorded for the merge proposal.  The proposal(s)
379
    are opened in a web browser.
380
381
    Any revision involved in the merge may be specified-- the revision in
382
    which the merge was performed, or one of the revisions that was merged.
383
384
    So, to find the merge proposal that reviewed line 1 of README::
385
386
      bzr lp-find-proposal -r annotate:README:1
387
    """
388
389
    takes_options = ['revision']
390
391
    def run(self, revision=None):
392
        from bzrlib.plugins.launchpad import lp_api
393
        import webbrowser
394
        b = _mod_branch.Branch.open_containing('.')[0]
395
        pb = ui.ui_factory.nested_progress_bar()
396
        b.lock_read()
397
        try:
398
            revno = self._find_merged_revno(revision, b, pb)
5546.2.4 by Aaron Bentley
Cleanup
399
            merged = self._find_proposals(revno, b, pb)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
400
            if len(merged) == 0:
401
                raise BzrCommandError('No review found.')
402
            trace.note('%d proposals(s) found.' % len(merged))
403
            for mp in merged:
404
                webbrowser.open(lp_api.canonical_url(mp))
405
        finally:
406
            b.unlock()
407
            pb.finished()
408
409
    def _find_merged_revno(self, revision, b, pb):
410
        if revision is None:
411
            return b.revno()
412
        pb.update('Finding revision-id')
413
        revision_id = revision[0].as_revision_id(b)
414
        # a revno spec is necessarily on the mainline.
415
        if self._is_revno_spec(revision[0]):
416
            merging_revision = revision_id
417
        else:
418
            graph = b.repository.get_graph()
419
            pb.update('Finding merge')
420
            merging_revision = graph.find_lefthand_merger(
421
                revision_id, b.last_revision())
422
            if merging_revision is None:
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
423
                raise InvalidRevisionSpec(revision[0].user_spec, b)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
424
        pb.update('Finding revno')
425
        return b.revision_id_to_revno(merging_revision)
426
5546.2.4 by Aaron Bentley
Cleanup
427
    def _find_proposals(self, revno, b, pb):
428
        launchpad = lp_api.login(lp_registration.LaunchpadService())
429
        pb.update('Finding Launchpad branch')
430
        lpb = lp_api.LaunchpadBranch.from_bzr(launchpad, b,
431
                                              create_missing=False)
432
        pb.update('Finding proposals')
433
        return list(lpb.lp.getMergeProposals(status=['Merged'],
434
                                             merged_revnos=[revno]))
435
436
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
437
    @staticmethod
438
    def _is_revno_spec(spec):
439
        try:
5546.2.3 by Aaron Bentley
Tighten revno check, avoid creating branches on lp.
440
            int(spec.user_spec)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
441
        except ValueError:
442
            return False
443
        else:
444
            return True
445
446
447
register_command(cmd_lp_find_proposal)
448
449
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
450
def _register_directory():
3251.4.3 by Aaron Bentley
More renames and cleanups
451
    directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
452
                              'LaunchpadDirectory',
453
                              'Launchpad-based directory service',)
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
454
    directories.register_lazy(
455
        'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
456
        'LaunchpadDirectory',
457
        'debianlp: shortcut')
458
    directories.register_lazy(
459
        'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
460
        'LaunchpadDirectory',
461
        'ubuntu: shortcut')
462
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
463
_register_directory()
2245.8.5 by Martin Pool
Add short-form lp:PRODUCT url form
464
0.4.1 by Martin Pool
Start lp-register command
465
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
466
def load_tests(basic_tests, module, loader):
467
    testmod_names = [
468
        'test_account',
469
        'test_register',
4505.6.25 by Jonathan Lange
Add a test to check what happens if launchpadlib not available.
470
        'test_lp_api',
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
471
        'test_lp_directory',
472
        'test_lp_login',
473
        'test_lp_open',
474
        'test_lp_service',
475
        ]
476
    basic_tests.addTest(loader.loadTestsFromModuleNames(
477
            ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
478
    return basic_tests
2245.8.1 by Martin Pool
Start adding tests for launchpad indirection
479
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
480
481
_launchpad_help = """Integration with Launchpad.net
482
483
Launchpad.net provides free Bazaar branch hosting with integrated bug and
484
specification tracking.
485
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
486
The bzr client (through the plugin called 'launchpad') has special
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
487
features to communicate with Launchpad:
488
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
489
    * The launchpad-login command tells Bazaar your Launchpad user name. This
490
      is then used by the 'lp:' transport to download your branches using
491
      bzr+ssh://.
492
4258.1.1 by James Westby
Add "--fixes lp:" to the launchpad plugin documentation.
493
    * The 'lp:' transport uses Launchpad as a directory service: for example
494
      'lp:bzr' and 'lp:python' refer to the main branches of the relevant
495
      projects and may be branched, logged, etc. You can also use the 'lp:'
496
      transport to refer to specific branches, e.g. lp:~bzr/bzr/trunk.
497
498
    * The 'lp:' bug tracker alias can expand launchpad bug numbers to their
499
      URLs for use with 'bzr commit --fixes', e.g. 'bzr commit --fixes lp:12345'
500
      will record a revision property that marks that revision as fixing
4258.1.2 by Matt Nordhoff
Fix a typo in the launchpad plugin's help
501
      Launchpad bug 12345. When you push that branch to Launchpad it will
502
      automatically be linked to the bug report.
4258.1.1 by James Westby
Add "--fixes lp:" to the launchpad plugin documentation.
503
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
504
    * The register-branch command tells Launchpad about the url of a
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
505
      public branch.  Launchpad will then mirror the branch, display
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
506
      its contents and allow it to be attached to bugs and other
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
507
      objects.
508
509
For more information see http://help.launchpad.net/
510
"""
511
topic_registry.register('launchpad',
512
    _launchpad_help,
513
    'Using Bazaar with Launchpad.net')