/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
43
import time
44
4283.3.1 by Vincent Ladeuil
Make built-in plugins display the same version than bzrlib.
45
# Since we are a built-in plugin we share the bzrlib version
46
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
47
from bzrlib.lazy_import import lazy_import
48
lazy_import(globals(), """
49
from bzrlib import (
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
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
55
from bzrlib import (
56
    branch as _mod_branch,
57
    bzrdir,
58
    lazy_regex,
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
59
    version_info,
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
60
    )
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
61
from bzrlib.commands import (
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
62
    Command,
63
    register_command,
64
    )
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
65
from bzrlib.directory_service import directories
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
66
from bzrlib.errors import (
67
    BzrCommandError,
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
68
    InvalidRevisionSpec,
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
69
    InvalidURL,
70
    NoPublicBranch,
71
    NotBranchError,
72
    )
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
73
from bzrlib.help_topics import topic_registry
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
74
from bzrlib.option import (
4969.2.10 by Aaron Bentley
Cleanup and docs.
75
        Option,
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
76
        ListOption,
77
)
0.4.4 by Martin Pool
Start forming xmlrpc requests
78
79
0.4.2 by Martin Pool
Rename command to 'register-branch'
80
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
81
    __doc__ = """Register a branch with launchpad.net.
0.4.1 by Martin Pool
Start lp-register command
82
83
    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)
84
    launchpad.net.  Registration allows the branch to be associated with
0.4.1 by Martin Pool
Start lp-register command
85
    bugs or specifications.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
86
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
87
    Before using this command you must register the project to which the
0.4.1 by Martin Pool
Start lp-register command
88
    branch belongs, and create an account for yourself on launchpad.net.
0.4.3 by Martin Pool
More command line processing
89
90
    arguments:
3200.2.3 by Robert Collins
Tweak wording.
91
        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
92
                    This must be an http or https url (which Launchpad can read
93
                    from to access the branch). Local file urls, SFTP urls, and
94
                    bzr+ssh urls will not work.
95
                    If no public_url is provided, bzr will use the configured
3200.2.3 by Robert Collins
Tweak wording.
96
                    public_url if there is one for the current branch, and
97
                    otherwise error.
0.4.3 by Martin Pool
More command line processing
98
99
    example:
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
100
        bzr register-branch http://foo.com/bzr/fooproject.mine \\
101
                --project fooproject
