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
295
def run(self, location='.'):
276
296
from bzrlib.plugins.launchpad import lp_api
277
297
from bzrlib.plugins.launchpad.lp_registration import LaunchpadService
278
branch = _mod_branch.Branch.open(location)
298
branch, _ = _mod_branch.Branch.open_containing(location)
279
299
service = LaunchpadService()
280
300
launchpad = lp_api.login(service)
281
lp_branch = lp_api.load_branch(launchpad, branch)
282
lp_branch.requestMirror()
301
lp_branch = lp_api.LaunchpadBranch.from_bzr(launchpad, branch,
302
create_missing=False)
303
lp_branch.lp.requestMirror()
285
306
register_command(cmd_launchpad_mirror)
348
369
register_command(cmd_lp_propose_merge)
372
class cmd_lp_find_proposal(Command):
374
__doc__ = """Find the proposal to merge this revision.
376
Finds the merge proposal(s) that discussed landing the specified revision.
377
This works only if the selected branch was the merge proposal target, and
378
if the merged_revno is recorded for the merge proposal. The proposal(s)
379
are opened in a web browser.
381
Any revision involved in the merge may be specified-- the revision in
382
which the merge was performed, or one of the revisions that was merged.
384
So, to find the merge proposal that reviewed line 1 of README::
386
bzr lp-find-proposal -r annotate:README:1
389
takes_options = ['revision']
391
def run(self, revision=None):
392
from bzrlib.plugins.launchpad import lp_api
394
b = _mod_branch.Branch.open_containing('.')[0]
395
pb = ui.ui_factory.nested_progress_bar()
398
revno = self._find_merged_revno(revision, b, pb)
399
merged = self._find_proposals(revno, b, pb)
401
raise BzrCommandError('No review found.')
402
trace.note('%d proposals(s) found.' % len(merged))
404
webbrowser.open(lp_api.canonical_url(mp))
409
def _find_merged_revno(self, revision, b, pb):
412
pb.update('Finding revision-id')
413
revision_id = revision[0].as_revision_id(b)
414
# a revno spec is necessarily on the mainline.
415
if self._is_revno_spec(revision[0]):
416
merging_revision = revision_id
418
graph = b.repository.get_graph()
419
pb.update('Finding merge')
420
merging_revision = graph.find_lefthand_merger(
421
revision_id, b.last_revision())
422
if merging_revision is None:
423
raise InvalidRevisionSpec(revision[0].user_spec, b)
424
pb.update('Finding revno')
425
return b.revision_id_to_revno(merging_revision)
427
def _find_proposals(self, revno, b, pb):
428
launchpad = lp_api.login(lp_registration.LaunchpadService())
429
pb.update('Finding Launchpad branch')
430
lpb = lp_api.LaunchpadBranch.from_bzr(launchpad, b,
431
create_missing=False)
432
pb.update('Finding proposals')
433
return list(lpb.lp.getMergeProposals(status=['Merged'],
434
merged_revnos=[revno]))
438
def _is_revno_spec(spec):
447
register_command(cmd_lp_find_proposal)
351
450
def _register_directory():
352
451
directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
353
452
'LaunchpadDirectory',
354
453
'Launchpad-based directory service',)
454
directories.register_lazy(
455
'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
456
'LaunchpadDirectory',
457
'debianlp: shortcut')
458
directories.register_lazy(
459
'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
460
'LaunchpadDirectory',
355
463
_register_directory()