13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
38
from __future__ import absolute_import
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Launchpad.net integration plugin for Bazaar."""
40
19
# The XMLRPC server address can be overridden by setting the environment
41
# variable $BZR_LP_XMLRPC_URL
43
# see http://wiki.bazaar.canonical.com/Specs/BranchRegistrationTool
46
branch as _mod_branch,
47
config as _mod_config,
49
# Since we are a built-in plugin we share the bzrlib version
53
from bzrlib.commands import (
20
# variable $BZR_LP_XMLRPL_URL
22
# see http://bazaar-vcs.org/Specs/BranchRegistrationTool
24
from bzrlib.branch import Branch
25
from bzrlib.commands import Command, Option, register_command
56
26
from bzrlib.directory_service import directories
27
from bzrlib.errors import BzrCommandError, NoPublicBranch, NotBranchError
57
28
from bzrlib.help_topics import topic_registry
59
for klsname, aliases in [
60
("cmd_register_branch", []),
61
("cmd_launchpad_open", ["lp-open"]),
62
("cmd_launchpad_login", ["lp-login"]),
63
("cmd_launchpad_mirror", ["lp-mirror"]),
64
("cmd_lp_propose_merge", ["lp-submit", "lp-propose"]),
65
("cmd_lp_find_proposal", [])]:
66
plugin_cmds.register_lazy(klsname, aliases,
67
"bzrlib.plugins.launchpad.cmds")
31
class cmd_register_branch(Command):
32
"""Register a branch with launchpad.net.
34
This command lists a bzr branch in the directory of branches on
35
launchpad.net. Registration allows the branch to be associated with
36
bugs or specifications.
38
Before using this command you must register the product to which the
39
branch belongs, and create an account for yourself on launchpad.net.
42
public_url: The publicly visible url for the branch to register.
43
This must be an http or https url (which Launchpad can read
44
from to access the branch). Local file urls, SFTP urls, and
45
bzr+ssh urls will not work.
46
If no public_url is provided, bzr will use the configured
47
public_url if there is one for the current branch, and
51
bzr register-branch http://foo.com/bzr/fooproduct.mine \\
54
takes_args = ['public_url?']
57
'Launchpad product short name to associate with the branch.',
60
'Short name for the branch; '
61
'by default taken from the last component of the url.',
63
Option('branch-title',
64
'One-sentence description of the branch.',
66
Option('branch-description',
67
'Longer description of the purpose or contents of the branch.',
70
"Branch author's email address, if not yourself.",
73
'The bug this branch fixes.',
76
'Prepare the request but don\'t actually send it.')
85
branch_description='',
89
from bzrlib.plugins.launchpad.lp_registration import (
90
LaunchpadService, BranchRegistrationRequest, BranchBugLinkRequest,
91
DryRunLaunchpadService)
92
if public_url is None:
94
b = Branch.open_containing('.')[0]
95
except NotBranchError:
96
raise BzrCommandError('register-branch requires a public '
97
'branch url - see bzr help register-branch.')
98
public_url = b.get_public_branch()
99
if public_url is None:
100
raise NoPublicBranch(b)
102
rego = BranchRegistrationRequest(branch_url=public_url,
103
branch_name=branch_name,
104
branch_title=branch_title,
105
branch_description=branch_description,
106
product_name=product,
109
linko = BranchBugLinkRequest(branch_url=public_url,
112
service = LaunchpadService()
113
# This gives back the xmlrpc url that can be used for future
114
# operations on the branch. It's not so useful to print to the
115
# user since they can't do anything with it from a web browser; it
116
# might be nice for the server to tell us about an html url as
119
# Run on service entirely in memory
120
service = DryRunLaunchpadService()
121
service.gather_user_credentials()
122
branch_object_url = rego.submit(service)
124
link_bug_url = linko.submit(service)
125
print 'Branch registered.'
127
register_command(cmd_register_branch)
130
class cmd_launchpad_login(Command):
131
"""Show or set the Launchpad user ID.
133
When communicating with Launchpad, some commands need to know your
134
Launchpad user ID. This command can be used to set or show the
135
user ID that Bazaar will use for such communication.
138
Show the Launchpad ID of the current user::
142
Set the Launchpad ID of the current user to 'bob'::
144
bzr launchpad-login bob
146
aliases = ['lp-login']
147
takes_args = ['name?']
150
"Don't check that the user name is valid."),
153
def run(self, name=None, no_check=False):
154
from bzrlib.plugins.launchpad import account
155
check_account = not no_check
158
username = account.get_lp_login()
161
account.check_lp_login(username)
162
self.outf.write(username + '\n')
164
self.outf.write('No Launchpad user ID configured.\n')
168
account.check_lp_login(name)
169
account.set_lp_login(name)
171
register_command(cmd_launchpad_login)
70
174
def _register_directory():
71
175
directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
72
176
'LaunchpadDirectory',
73
177
'Launchpad-based directory service',)
74
directories.register_lazy(
75
'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
78
directories.register_lazy(
79
'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
83
178
_register_directory()
85
# This is kept in __init__ so that we don't load lp_api_lite unless the branch
86
# actually matches. That way we can avoid importing extra dependencies like
88
_package_branch = lazy_regex.lazy_compile(
89
r'bazaar.launchpad.net.*?/'
90
r'(?P<user>~[^/]+/)?(?P<archive>ubuntu|debian)/(?P<series>[^/]+/)?'
91
r'(?P<project>[^/]+)(?P<branch>/[^/]+)?'
94
def _get_package_branch_info(url):
95
"""Determine the packaging information for this URL.
97
:return: If this isn't a packaging branch, return None. If it is, return
98
(archive, series, project)
102
m = _package_branch.search(url)
105
archive, series, project, user = m.group('archive', 'series',
107
if series is not None:
108
# series is optional, so the regex includes the extra '/', we don't
109
# want to send that on (it causes Internal Server Errors.)
110
series = series.strip('/')
112
user = user.strip('~/')
113
if user != 'ubuntu-branches':
115
return archive, series, project
118
def _check_is_up_to_date(the_branch):
119
info = _get_package_branch_info(the_branch.base)
122
c = the_branch.get_config_stack()
123
verbosity = c.get('launchpad.packaging_verbosity')
125
trace.mutter('not checking %s because verbosity is turned off'
126
% (the_branch.base,))
128
archive, series, project = info
129
from bzrlib.plugins.launchpad import lp_api_lite
130
latest_pub = lp_api_lite.LatestPublication(archive, series, project)
131
lp_api_lite.report_freshness(the_branch, verbosity, latest_pub)
134
def _register_hooks():
135
_mod_branch.Branch.hooks.install_named_hook('open',
136
_check_is_up_to_date, 'package-branch-up-to-date')
141
def load_tests(basic_tests, module, loader):
152
basic_tests.addTest(loader.loadTestsFromModuleNames(
153
["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
182
"""Called by bzrlib to fetch tests for this plugin"""
183
from unittest import TestSuite, TestLoader
184
from bzrlib.plugins.launchpad import (
185
test_account, test_lp_directory, test_lp_service, test_register,
188
loader = TestLoader()
196
suite.addTests(loader.loadTestsFromModule(module))
157
199
_launchpad_help = """Integration with Launchpad.net
166
208
is then used by the 'lp:' transport to download your branches using
169
* The 'lp:' transport uses Launchpad as a directory service: for example
170
'lp:bzr' and 'lp:python' refer to the main branches of the relevant
171
projects and may be branched, logged, etc. You can also use the 'lp:'
172
transport to refer to specific branches, e.g. lp:~bzr/bzr/trunk.
174
* The 'lp:' bug tracker alias can expand launchpad bug numbers to their
175
URLs for use with 'bzr commit --fixes', e.g. 'bzr commit --fixes lp:12345'
176
will record a revision property that marks that revision as fixing
177
Launchpad bug 12345. When you push that branch to Launchpad it will
178
automatically be linked to the bug report.
180
211
* The register-branch command tells Launchpad about the url of a
181
212
public branch. Launchpad will then mirror the branch, display
182
213
its contents and allow it to be attached to bugs and other
216
* The 'lp:' transport uses Launchpad as a directory service: for example
217
'lp:bzr' and 'lp:python' refer to the main branches of the relevant
218
projects and may be branched, logged, etc. You can also use the 'lp:'
219
transport to refer to specific branches, e.g. lp:///~bzr/bzr/trunk.
185
221
For more information see http://help.launchpad.net/
187
223
topic_registry.register('launchpad',
189
225
'Using Bazaar with Launchpad.net')
191
_mod_config.option_registry.register(
192
_mod_config.Option('launchpad.packaging_verbosity', default=True,
193
from_unicode=_mod_config.bool_from_store,
195
Whether to warn if a UDD package import branch is accessed that is out of date.
197
Setting this option to 'off' will disable verbosity.
199
_mod_config.option_registry.register(
200
_mod_config.Option('launchpad_username', default=None,
201
help="The username to login with when conneting to Launchpad."))