0.4.1 by Martin Pool
Start lp-register command
102
    """
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
103
    takes_args = ['public_url?']
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
104
    takes_options = [
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
105
         Option('project',
106
                'Launchpad project short name to associate with the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
107
                unicode),
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
108
         Option('product',
109
                'Launchpad product short name to associate with the branch.', 
110
                unicode,
111
                hidden=True),
0.4.15 by Martin Pool
(register-branch) Add command-line options
112
         Option('branch-name',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
113
                'Short name for the branch; '
114
                'by default taken from the last component of the url.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
115
                unicode),
116
         Option('branch-title',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
117
                'One-sentence description of the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
118
                unicode),
119
         Option('branch-description',
2598.1.5 by Martin Pool
Fix one more option message.
120
                'Longer description of the purpose or contents of the branch.',
0.4.15 by Martin Pool
(register-branch) Add command-line options
121
                unicode),
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
122
         Option('author',
123
                "Branch author's email address, if not yourself.",
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
124
                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.
125
         Option('link-bug',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
126
                '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.
127
                int),
0.4.15 by Martin Pool
(register-branch) Add command-line options
128
         Option('dry-run',
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
129
                'Prepare the request but don\'t actually send it.')
0.4.15 by Martin Pool
(register-branch) Add command-line options
130
        ]
131
132
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
133
    def run(self,
134
            public_url=None,
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
135
            project='',
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
136
            product=None,
0.4.15 by Martin Pool
(register-branch) Add command-line options
137
            branch_name='',
138
            branch_title='',
139
            branch_description='',
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
140
            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.
141
            link_bug=None,
0.4.15 by Martin Pool
(register-branch) Add command-line options
142
            dry_run=False):
2898.3.8 by James Henstridge
Get rid of relative imports in Launchpad plugin.
143
        from bzrlib.plugins.launchpad.lp_registration import (
4505.6.4 by Jonathan Lange
Remove unnecessary import.
144
            BranchRegistrationRequest, BranchBugLinkRequest,
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
145
            DryRunLaunchpadService, LaunchpadService)
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
146
        if public_url is None:
147
            try:
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
148
                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
149
            except NotBranchError:
150
                raise BzrCommandError('register-branch requires a public '
151
                    'branch url - see bzr help register-branch.')
152
            public_url = b.get_public_branch()
153
            if public_url is None:
154
                raise NoPublicBranch(b)
4416.7.3 by Neil Martinsen-Burrell
Retain --product options for register-branch, but deprecate it in favor of --project
155
        if product is not None:
156
            project = product
157
            trace.note('--product is deprecated; please use --project.')
158
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
159
160
        rego = BranchRegistrationRequest(branch_url=public_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
161
                                         branch_name=branch_name,
162
                                         branch_title=branch_title,
163
                                         branch_description=branch_description,
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
164
                                         product_name=project,
0.4.16 by Martin Pool
(register-branch) Add --author option and respect --dry-run
165
                                         author_email=author,
0.4.15 by Martin Pool
(register-branch) Add command-line options
166
                                         )
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
167
        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.
168
                                     bug_id=link_bug)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
169
        if not dry_run:
170
            service = LaunchpadService()
171
            # This gives back the xmlrpc url that can be used for future
172
            # operations on the branch.  It's not so useful to print to the
173
            # user since they can't do anything with it from a web browser; it
174
            # might be nice for the server to tell us about an html url as
175
            # well.
176
        else:
177
            # Run on service entirely in memory
178
            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.
179
        service.gather_user_credentials()
4505.6.21 by Jonathan Lange
Clean up flakes.
180
        rego.submit(service)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
181
        if link_bug:
4505.6.21 by Jonathan Lange
Clean up flakes.
182
            linko.submit(service)
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
183
        print 'Branch registered.'
0.4.1 by Martin Pool
Start lp-register command
184
0.4.2 by Martin Pool
Rename command to 'register-branch'
185
register_command(cmd_register_branch)
2245.8.4 by Martin Pool
lp:/// indirection works
186
2898.3.3 by James Henstridge
Add launchpad-login command.
187
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
188
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
189
    __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.
190
191
    aliases = ['lp-open']
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
192
    takes_options = [
193
        Option('dry-run',
194
               'Do not actually open the browser. Just say the URL we would '
195
               'use.'),
196
        ]
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
197
    takes_args = ['location?']
198
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
199
    def _possible_locations(self, location):
200
        """Yield possible external locations for the branch at 'location'."""
201
        yield location
202
        try:
4867.2.1 by Neil Martinsen-Burrell
launchpad-open works from a subdirectory of a branch
203
            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.
204
        except NotBranchError:
205
            return
206
        branch_url = branch.get_public_branch()
207
        if branch_url is not None:
208
            yield branch_url
209
        branch_url = branch.get_push_location()
210
        if branch_url is not None:
211
            yield branch_url
212
213
    def _get_web_url(self, service, location):
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
214
        from bzrlib.plugins.launchpad.lp_registration import (
215
            NotLaunchpadBranch)
4031.2.5 by Jonathan Lange
Refactor the code so we don't do too many remote requests.
216
        for branch_url in self._possible_locations(location):
217
            try:
218
                return service.get_web_url_from_branch_url(branch_url)
219
            except (NotLaunchpadBranch, InvalidURL):
220
                pass
221
        raise NotLaunchpadBranch(branch_url)
222
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
223
    def run(self, location=None, dry_run=False):
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
224
        from bzrlib.plugins.launchpad.lp_registration import (
225
            LaunchpadService)
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
226
        if location is None:
227
            location = u'.'
4505.6.21 by Jonathan Lange
Clean up flakes.
228
        web_url = self._get_web_url(LaunchpadService(), location)
4031.2.11 by John Arbash Meinel
Turn a bunch of imports into lazy imports.
229
        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.
230
        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.
231
            import webbrowser   # this import should not be lazy
232
                                # otherwise bzr.exe lacks this module
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
233
            webbrowser.open(web_url)
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
234
235
register_command(cmd_launchpad_open)
236
237
2898.3.3 by James Henstridge
Add launchpad-login command.
238
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
239
    __doc__ = """Show or set the Launchpad user ID.
2898.3.3 by James Henstridge
Add launchpad-login command.
240
241
    When communicating with Launchpad, some commands need to know your
242
    Launchpad user ID.  This command can be used to set or show the
243
    user ID that Bazaar will use for such communication.
