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