47
47
STAGING_SERVICE_ROOT,
50
from launchpadlib import uris
52
LPNET_SERVICE_ROOT = getattr(uris, 'LPNET_SERVICE_ROOT',
53
'https://api.launchpad.net/beta/')
54
QASTAGING_SERVICE_ROOT = getattr(uris, 'QASTAGING_SERVICE_ROOT',
55
'https://api.qastaging.launchpad.net/')
52
57
# Declare the minimum version of launchpadlib that we need in order to work.
53
58
# 1.5.1 is the version of launchpadlib packaged in Ubuntu 9.10, the most
74
79
installed_version, installed_version)
77
# The older versions of launchpadlib only provided service root constants for
78
# edge and staging, whilst newer versions drop edge. Therefore service root
79
# URIs for which we do not always have constants are derived from the staging
80
# one, which does always exist.
82
# It is necessary to derive, rather than use hardcoded URIs because
83
# launchpadlib <= 1.5.4 requires service root URIs that end in a path of
84
# /beta/, whilst launchpadlib >= 1.5.5 requires service root URIs with no path
87
# Once we have a hard dependency on launchpadlib >= 1.5.4 we can replace all of
88
# bzr's local knowledge of individual Launchpad instances with use of the
89
# launchpadlib.uris module.
90
82
LAUNCHPAD_API_URLS = {
91
'production': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
93
'qastaging': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
94
'api.qastaging.launchpad.net'),
83
'production': LPNET_SERVICE_ROOT,
84
'qastaging': QASTAGING_SERVICE_ROOT,
95
85
'staging': STAGING_SERVICE_ROOT,
96
'dev': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
86
'dev': 'https://api.launchpad.dev/beta/',
208
194
if str(launchpad._root_uri) == STAGING_SERVICE_ROOT:
209
195
return url.replace('bazaar.launchpad.net',
210
196
'bazaar.staging.launchpad.net')
211
elif str(launchpad._root_uri) == LAUNCHPAD_API_URLS['qastaging']:
197
elif str(launchpad._root_uri) == QASTAGING_SERVICE_ROOT:
212
198
return url.replace('bazaar.launchpad.net',
213
199
'bazaar.qastaging.launchpad.net')
236
222
"""Create a Bazaar branch on Launchpad for the supplied branch."""
237
223
url = cls.tweak_url(bzr_branch.get_push_location(), launchpad)
238
224
if not cls.plausible_launchpad_url(url):
239
raise errors.BzrError(gettext('%s is not registered on Launchpad') %
225
raise errors.BzrError('%s is not registered on Launchpad' %
241
227
bzr_branch.create_clone_on_transport(transport.get_transport(url))
242
228
lp_branch = launchpad.branches.getByUrl(url=url)
243
229
if lp_branch is None:
244
raise errors.BzrError(gettext('%s is not registered on Launchpad') %
230
raise errors.BzrError('%s is not registered on Launchpad' % url)
248
233
def get_target(self):
249
234
"""Return the 'LaunchpadBranch' for the target of this one."""
250
235
lp_branch = self.lp
251
236
if lp_branch.project is not None:
252
dev_focus = lp_branch.project.development_focus
237
dev_focus = lp_branch.project.development_focus.branch
253
238
if dev_focus is None:
254
raise errors.BzrError(gettext('%s has no development focus.') %
239
raise errors.BzrError('%s has no development focus.' %
255
240
lp_branch.bzr_identity)
256
241
target = dev_focus.branch
257
242
if target is None:
258
raise errors.BzrError(gettext(
259
'development focus %s has no branch.') % dev_focus)
243
raise errors.BzrError('development focus %s has no branch.' % dev_focus)
260
244
elif lp_branch.sourcepackage is not None:
261
245
target = lp_branch.sourcepackage.getBranch(pocket="Release")
262
246
if target is None:
263
raise errors.BzrError(gettext(
264
'source package %s has no branch.') %
247
raise errors.BzrError('source package %s has no branch.' %
265
248
lp_branch.sourcepackage)
267
raise errors.BzrError(gettext(
268
'%s has no associated product or source package.') %
250
raise errors.BzrError('%s has no associated product or source package.' %
269
251
lp_branch.bzr_identity)
270
252
return LaunchpadBranch(target, target.bzr_identity)
278
260
if self.lp.last_scanned_id is not None:
279
261
if self.bzr.last_revision() == self.lp.last_scanned_id:
280
trace.note(gettext('%s is already up-to-date.') %
262
trace.note('%s is already up-to-date.' %
281
263
self.lp.bzr_identity)
283
265
graph = self.bzr.repository.get_graph()
284
266
if not graph.is_ancestor(self.lp.last_scanned_id,
285
267
self.bzr.last_revision()):
286
268
raise errors.DivergedBranches(self.bzr, self.push_bzr)
287
trace.note(gettext('Pushing to %s') % self.lp.bzr_identity)
269
trace.note('Pushing to %s' % self.lp.bzr_identity)
288
270
self.bzr.push(self.push_bzr)
290
272
self.bzr.unlock()
301
283
return self.bzr.repository.revision_tree(lca)
286
def load_branch(launchpad, branch):
287
"""Return the launchpadlib Branch object corresponding to 'branch'.
289
:param launchpad: The root `Launchpad` object from launchpadlib.
290
:param branch: A `bzrlib.branch.Branch`.
291
:raise NotLaunchpadBranch: If we cannot determine the Launchpad URL of
293
:return: A launchpadlib Branch object.
295
# XXX: This duplicates the "What are possible URLs for the branch that
296
# Launchpad might recognize" logic found in cmd_lp_open.
298
# XXX: This makes multiple roundtrips to Launchpad for what is
299
# conceptually a single operation -- get me the branches that match these
300
# URLs. Unfortunately, Launchpad's support for such operations is poor, so
301
# we have to allow multiple roundtrips.
302
for url in branch.get_public_branch(), branch.get_push_location():
303
lp_branch = launchpad.branches.getByUrl(url=url)
306
raise NotLaunchpadBranch(url)
304
309
def canonical_url(object):
305
310
"""Return the canonical URL for a branch."""
306
311
scheme, netloc, path, params, query, fragment = urlparse.urlparse(