14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Launchpad.net integration plugin for Bazaar."""
17
"""Launchpad.net integration plugin for Bazaar.
19
This plugin provides facilities for working with Bazaar branches that are
20
hosted on Launchpad (http://launchpad.net). It provides a directory service
21
for referring to Launchpad branches using the "lp:" prefix. For example,
22
lp:bzr refers to the Bazaar's main development branch and
23
lp:~username/project/branch-name can be used to refer to a specific branch.
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.
28
The plugin also provides the following commands:
30
launchpad-login: Show or set the Launchpad user ID
31
launchpad-open: Open a Launchpad branch page in your web browser
32
lp-propose-merge: Propose merging a branch on Launchpad
33
register-branch: Register a branch with launchpad.net
34
launchpad-mirror: Ask Launchpad to mirror a branch now
19
38
# The XMLRPC server address can be overridden by setting the environment
20
39
# variable $BZR_LP_XMLRPC_URL
22
# see http://bazaar-vcs.org/Specs/BranchRegistrationTool
41
# see http://wiki.bazaar.canonical.com/Specs/BranchRegistrationTool
24
43
# Since we are a built-in plugin we share the bzrlib version
25
44
from bzrlib import version_info
275
296
def run(self, location='.'):
276
297
from bzrlib.plugins.launchpad import lp_api
277
298
from bzrlib.plugins.launchpad.lp_registration import LaunchpadService
278
branch = _mod_branch.Branch.open(location)
299
branch, _ = _mod_branch.Branch.open_containing(location)
279
300
service = LaunchpadService()
280
301
launchpad = lp_api.login(service)
281
lp_branch = lp_api.load_branch(launchpad, branch)
282
lp_branch.requestMirror()
302
lp_branch = lp_api.LaunchpadBranch.from_bzr(launchpad, branch,
303
create_missing=False)
304
lp_branch.lp.requestMirror()
285
307
register_command(cmd_launchpad_mirror)
348
370
register_command(cmd_lp_propose_merge)
373
class cmd_lp_find_proposal(Command):
375
__doc__ = """Find the proposal to merge this revision.
377
Finds the merge proposal(s) that discussed landing the specified revision.
378
This works only if the selected branch was the merge proposal target, and
379
if the merged_revno is recorded for the merge proposal. The proposal(s)
380
are opened in a web browser.
382
Any revision involved in the merge may be specified-- the revision in
383
which the merge was performed, or one of the revisions that was merged.
385
So, to find the merge proposal that reviewed line 1 of README::
387
bzr lp-find-proposal -r annotate:README:1
390
takes_options = ['revision']
392
def run(self, revision=None):
393
from bzrlib.plugins.launchpad import lp_api
395
b = _mod_branch.Branch.open_containing('.')[0]
396
pb = ui.ui_factory.nested_progress_bar()
399
revno = self._find_merged_revno(revision, b, pb)
400
merged = self._find_proposals(revno, b, pb)
402
raise BzrCommandError('No review found.')
403
trace.note('%d proposals(s) found.' % len(merged))
405
webbrowser.open(lp_api.canonical_url(mp))
410
def _find_merged_revno(self, revision, b, pb):
413
pb.update('Finding revision-id')
414
revision_id = revision[0].as_revision_id(b)
415
# a revno spec is necessarily on the mainline.
416
if self._is_revno_spec(revision[0]):
417
merging_revision = revision_id
419
graph = b.repository.get_graph()
420
pb.update('Finding merge')
421
merging_revision = graph.find_lefthand_merger(
422
revision_id, b.last_revision())
423
if merging_revision is None:
424
raise errors.InvalidRevisionSpec(revision[0].user_spec, b)
425
pb.update('Finding revno')
426
return b.revision_id_to_revno(merging_revision)
428
def _find_proposals(self, revno, b, pb):
429
launchpad = lp_api.login(lp_registration.LaunchpadService())
430
pb.update('Finding Launchpad branch')
431
lpb = lp_api.LaunchpadBranch.from_bzr(launchpad, b,
432
create_missing=False)
433
pb.update('Finding proposals')
434
return list(lpb.lp.getMergeProposals(status=['Merged'],
435
merged_revnos=[revno]))
439
def _is_revno_spec(spec):
448
register_command(cmd_lp_find_proposal)
351
451
def _register_directory():
352
452
directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
353
453
'LaunchpadDirectory',
354
454
'Launchpad-based directory service',)
455
directories.register_lazy(
456
'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
457
'LaunchpadDirectory',
458
'debianlp: shortcut')
459
directories.register_lazy(
460
'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
461
'LaunchpadDirectory',
355
464
_register_directory()