You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
5.8 KiB

# Copyright 2012 Canonical Ltd.
# Author: Colin Watson <cjwatson@ubuntu.com>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Launchpad API utility functions."""
from operator import attrgetter
from debian import debian_support
from lazr.restfulclient.resource import Entry
class PackageMissing(Exception):
"Generic exception generated by `lputils`."
def __init__(self, message=None):
Exception.__init__(self, message)
self.message = message
known_pockets = (
"Security",
"Updates",
"Proposed",
"Backports",
)
ARCHIVE_REFERENCE_DESCRIPTION = (
'ARCHIVE can take one of four forms: "ubuntu" for a primary archive, '
'"~canonical-kernel-team/ubuntu/ppa" or '
'"ppa:canonical-kernel-team/ubuntu/ppa" for a PPA, or '
'"ubuntu/partner" for a partner or copy archive.')
def setup_location(args, default_pocket="Release"):
archive = None
if getattr(args, "archive", False):
# Try parsing an archive reference first.
archive = args.launchpad.archives.getByReference(
reference=args.archive)
if archive is None:
raise AssertionError("No such archive: %s" % args.archive)
else:
# Otherwise derive the archive from the deprecated
# -d/--ppa/--ppa-name/--partner options.
if isinstance(args.distribution, Entry):
distro = args.distribution
else:
distro = args.launchpad.distributions[args.distribution]
if getattr(args, "partner", False):
archive = [
archive for archive in distro.archives
if archive.name == "partner"][0]
elif getattr(args, "ppa", None):
archive = args.launchpad.people[args.ppa].getPPAByName(
distribution=distro, name=args.ppa_name)
else:
archive = distro.main_archive
args.archive = archive
args.distribution = archive.distribution
if args.suite:
if "-" in args.suite:
args.series, args.pocket = args.suite.rsplit("-", 1)
args.pocket = args.pocket.title()
if args.pocket not in known_pockets:
args.series = args.suite
args.pocket = "Release"
else:
args.series = args.suite
args.pocket = "Release"
args.series = args.distribution.getSeries(name_or_version=args.series)
else:
args.series = args.distribution.current_series
args.pocket = default_pocket
if args.pocket == "Release":
args.suite = args.series.name
else:
args.suite = "%s-%s" % (args.series.name, args.pocket.lower())
if getattr(args, "architecture", None) is not None:
args.architectures = [args.series.getDistroArchSeries(
archtag=args.architecture)]
elif getattr(args, "architectures", None) is not None:
args.architectures = sorted(
[a for a in args.series.architectures
if a.architecture_tag in args.architectures],
key=attrgetter("architecture_tag"))
else:
args.architectures = sorted(
args.series.architectures, key=attrgetter("architecture_tag"))
def find_newest_publication(method, version_attr, **kwargs):
"""Hack around being unable to pass status=("Published", "Pending")."""
published_pubs = method(status="Published", **kwargs)
pending_pubs = method(status="Pending", **kwargs)
try:
newest_published = published_pubs[0]
newest_published_ver = getattr(newest_published, version_attr)
except IndexError:
try:
return pending_pubs[0]
except IndexError:
if kwargs["version"] is not None:
try:
return method(**kwargs)[0]
except IndexError:
return None
else:
return None
try:
newest_pending = pending_pubs[0]
newest_pending_ver = getattr(newest_pending, version_attr)
except IndexError:
return newest_published
if debian_support.version_compare(
newest_published_ver, newest_pending_ver) > 0:
return newest_published
else:
return newest_pending
def find_latest_published_binaries(args, package):
target_binaries = []
for architecture in args.architectures:
binary = find_newest_publication(
args.archive.getPublishedBinaries, "binary_package_version",
binary_name=package, version=args.version,
distro_arch_series=architecture, pocket=args.pocket,
exact_match=True)
if binary is not None:
target_binaries.append(binary)
if not target_binaries:
raise PackageMissing(
"Could not find binaries for '%s/%s' in %s" %
(package, args.version, args.suite))
return target_binaries
def find_latest_published_source(args, package):
source = find_newest_publication(
args.archive.getPublishedSources, "source_package_version",
source_name=package, version=args.version,
distro_series=args.series, pocket=args.pocket, exact_match=True)
if source is None:
raise PackageMissing(
"Could not find source '%s/%s' in %s" %
(package, args.version, args.suite))
return source