244
245
    :Examples:
246
      Show the Launchpad ID of the current user::
247
248
          bzr launchpad-login
249
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
250
      Set the Launchpad ID of the current user to 'bob'::
2898.3.3 by James Henstridge
Add launchpad-login command.
251
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
252
          bzr launchpad-login bob
2898.3.3 by James Henstridge
Add launchpad-login command.
253
    """
254
    aliases = ['lp-login']
255
    takes_args = ['name?']
256
    takes_options = [
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
257
        'verbose',
2898.3.4 by James Henstridge
Cleanups from mini-review by Tim.
258
        Option('no-check',
259
               "Don't check that the user name is valid."),
2898.3.3 by James Henstridge
Add launchpad-login command.
260
        ]
261
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
262
    def run(self, name=None, no_check=False, verbose=False):
4505.6.13 by Jonathan Lange
Clarify the comment.
263
        # This is totally separate from any launchpadlib login system.
2898.3.8 by James Henstridge
Get rid of relative imports in Launchpad plugin.
264
        from bzrlib.plugins.launchpad import account
2898.3.3 by James Henstridge
Add launchpad-login command.
265
        check_account = not no_check
266
267
        if name is None:
268
            username = account.get_lp_login()
269
            if username:
2898.3.4 by James Henstridge
Cleanups from mini-review by Tim.
270
                if check_account:
271
                    account.check_lp_login(username)
4505.1.3 by Jonathan Lange
Add some extra untested verbosity.
272
                    if verbose:
273
                        self.outf.write(
274
                            "Launchpad user ID exists and has SSH keys.\n")
2898.3.3 by James Henstridge
Add launchpad-login command.
275
                self.outf.write(username + '\n')
276
            else:
277
                self.outf.write('No Launchpad user ID configured.\n')
2898.3.9 by James Henstridge
* Add a simple NEWS item for the command.
278
                return 1
2898.3.3 by James Henstridge
Add launchpad-login command.
279
        else:
4216.2.1 by Michael Hudson
well this is it
280
            name = name.lower()
2898.3.3 by James Henstridge
Add launchpad-login command.
281
            if check_account:
282
                account.check_lp_login(name)
4505.1.3 by Jonathan Lange
Add some extra untested verbosity.
283
                if verbose:
284
                    self.outf.write(
285
                        "Launchpad user ID exists and has SSH keys.\n")
2898.3.3 by James Henstridge
Add launchpad-login command.
286
            account.set_lp_login(name)
4505.1.2 by Jonathan Lange
Add many more tests, fix the actual bug.
287
            if verbose:
288
                self.outf.write("Launchpad user ID set to '%s'.\n" % (name,))
2898.3.3 by James Henstridge
Add launchpad-login command.
289
290
register_command(cmd_launchpad_login)
291
292
4505.6.9 by Jonathan Lange
Add some XXX comments based on the review.
293
# XXX: cmd_launchpad_mirror is untested
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
294
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
295
    __doc__ = """Ask Launchpad to mirror a branch now."""
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
296
297
    aliases = ['lp-mirror']
298
    takes_args = ['location?']
299
300
    def run(self, location='.'):
4505.6.25 by Jonathan Lange
Add a test to check what happens if launchpadlib not available.
301
        from bzrlib.plugins.launchpad import lp_api
4505.6.10 by Jonathan Lange
Move lp_registration imports into commands.
302
        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.
303
        branch, _ = _mod_branch.Branch.open_containing(location)
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
304
        service = LaunchpadService()
305
        launchpad = lp_api.login(service)
5657.1.1 by Max Bowsher
Fix bzr lp-mirror to work on command line branch URLs and branches
306
        lp_branch = lp_api.LaunchpadBranch.from_bzr(launchpad, branch,
307
                create_missing=False)
308
        lp_branch.lp.requestMirror()
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
309
310
4505.6.8 by Jonathan Lange
Always register the lp-mirror command. Only try to load launchpadlib if
311
register_command(cmd_launchpad_mirror)
4505.6.6 by Jonathan Lange
Add a command to mirror Launchpad branches now.
312
313
4969.2.16 by Aaron Bentley
Updates from review.
314
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
315
    __doc__ = """Propose merging a branch on Launchpad.
4969.2.16 by Aaron Bentley
Updates from review.
316
317
    This will open your usual editor to provide the initial comment.  When it
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
318
    has created the proposal, it will open it in your default web browser.
