/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/plugins/launchpad/lp_api.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-18 15:28:38 UTC
  • mto: This revision was merged to the branch mainline in revision 6386.
  • Revision ID: jelmer@samba.org-20111218152838-5wxpfnugk2jd625k
UseĀ absolute_import.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
 
17
from __future__ import absolute_import
 
18
 
17
19
"""Tools for dealing with the Launchpad API."""
18
20
 
19
21
# Importing this module will be expensive, since it imports launchpadlib and
23
25
 
24
26
import os
25
27
import re
 
28
import urlparse
26
29
 
27
30
from bzrlib import (
28
31
    branch,
32
35
    trace,
33
36
    transport,
34
37
    )
 
38
from bzrlib.i18n import gettext
35
39
from bzrlib.plugins.launchpad.lp_registration import (
36
40
    InvalidLaunchpadInstance,
37
 
    NotLaunchpadBranch,
38
41
    )
39
42
 
40
43
try:
43
46
    raise errors.DependencyNotPresent('launchpadlib', e)
44
47
 
45
48
from launchpadlib.launchpad import (
46
 
    EDGE_SERVICE_ROOT,
47
49
    STAGING_SERVICE_ROOT,
48
50
    Launchpad,
49
51
    )
74
76
            installed_version, installed_version)
75
77
 
76
78
 
 
79
# The older versions of launchpadlib only provided service root constants for
 
80
# edge and staging, whilst newer versions drop edge. Therefore service root
 
81
# URIs for which we do not always have constants are derived from the staging
 
82
# one, which does always exist.
 
83
#
 
84
# It is necessary to derive, rather than use hardcoded URIs because
 
85
# launchpadlib <= 1.5.4 requires service root URIs that end in a path of
 
86
# /beta/, whilst launchpadlib >= 1.5.5 requires service root URIs with no path
 
87
# info.
 
88
#
 
89
# Once we have a hard dependency on launchpadlib >= 1.5.4 we can replace all of
 
90
# bzr's local knowledge of individual Launchpad instances with use of the
 
91
# launchpadlib.uris module.
77
92
LAUNCHPAD_API_URLS = {
78
 
    'production': 'https://api.launchpad.net/beta/',
79
 
    'edge': EDGE_SERVICE_ROOT,
 
93
    'production': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
 
94
        'api.launchpad.net'),
 
95
    'qastaging': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
 
96
        'api.qastaging.launchpad.net'),
80
97
    'staging': STAGING_SERVICE_ROOT,
81
 
    'dev': 'https://api.launchpad.dev/beta/',
 
98
    'dev': STAGING_SERVICE_ROOT.replace('api.staging.launchpad.net',
 
99
        'api.launchpad.dev'),
82
100
    }
83
101
 
84
102
 
85
103
def _get_api_url(service):
86
104
    """Return the root URL of the Launchpad API.
87
105
 
88
 
    e.g. For the 'edge' Launchpad service, this function returns
89
 
    launchpadlib.launchpad.EDGE_SERVICE_ROOT.
 
106
    e.g. For the 'staging' Launchpad service, this function returns
 
107
    launchpadlib.launchpad.STAGING_SERVICE_ROOT.
90
108
 
91
109
    :param service: A `LaunchpadService` object.
92
110
    :return: A URL as a string.
101
119
        raise InvalidLaunchpadInstance(lp_instance)
102
120
 
103
121
 
 
122
class NoLaunchpadBranch(errors.BzrError):
 
123
    _fmt = 'No launchpad branch could be found for branch "%(url)s".'
 
124
 
 
125
    def __init__(self, branch):
 
126
        errors.BzrError.__init__(self, branch=branch, url=branch.base)
 
127
 
 
128
 
104
129
def login(service, timeout=None, proxy_info=None):
105
130
    """Log in to the Launchpad API.
106
131
 
112
137
        proxy_info=proxy_info)
113
138
    # XXX: Work-around a minor security bug in launchpadlib 1.5.1, which would
114
139
    # create this directory with default umask.
115
 
    os.chmod(cache_directory, 0700)
 
140
    osutils.chmod_if_possible(cache_directory, 0700)
116
141
    return launchpad
117
142
 
118
143
 
174
199
        url = bzr_branch.get_push_location()
175
200
        if url is not None:
176
201
            yield url
 
202
        url = bzr_branch.get_parent()
 
203
        if url is not None:
 
204
            yield url
177
205
        yield bzr_branch.base
178
206
 
179
207
    @staticmethod
180
208
    def tweak_url(url, launchpad):
181
209
        """Adjust a URL to work with staging, if needed."""
182
 
        if str(launchpad._root_uri) != STAGING_SERVICE_ROOT:
183
 
            return url
184
 
        if url is None:
185
 
            return None
186
 
        return url.replace('bazaar.launchpad.net',
187
 
                           'bazaar.staging.launchpad.net')
 
210
        if str(launchpad._root_uri) == STAGING_SERVICE_ROOT:
 
211
            return url.replace('bazaar.launchpad.net',
 
212
                               'bazaar.staging.launchpad.net')
 
213
        elif str(launchpad._root_uri) == LAUNCHPAD_API_URLS['qastaging']:
 
214
            return url.replace('bazaar.launchpad.net',
 
215
                               'bazaar.qastaging.launchpad.net')
 
216
        return url
188
217
 
189
218
    @classmethod
190
 
    def from_bzr(cls, launchpad, bzr_branch):
 
219
    def from_bzr(cls, launchpad, bzr_branch, create_missing=True):
191
220
        """Find a Launchpad branch from a bzr branch."""
192
221
        check_update = True
193
222
        for url in cls.candidate_urls(bzr_branch):
198
227
            if lp_branch is not None:
