17
17
"""Launchpad plugin commands."""
19
from __future__ import absolute_import
20
22
branch as _mod_branch,
24
from ...commands import (
26
from brzlib.commands import (
27
from ...errors import (
29
from brzlib.errors import (
31
from ...i18n import gettext
32
from ...option import (
35
from brzlib.i18n import gettext
36
from brzlib.option import (
42
class cmd_register_branch(Command):
43
__doc__ = """Register a branch with launchpad.net.
45
This command lists a bzr branch in the directory of branches on
46
launchpad.net. Registration allows the branch to be associated with
47
bugs or specifications.
49
Before using this command you must register the project to which the
50
branch belongs, and create an account for yourself on launchpad.net.
53
public_url: The publicly visible url for the branch to register.
54
This must be an http or https url (which Launchpad can read
55
from to access the branch). Local file urls, SFTP urls, and
56
bzr+ssh urls will not work.
57
If no public_url is provided, bzr will use the configured
58
public_url if there is one for the current branch, and
62
bzr register-branch http://foo.com/bzr/fooproject.mine \\
65
takes_args = ['public_url?']
68
'Launchpad project short name to associate with the branch.',
71
'Launchpad product short name to associate with the branch.',
75
'Short name for the branch; '
76
'by default taken from the last component of the url.',
78
Option('branch-title',
79
'One-sentence description of the branch.',
81
Option('branch-description',
82
'Longer description of the purpose or contents of the branch.',
85
"Branch author's email address, if not yourself.",
88
'The bug this branch fixes.',
91
'Prepare the request but don\'t actually send it.')
101
branch_description='',
105
from brzlib.plugins.launchpad.lp_registration import (
106
BranchRegistrationRequest, BranchBugLinkRequest,
107
DryRunLaunchpadService, LaunchpadService)
108
if public_url is None:
110
b = _mod_branch.Branch.open_containing('.')[0]
111
except NotBranchError:
112
raise BzrCommandError(gettext(
113
'register-branch requires a public '
114
'branch url - see bzr help register-branch.'))
115
public_url = b.get_public_branch()
116
if public_url is None:
117
raise NoPublicBranch(b)
118
if product is not None:
121
'--product is deprecated; please use --project.'))
124
rego = BranchRegistrationRequest(branch_url=public_url,
125
branch_name=branch_name,
126
branch_title=branch_title,
127
branch_description=branch_description,
128
product_name=project,
131
linko = BranchBugLinkRequest(branch_url=public_url,
134
service = LaunchpadService()
135
# This gives back the xmlrpc url that can be used for future
136
# operations on the branch. It's not so useful to print to the
137
# user since they can't do anything with it from a web browser; it
138
# might be nice for the server to tell us about an html url as
141
# Run on service entirely in memory
142
service = DryRunLaunchpadService()
143
service.gather_user_credentials()
146
linko.submit(service)
147
self.outf.write('Branch registered.\n')
38
150
class cmd_launchpad_open(Command):
39
151
__doc__ = """Open a Launchpad branch page in your web browser."""
135
246
account.set_lp_login(name)
137
248
self.outf.write(gettext("Launchpad user ID set to '%s'.\n") %
141
class cmd_launchpad_logout(Command):
142
__doc__ = """Unset the Launchpad user ID.
144
When communicating with Launchpad, some commands need to know your
145
Launchpad user ID. This command will log you out from Launchpad.
146
This means that communication with Launchpad will happen over
147
HTTPS, and will not require one of your SSH keys to be available.
149
aliases = ['lp-logout']
150
takes_options = ['verbose']
152
def run(self, verbose=False):
153
from . import account
154
old_username = account.get_lp_login()
155
if old_username is None:
156
self.outf.write(gettext('Not logged into Launchpad.\n'))
158
account.set_lp_login(None)
160
self.outf.write(gettext(
161
"Launchpad user ID %s logged out.\n") %
252
# XXX: cmd_launchpad_mirror is untested
253
class cmd_launchpad_mirror(Command):
254
__doc__ = """Ask Launchpad to mirror a branch now."""
256
aliases = ['lp-mirror']
257
takes_args = ['location?']
259
def run(self, location='.'):
260
from brzlib.plugins.launchpad import lp_api
261
from brzlib.plugins.launchpad.lp_registration import LaunchpadService
262
branch, _ = _mod_branch.Branch.open_containing(location)
263
service = LaunchpadService()
264
launchpad = lp_api.login(service)
265
lp_branch = lp_api.LaunchpadBranch.from_bzr(launchpad, branch,
266
create_missing=False)
267
lp_branch.lp.requestMirror()
165
270
class cmd_lp_propose_merge(Command):
177
282
The parameter the launchpad account name of the desired reviewer. This
178
283
may optionally be followed by '=' and the review type. For example:
180
brz lp-propose-merge --review jrandom --review review-team=qa
285
bzr lp-propose-merge --review jrandom --review review-team=qa
182
287
This will propose a merge, request "jrandom" to perform a review of
183
288
unspecified type, and request "review-team" to perform a "qa" review.
187
291
takes_options = [Option('staging',
188
292
help='Propose the merge on staging.'),
189
Option('message', short_name='m', type=str,
293
Option('message', short_name='m', type=unicode,
190
294
help='Commit message.'),
191
295
Option('approve',
192
296
help=('Mark the proposal as approved immediately, '
193
297
'setting the approved revision to tip.')),
194
298
Option('fixes', 'The bug this proposal fixes.', str),
195
ListOption('review', short_name='R', type=str,
196
help='Requested reviewer and optional type.')]
299
ListOption('review', short_name='R', type=unicode,
300
help='Requested reviewer and optional type.')]
198
302
takes_args = ['submit_branch?']
240
344
So, to find the merge proposal that reviewed line 1 of README::
242
brz lp-find-proposal -r mainline:annotate:README:1
346
bzr lp-find-proposal -r mainline:annotate:README:1
245
349
takes_options = ['revision']
247
351
def run(self, revision=None):
352
from brzlib import ui
353
from brzlib.plugins.launchpad import lp_api
250
354
import webbrowser
251
355
b = _mod_branch.Branch.open_containing('.')[0]
252
with ui.ui_factory.nested_progress_bar() as pb, b.lock_read():
356
pb = ui.ui_factory.nested_progress_bar()
253
359
if revision is None:
254
360
revision_id = b.last_revision()
260
366
trace.note(gettext('%d proposals(s) found.') % len(merged))
261
367
for mp in merged:
262
368
webbrowser.open(lp_api.canonical_url(mp))
264
373
def _find_proposals(self, revision_id, pb):
265
from launchpadlib import uris
374
from brzlib.plugins.launchpad import (lp_api, lp_registration)
267
375
# "devel" because branches.getMergeProposals is not part of 1.0 API.
268
lp_base_url = uris.LPNET_SERVICE_ROOT
269
launchpad = lp_api.connect_launchpad(lp_base_url, version='devel')
376
launchpad = lp_api.login(lp_registration.LaunchpadService(),
270
378
pb.update(gettext('Finding proposals'))
271
379
return list(launchpad.branches.getMergeProposals(
272
merged_revision=revision_id.decode('utf-8')))
380
merged_revision=revision_id))