1
# Copyright (C) 2009 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
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
"""Tools for dealing with the Launchpad API."""
19
# Importing this module will be expensive, since it imports launchpadlib and
20
# its dependencies. However, our plan is to only load this module when it is
21
# needed by a command that uses it.
29
from bzrlib.plugins.launchpad.lp_registration import (
30
InvalidLaunchpadInstance,
34
from launchpadlib.credentials import Credentials
35
from launchpadlib.launchpad import (
40
from lazr.uri import URI
43
# XXX: Not the right value for Windows
44
# Look in win32 utils -- maybe wrap it up
45
CACHE_DIRECTORY = os.path.expanduser('~/.launchpadlib/cache')
48
LAUNCHPAD_API_URLS = {
49
'production': EDGE_SERVICE_ROOT,
50
'edge': EDGE_SERVICE_ROOT,
51
'staging': STAGING_SERVICE_ROOT,
52
'dev': 'https://api.launchpad.dev/beta/',
56
def _get_api_url(service):
57
"""Return the root URL of the Launchpad API.
59
e.g. For the 'edge' Launchpad service, this function returns
60
launchpadlib.launchpad.EDGE_SERVICE_ROOT.
62
:param service: A `LaunchpadService` object.
63
:return: A URL as a string.
65
if service._lp_instance is None:
66
lp_instance = service.DEFAULT_INSTANCE
68
lp_instance = service._lp_instance
70
return LAUNCHPAD_API_URLS[lp_instance]
72
raise InvalidLaunchpadInstance(lp_instance)
75
def _get_credential_path(service):
76
"""Return the path to cached credentials for 'service'.
78
:param service: A `LaunchpadService` object.
79
:return: The path to a cached credentials file, which might not exist.
81
web_root_uri = URI(_get_api_url(service))
82
credential_name = 'creds-%s-bzr' % (web_root_uri.host)
83
return os.path.join(CACHE_DIRECTORY, credential_name)
86
def _login_from_cache(consumer_name, service_root, cache_dir,
87
credential_cache, timeout=None, proxy_info=None):
88
"""Use cached credentials if they exist, log in otherwise."""
89
# XXX: make sure credentials are private
91
credentials = Credentials.load_from_path(credential_cache)
92
except (OSError, IOError):
93
launchpad = Launchpad.get_token_and_login(
94
consumer_name, service_root, cache_dir, timeout, proxy_info)
95
launchpad.credentials.save_to_path(credential_cache)
97
access_key = credentials.access_token.key
98
access_secret = credentials.access_token.secret
99
launchpad = Launchpad.login(
100
consumer_name, access_key, access_secret, service_root,
101
cache_dir, timeout, proxy_info)
105
def login(service, timeout=None, proxy_info=None):
106
"""Log in to the Launchpad API.
108
:return: The root `Launchpad` object from launchpadlib.
110
credential_path = _get_credential_path(service)
111
launchpad = _login_from_cache(
112
'bzr', _get_api_url(service), CACHE_DIRECTORY, credential_path,
114
# XXX: Why does this set the private member of a class?
115
launchpad._service = service
119
def load_branch(launchpad, branch):
120
"""Return the launchpadlib Branch object corresponding to 'branch'.
122
:param launchpad: The root `Launchpad` object from launchpadlib.
123
:param branch: A `bzrlib.branch.Branch`.
124
:raise NotLaunchpadBranch: If we cannot determine the Launchpad URL of
126
:return: A launchpadlib Branch object.
128
# XXX: Why does this need service and _guess_branch_path?
129
service = launchpad._service
130
for url in branch.get_public_branch(), branch.get_push_location():
134
path = service._guess_branch_path(url)
135
except (errors.InvalidURL, NotLaunchpadBranch):
138
trace.mutter('Guessing path: %s', path)
139
uri = launchpad._root_uri.append(path)
141
trace.mutter('Guessing url: %s', uri_str)
142
return launchpad.load(uri_str)
143
raise NotLaunchpadBranch(url)