4969.2.16 by Aaron Bentley
Updates from review.
319
320
    The branch will be proposed to merge into SUBMIT_BRANCH.  If SUBMIT_BRANCH
321
    is not supplied, the remembered submit branch will be used.  If no submit
322
    branch is remembered, the development focus will be used.
323
324
    By default, the SUBMIT_BRANCH's review team will be requested to review
325
    the merge proposal.  This can be overriden by specifying --review (-R).
326
    The parameter the launchpad account name of the desired reviewer.  This
327
    may optionally be followed by '=' and the review type.  For example:
328
329
      bzr lp-propose-merge --review jrandom --review review-team=qa
330
331
    This will propose a merge,  request "jrandom" to perform a review of
332
    unspecified type, and request "review-team" to perform a "qa" review.
333
    """
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
334
335
    takes_options = [Option('staging',
336
                            help='Propose the merge on staging.'),
337
                     Option('message', short_name='m', type=unicode,
338
                            help='Commit message.'),
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
339
                     Option('approve',
340
                            help='Mark the proposal as approved immediately.'),
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
341
                     ListOption('review', short_name='R', type=unicode,
342
                            help='Requested reviewer and optional type.')]
343
344
    takes_args = ['submit_branch?']
345
4969.2.16 by Aaron Bentley
Updates from review.
346
    aliases = ['lp-submit', 'lp-propose']
347
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
348
    def run(self, submit_branch=None, review=None, staging=False,
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
349
            message=None, approve=False):
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
350
        from bzrlib.plugins.launchpad import lp_propose
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
351
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
352
            '.')
353
        if review is None:
354
            reviews = None
355
        else:
356
            reviews = []
357
            for review in review:
358
                if '=' in review:
359
                    reviews.append(review.split('=', 2))
360
                else:
361
                    reviews.append((review, ''))
362
            if submit_branch is None:
363
                submit_branch = branch.get_submit_branch()
364
        if submit_branch is None:
365
            target = None
366
        else:
367
            target = _mod_branch.Branch.open(submit_branch)
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
368
        proposer = lp_propose.Proposer(tree, branch, target, message,
5244.1.3 by Robert Collins
Allow setting new proposals as approved immediately.
369
                                       reviews, staging, approve=approve)
4969.2.19 by Aaron Bentley
Rename submit to propose everywhere.
370
        proposer.check_proposal()
371
        proposer.create_proposal()
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
372
373
4969.2.16 by Aaron Bentley
Updates from review.
374
register_command(cmd_lp_propose_merge)
4969.2.7 by Aaron Bentley
Add lp-submit, get working.
375
376
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
377
class cmd_lp_find_proposal(Command):
378
379
    __doc__ = """Find the proposal to merge this revision.
380
381
    Finds the merge proposal(s) that discussed landing the specified revision.
382
    This works only if the selected branch was the merge proposal target, and
383
    if the merged_revno is recorded for the merge proposal.  The proposal(s)
384
    are opened in a web browser.
385
386
    Any revision involved in the merge may be specified-- the revision in
387
    which the merge was performed, or one of the revisions that was merged.
388
389
    So, to find the merge proposal that reviewed line 1 of README::
390
391
      bzr lp-find-proposal -r annotate:README:1
