140
class LaunchpadBranch(object):
141
"""Provide bzr and lp API access to a Launchpad branch."""
143
def __init__(self, lp_branch, bzr_url, bzr_branch=None, check_update=True):
146
:param lp_branch: The Launchpad branch.
147
:param bzr_url: The URL of the Bazaar branch.
148
:param bzr_branch: An instance of the Bazaar branch.
150
self.bzr_url = bzr_url
151
self._bzr = bzr_branch
152
self._push_bzr = None
153
self._check_update = check_update
158
"""Return the bzr branch for this branch."""
159
if self._bzr is None:
160
self._bzr = branch.Branch.open(self.bzr_url)
165
"""Return the push branch for this branch."""
166
if self._push_bzr is None:
167
self._push_bzr = branch.Branch.open(self.lp.bzr_identity)
168
return self._push_bzr
171
def plausible_launchpad_url(url):
172
"""Is 'url' something that could conceivably be pushed to LP?
174
:param url: A URL that may refer to a Launchpad branch.
179
if url.startswith('lp:'):
181
regex = re.compile('([a-z]*\+)*(bzr\+ssh|http)'
182
'://bazaar.*.launchpad.net')
183
return bool(regex.match(url))
186
def candidate_urls(bzr_branch):
187
"""Iterate through related URLs that might be Launchpad URLs.
189
:param bzr_branch: A Bazaar branch to find URLs from.
190
:return: a generator of URL strings.
192
url = bzr_branch.get_public_branch()
195
url = bzr_branch.get_push_location()
198
yield bzr_branch.base
201
def tweak_url(url, launchpad):
202
"""Adjust a URL to work with staging, if needed."""
203
if str(launchpad._root_uri) != STAGING_SERVICE_ROOT:
207
return url.replace('bazaar.launchpad.net',
208
'bazaar.staging.launchpad.net')
211
def from_bzr(cls, launchpad, bzr_branch, create_missing=True):
212
"""Find a Launchpad branch from a bzr branch."""
214
for url in cls.candidate_urls(bzr_branch):
215
url = cls.tweak_url(url, launchpad)
216
if not cls.plausible_launchpad_url(url):
218
lp_branch = launchpad.branches.getByUrl(url=url)
219
if lp_branch is not None:
222
if not create_missing:
223
raise NoLaunchpadBranch(bzr_branch)
224
lp_branch = cls.create_now(launchpad, bzr_branch)
226
return cls(lp_branch, bzr_branch.base, bzr_branch, check_update)
229
def create_now(cls, launchpad, bzr_branch):
230
"""Create a Bazaar branch on Launchpad for the supplied branch."""
231
url = cls.tweak_url(bzr_branch.get_push_location(), launchpad)
232
if not cls.plausible_launchpad_url(url):
233
raise errors.BzrError('%s is not registered on Launchpad' %
235
bzr_branch.create_clone_on_transport(transport.get_transport(url))
236
lp_branch = launchpad.branches.getByUrl(url=url)
237
if lp_branch is None:
238
raise errors.BzrError('%s is not registered on Launchpad' % url)
241
def get_dev_focus(self):
242
"""Return the 'LaunchpadBranch' for the dev focus of this one."""
244
if lp_branch.project is None:
245
raise errors.BzrError('%s has no product.' %
246
lp_branch.bzr_identity)
247
dev_focus = lp_branch.project.development_focus.branch
248
if dev_focus is None:
249
raise errors.BzrError('%s has no development focus.' %
250
lp_branch.bzr_identity)
251
return LaunchpadBranch(dev_focus, dev_focus.bzr_identity)
254
"""Update the Launchpad copy of this branch."""
255
if not self._check_update:
259
if self.lp.last_scanned_id is not None:
260
if self.bzr.last_revision() == self.lp.last_scanned_id:
261
trace.note('%s is already up-to-date.' %
262
self.lp.bzr_identity)
264
graph = self.bzr.repository.get_graph()
265
if not graph.is_ancestor(self.lp.last_scanned_id,
266
self.bzr.last_revision()):
267
raise errors.DivergedBranches(self.bzr, self.push_bzr)
268
trace.note('Pushing to %s' % self.lp.bzr_identity)
269
self.bzr.push(self.push_bzr)
273
def find_lca_tree(self, other):
274
"""Find the revision tree for the LCA of this branch and other.
276
:param other: Another LaunchpadBranch
277
:return: The RevisionTree of the LCA of this branch and other.
279
graph = self.bzr.repository.get_graph(other.bzr.repository)
280
lca = graph.find_unique_lca(self.bzr.last_revision(),
281
other.bzr.last_revision())
282
return self.bzr.repository.revision_tree(lca)
128
285
def load_branch(launchpad, branch):
129
286
"""Return the launchpadlib Branch object corresponding to 'branch'.