199
228
                break
200
229
        else:
 
230
            if not create_missing:
 
231
                raise NoLaunchpadBranch(bzr_branch)
201
232
            lp_branch = cls.create_now(launchpad, bzr_branch)
202
233
            check_update = False
203
234
        return cls(lp_branch, bzr_branch.base, bzr_branch, check_update)
207
238
        """Create a Bazaar branch on Launchpad for the supplied branch."""
208
239
        url = cls.tweak_url(bzr_branch.get_push_location(), launchpad)
209
240
        if not cls.plausible_launchpad_url(url):
210
 
            raise errors.BzrError('%s is not registered on Launchpad' %
 
241
            raise errors.BzrError(gettext('%s is not registered on Launchpad') %
211
242
                                  bzr_branch.base)
212
243
        bzr_branch.create_clone_on_transport(transport.get_transport(url))
213
244
        lp_branch = launchpad.branches.getByUrl(url=url)
214
245
        if lp_branch is None:
215
 
            raise errors.BzrError('%s is not registered on Launchpad' % url)
 
246
            raise errors.BzrError(gettext('%s is not registered on Launchpad') %
 
247
                                                                            url)
216
248
        return lp_branch
217
249
 
218
 
    def get_dev_focus(self):
219
 
        """Return the 'LaunchpadBranch' for the dev focus of this one."""
 
250
    def get_target(self):
 
251
        """Return the 'LaunchpadBranch' for the target of this one."""
220
252
        lp_branch = self.lp
221
 
        if lp_branch.project is None:
222
 
            raise errors.BzrError('%s has no product.' %
223
 
                                  lp_branch.bzr_identity)
224
 
        dev_focus = lp_branch.project.development_focus.branch
225
 
        if dev_focus is None:
226
 
            raise errors.BzrError('%s has no development focus.' %
227
 
                                  lp_branch.bzr_identity)
228
 
        return LaunchpadBranch(dev_focus, dev_focus.bzr_identity)
 
253
        if lp_branch.project is not None:
 
254
            dev_focus = lp_branch.project.development_focus
 
255
            if dev_focus is None:
 
256
                raise errors.BzrError(gettext('%s has no development focus.') %
 
257
                                  lp_branch.bzr_identity)
 
258
            target = dev_focus.branch
 
259
            if target is None:
 
260
                raise errors.BzrError(gettext(
 
261
                        'development focus %s has no branch.') % dev_focus)
 
262
        elif lp_branch.sourcepackage is not None:
 
263
            target = lp_branch.sourcepackage.getBranch(pocket="Release")
 
264
            if target is None:
 
265
                raise errors.BzrError(gettext(
 
266
                                      'source package %s has no branch.') %
 
267
                                      lp_branch.sourcepackage)
 
268
        else:
 
269
            raise errors.BzrError(gettext(
 
270
                        '%s has no associated product or source package.') %
 
271
                                  lp_branch.bzr_identity)
 
272
        return LaunchpadBranch(target, target.bzr_identity)
229
273
 
230
274
    def update_lp(self):
231
275
        """Update the Launchpad copy of this branch."""
235
279
        try:
236
280
            if self.lp.last_scanned_id is not None:
237
281
                if self.bzr.last_revision() == self.lp.last_scanned_id:
238
 
                    trace.note('%s is already up-to-date.' %
 
282
                    trace.note(gettext('%s is already up-to-date.') %
239
283
                               self.lp.bzr_identity)
240
284
                    return
241
285
                graph = self.bzr.repository.get_graph()
242
286
                if not graph.is_ancestor(self.lp.last_scanned_id,
243
287
                                         self.bzr.last_revision()):
244
288
                    raise errors.DivergedBranches(self.bzr, self.push_bzr)
245
 
                trace.note('Pushing to %s' % self.lp.bzr_identity)
 
289
                trace.note(gettext('Pushing to %s') % self.lp.bzr_identity)
246
290
            self.bzr.push(self.push_bzr)
247
291
        finally:
248
292
            self.bzr.unlock()
259
303
        return self.bzr.repository.revision_tree(lca)
260
304
 
261
305
 
262
 
def load_branch(launchpad, branch):
263
 
    """Return the launchpadlib Branch object corresponding to 'branch'.
264
 
 
265
 
    :param launchpad: The root `Launchpad` object from launchpadlib.
266
 
    :param branch: A `bzrlib.branch.Branch`.
267
 
    :raise NotLaunchpadBranch: If we cannot determine the Launchpad URL of
268
 
        `branch`.
269
 
    :return: A launchpadlib Branch object.
270
 
    """
271
 
    # XXX: This duplicates the "What are possible URLs for the branch that
272
 
    # Launchpad might recognize" logic found in cmd_lp_open.
273
 
 
274
 
    # XXX: This makes multiple roundtrips to Launchpad for what is
275
 
    # conceptually a single operation -- get me the branches that match these
276
 
    # URLs. Unfortunately, Launchpad's support for such operations is poor, so
277
 
    # we have to allow multiple roundtrips.
278
 
    for url in branch.get_public_branch(), branch.get_push_location():
279
 
        lp_branch = launchpad.branches.getByUrl(url=url)
280
 
        if lp_branch:
281
 
            return lp_branch
282
 
    raise NotLaunchpadBranch(url)
 
306
def canonical_url(object):
 
307
    """Return the canonical URL for a branch."""
 
308
    scheme, netloc, path, params, query, fragment = urlparse.urlparse(
 
309
        str(object.self_link))
 
310
    path = '/'.join(path.split('/')[2:])
 
311
    netloc = netloc.replace('api.', 'code.')
 
312
    return urlparse.urlunparse((scheme, netloc, path, params, query,
 
313
                                fragment))