392
    """
393
394
    takes_options = ['revision']
395
396
    def run(self, revision=None):
397
        from bzrlib.plugins.launchpad import lp_api
398
        import webbrowser
399
        b = _mod_branch.Branch.open_containing('.')[0]
400
        pb = ui.ui_factory.nested_progress_bar()
401
        b.lock_read()
402
        try:
403
            revno = self._find_merged_revno(revision, b, pb)
5546.2.4 by Aaron Bentley
Cleanup
404
            merged = self._find_proposals(revno, b, pb)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
405
            if len(merged) == 0:
406
                raise BzrCommandError('No review found.')
407
            trace.note('%d proposals(s) found.' % len(merged))
408
            for mp in merged:
409
                webbrowser.open(lp_api.canonical_url(mp))
410
        finally:
411
            b.unlock()
412
            pb.finished()
413
414
    def _find_merged_revno(self, revision, b, pb):
415
        if revision is None:
416
            return b.revno()
417
        pb.update('Finding revision-id')
418
        revision_id = revision[0].as_revision_id(b)
419
        # a revno spec is necessarily on the mainline.
420
        if self._is_revno_spec(revision[0]):
421
            merging_revision = revision_id
422
        else:
423
            graph = b.repository.get_graph()
424
            pb.update('Finding merge')
425
            merging_revision = graph.find_lefthand_merger(
426
                revision_id, b.last_revision())
427
            if merging_revision is None:
5753.2.2 by Jelmer Vernooij
Remove some unnecessary imports, clean up lazy imports.
428
                raise InvalidRevisionSpec(revision[0].user_spec, b)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
429
        pb.update('Finding revno')
430
        return b.revision_id_to_revno(merging_revision)
431
5546.2.4 by Aaron Bentley
Cleanup
432
    def _find_proposals(self, revno, b, pb):
433
        launchpad = lp_api.login(lp_registration.LaunchpadService())
434
        pb.update('Finding Launchpad branch')
435
        lpb = lp_api.LaunchpadBranch.from_bzr(launchpad, b,
436
                                              create_missing=False)
437
        pb.update('Finding proposals')
438
        return list(lpb.lp.getMergeProposals(status=['Merged'],
439
                                             merged_revnos=[revno]))
440
441
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
442
    @staticmethod
443
    def _is_revno_spec(spec):
444
        try:
5546.2.3 by Aaron Bentley
Tighten revno check, avoid creating branches on lp.
445
            int(spec.user_spec)
5546.2.1 by Aaron Bentley
Add lp-find-proposal.
446
        except ValueError:
447
            return False
448
        else:
449
            return True
450
451
452
register_command(cmd_lp_find_proposal)
453
454
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
455
def _register_directory():
3251.4.3 by Aaron Bentley
More renames and cleanups
456
    directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
457
                              'LaunchpadDirectory',
458
                              'Launchpad-based directory service',)
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
459
    directories.register_lazy(
460
        'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
461
        'LaunchpadDirectory',
462
        'debianlp: shortcut')
463
    directories.register_lazy(
464
        'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
465
        'LaunchpadDirectory',
466
        'ubuntu: shortcut')
467
3251.4.2 by Aaron Bentley
Clean up Launchpad directory service code
468
_register_directory()
2245.8.5 by Martin Pool
Add short-form lp:PRODUCT url form
469
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
470
# This is kept in __init__ so that we don't load lp_api_lite unless the branch
471
# actually matches. That way we can avoid importing extra dependencies like
472
# json.
473
_package_branch = lazy_regex.lazy_compile(
6024.3.4 by John Arbash Meinel
More tests, and a small fix for the regex.
474
    r'bazaar.launchpad.net.*?/'
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
475
    r'(?P<user>~[^/]+/)?(?P<archive>ubuntu|debian)/(?P<series>[^/]+/)?'
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
476
    r'(?P<project>[^/]+)(?P<branch>/[^/]+)?'
477
    )
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
478
479
def _get_package_branch_info(url):
480
    """Determine the packaging information for this URL.
481
482
    :return: If this isn't a packaging branch, return None. If it is, return
483
        (archive, series, project)
484
    """
485
    m = _package_branch.search(url)
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
486
    if m is None:
487
        return
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
488
    archive, series, project, user = m.group('archive', 'series',
489
                                             'project', 'user')
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
490
    if series is not None:
5050.79.7 by John Arbash Meinel
clarify a comment.
491
        # series is optional, so the regex includes the extra '/', we don't
492
        # want to send that on (it causes Internal Server Errors.)
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
493
        series = series.strip('/')
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
494
    if user is not None:
495
        user = user.strip('~/')
496
        if user != 'ubuntu-branches':
497
            return None
498
    return archive, series, project
499
500
501
def _check_is_up_to_date(the_branch):
502
    info = _get_package_branch_info(the_branch.base)
503
    if info is None:
504
        return
505
    archive, series, project = info
506
    from bzrlib.plugins.launchpad import lp_api_lite
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
507
    t = time.time()
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
508
    latest_pub = lp_api_lite.LatestPublication(archive, series, project)
509
    latest_ver = latest_pub.get_latest_version()
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
510
    t_latest_ver = time.time() - t
511
    trace.mutter('LatestPublication.get_latest_version took %.3fs'
512
                 % (t_latest_ver,))
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
513
    if latest_ver is None:
6024.3.6 by John Arbash Meinel
Clean up the warning messages a bit.
514
        trace.note('Could not find a published version for packaging branch:\n'
515
                   '  %s' % (the_branch.base,))
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
516
        return
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
517
    t = time.time()
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
518
    tags = the_branch.tags.get_tag_dict()
5050.79.6 by John Arbash Meinel
small bits of cleanup, and add timing information.
519
    t_tag_dict = time.time() - t
6024.3.6 by John Arbash Meinel
Clean up the warning messages a bit.
520
    trace.mutter('LatestPublication get_tag_dict took: %.3fs' % (t_tag_dict,))
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
521
    if latest_ver in tags:
6024.3.6 by John Arbash Meinel
Clean up the warning messages a bit.
522
        trace.note('Found most recent published version: %s'
523
                   ' in packaging branch:\n  %s'
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
524
                   % (latest_ver, the_branch.base))
525
    else:
6024.3.6 by John Arbash Meinel
Clean up the warning messages a bit.
526
        place = archive.title()
527
        if series is not None:
528
            place = '%s/%s' % (place, series.title())
6024.3.7 by John Arbash Meinel
Add code to determine the moste recent tag.
529
        best_tag = lp_api_lite.get_most_recent_tag(tags, the_branch)
530
        if best_tag is None:
531
            best_message = ''
532
        else:
533
            best_message = '\nThe most recent tag found is %s' % (best_tag,)
6024.3.6 by John Arbash Meinel
Clean up the warning messages a bit.
534
        trace.warning(
535
            'Packaging branch is not up-to-date. The most recent published\n'
6024.3.7 by John Arbash Meinel
Add code to determine the moste recent tag.
536
            'version in %s is %s, but it is not in the branch tags for:\n  %s%s'
537
            % (place, latest_ver, the_branch.base, best_message))
5050.79.5 by John Arbash Meinel
Add a Branch.open hook.
538
539
def _register_hooks():
540
    _mod_branch.Branch.hooks.install_named_hook('open',
541
        _check_is_up_to_date, 'package-branch-up-to-date')
542
543
544
_register_hooks()
545
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
546
def load_tests(basic_tests, module, loader):
547
    testmod_names = [
548
        'test_account',
549
        'test_register',
4505.6.25 by Jonathan Lange
Add a test to check what happens if launchpadlib not available.
550
        'test_lp_api',
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
551
        'test_lp_api_lite',
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
552
        'test_lp_directory',
553
        'test_lp_login',
554
        'test_lp_open',
555
        'test_lp_service',
556
        ]
557
    basic_tests.addTest(loader.loadTestsFromModuleNames(
558
            ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
559
    return basic_tests
2245.8.1 by Martin Pool
Start adding tests for launchpad indirection
560
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
561
562
_launchpad_help = """Integration with Launchpad.net
563
564
Launchpad.net provides free Bazaar branch hosting with integrated bug and
565
specification tracking.
566
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
567
The bzr client (through the plugin called 'launchpad') has special
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
568
features to communicate with Launchpad:
569
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
570
    * The launchpad-login command tells Bazaar your Launchpad user name. This
571
      is then used by the 'lp:' transport to download your branches using
572
      bzr+ssh://.
573
4258.1.1 by James Westby
Add "--fixes lp:" to the launchpad plugin documentation.
574
    * The 'lp:' transport uses Launchpad as a directory service: for example
575
      'lp:bzr' and 'lp:python' refer to the main branches of the relevant
576
      projects and may be branched, logged, etc. You can also use the 'lp:'
577
      transport to refer to specific branches, e.g. lp:~bzr/bzr/trunk.
578
579
    * The 'lp:' bug tracker alias can expand launchpad bug numbers to their
580
      URLs for use with 'bzr commit --fixes', e.g. 'bzr commit --fixes lp:12345'
581
      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
582
      Launchpad bug 12345. When you push that branch to Launchpad it will
583
      automatically be linked to the bug report.
4258.1.1 by James Westby
Add "--fixes lp:" to the launchpad plugin documentation.
584
3031.1.1 by jml at canonical
Expand the documentation on lp:// URLs and mention the launchpad-login command.
585
    * The register-branch command tells Launchpad about the url of a
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
586
      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.
587
      its contents and allow it to be attached to bugs and other
2245.8.6 by Martin Pool
Documentation under 'help launchpad'
588
      objects.
589
590
For more information see http://help.launchpad.net/
591
"""
592
topic_registry.register('launchpad',
593
    _launchpad_help,
594
    'Using Bazaar with Launchpad.net')