From 9ba17908638c364a7d822f85f6de6550d2fe9ea1 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 23 Nov 2011 01:45:49 +0200 Subject: [PATCH] pull-lp-source, requestbackport: Take the latest version from any non-backports pocket. Implemented by making lpapicache's getSourcePackage smarter. --- backportpackage | 55 ++++++++------------------ debian/changelog | 3 ++ doc/pull-lp-source.1 | 3 ++ pull-lp-source | 4 +- requestbackport | 2 +- ubuntutools/lp/lpapicache.py | 75 ++++++++++++++++++++++++++---------- ubuntutools/misc.py | 4 +- 7 files changed, 82 insertions(+), 64 deletions(-) diff --git a/backportpackage b/backportpackage index 2de32ca..ef86b45 100755 --- a/backportpackage +++ b/backportpackage @@ -24,7 +24,6 @@ import shutil import sys import tempfile -from launchpadlib.launchpad import Launchpad import lsb_release from debian.debian_support import Version @@ -35,6 +34,9 @@ from ubuntutools.archive import (SourcePackage, DebianSourcePackage, UbuntuSourcePackage, DownloadError, rmadison) from ubuntutools.config import UDTConfig, ubu_email from ubuntutools.builder import get_builder +from ubuntutools.lp.lpapicache import (Launchpad, Distribution, + SeriesNotFoundException, + PackageNotFoundException) from ubuntutools.misc import (system_distribution, vendor_to_distroinfo, codename_to_distribution) from ubuntutools.question import YesNoQuestion @@ -144,29 +146,9 @@ def parse(args): return opts, args, config -def get_current_version(package, distribution, source_release): - info = vendor_to_distroinfo(distribution) - source_release = info().codename(source_release, default=source_release) - latest_version = None - - releases = [source_release] - if distribution.lower() == "ubuntu": - releases += [source_release + "-updates", source_release + "-security"] - - for release in releases: - for record in rmadison(distribution.lower(), package, suite=release): - if 'source' not in record: - continue - - if (not latest_version or - Version(latest_version) < Version(record['version'])): - latest_version = record['version'] - - return latest_version - -def find_release_package(launchpad, mirror, workdir, package, version, - source_release, config): +def find_release_package(mirror, workdir, package, version, source_release, + config): srcpkg = None if source_release: @@ -181,40 +163,37 @@ def find_release_package(launchpad, mirror, workdir, package, version, mirrors.append(config.get_value('%s_MIRROR' % distribution.upper())) if not version: - version = get_current_version(package, distribution, source_release) - - if not version: - error('Unable to find package %s in release %s.' % - (package, source_release)) + archive = Distribution(distribution.lower()).getArchive() + try: + spph = archive.getSourcePackage(package, source_release) + except (SeriesNotFoundException, PackageNotFoundException), e: + error(str(e)) + version = spph.getVersion() if distribution == 'Debian': srcpkg = DebianSourcePackage(package, version, workdir=workdir, - lp=launchpad, mirrors=mirrors) elif distribution == 'Ubuntu': srcpkg = UbuntuSourcePackage(package, version, workdir=workdir, - lp=launchpad, mirrors=mirrors) return srcpkg -def find_package(launchpad, mirror, workdir, package, version, source_release, - config): +def find_package(mirror, workdir, package, version, source_release, config): "Returns the SourcePackage" if package.endswith('.dsc'): return SourcePackage(version=version, dscfile=package, - workdir=workdir, lp=launchpad, - mirrors=(mirror,)) + workdir=workdir, mirrors=(mirror,)) if not source_release and not version: info = vendor_to_distroinfo(system_distribution()) source_release = info().devel() - srcpkg = find_release_package(launchpad, mirror, workdir, package, version, + srcpkg = find_release_package(mirror, workdir, package, version, source_release, config) if version and srcpkg.version != version: error('Requested backport of version %s but version of %s in %s is %s' @@ -298,8 +277,7 @@ def main(args): opts, (package_or_dsc,), config = parse(args[1:]) - script_name = os.path.basename(sys.argv[0]) - launchpad = Launchpad.login_anonymously(script_name, opts.lpinstance) + Launchpad.login_anonymously(service=opts.lpinstance) if not opts.dest_releases: distinfo = lsb_release.get_distro_information() @@ -317,8 +295,7 @@ def main(args): os.makedirs(workdir) try: - pkg = find_package(launchpad, - opts.mirror, + pkg = find_package(opts.mirror, workdir, package_or_dsc, opts.version, diff --git a/debian/changelog b/debian/changelog index 1b0552b..0fce189 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,9 @@ ubuntu-dev-tools (0.136ubuntu1) UNRELEASED; urgency=low * Use httplib2 everywhere that we do https. The python stdlib doesn't do certificate verification. * requestbackport: Check for existing backport bugs first. + * pull-lp-source, requestbackport: Take the latest version from any + non-backports pocket. Implemented by making lpapicache's getSourcePackage + smarter. -- Stefano Rivera Mon, 21 Nov 2011 09:47:00 +0200 diff --git a/doc/pull-lp-source.1 b/doc/pull-lp-source.1 index 0cb6e79..757857a 100644 --- a/doc/pull-lp-source.1 +++ b/doc/pull-lp-source.1 @@ -11,6 +11,9 @@ pull\-lp\-source \- download a source package from Launchpad \fBpull\-lp\-source\fR downloads and extracts the specified \fIversion\fR of <\fBsource package\fR> from Launchpad, or the latest version of the specified \fIrelease\fR. +To request a version from a particular pocket say +\fIrelease\fB\-\fIpocket\fR (with a magic \fB\-release\fR for only the +release pocket). If no \fIversion\fR or \fIrelease\fR is specified, the latest version in the development release will be downloaded. diff --git a/pull-lp-source b/pull-lp-source index a1fb151..fe4cebd 100755 --- a/pull-lp-source +++ b/pull-lp-source @@ -76,10 +76,10 @@ def main(): release = None pocket = None try: - (release, pocket) = split_release_pocket(version) + (release, pocket) = split_release_pocket(version, default=None) except PocketDoesNotExistError, e: pass - if release in ubuntu_info.all and pocket is not None: + if release in ubuntu_info.all: try: spph = Distribution('ubuntu').getArchive().getSourcePackage(package, release, diff --git a/requestbackport b/requestbackport index 4e4348f..6f90ff0 100755 --- a/requestbackport +++ b/requestbackport @@ -193,7 +193,7 @@ def request_backport(package_spph, source, destinations): 'package': package_spph.getPackageName(), 'version': package_spph.getVersion(), 'component': package_spph.getComponent(), - 'source': source, + 'source': package_spph.getSeriesAndPocket(), 'destinations': ', '.join(destinations), } subject = ("Please backport %(package)s %(version)s (%(component)s) " diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index deef7f6..4fc911d 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -281,7 +281,7 @@ class Archive(BaseWrapper): if '_srcpkgs' not in self.__dict__: self._srcpkgs = dict() - def getSourcePackage(self, name, series=None, pocket='Release'): + def getSourcePackage(self, name, series=None, pocket=None): ''' Returns a SourcePackagePublishingHistory object for the most recent source package in the distribution 'dist', series and @@ -289,13 +289,23 @@ class Archive(BaseWrapper): series defaults to the current development series if not specified. + pocket may be a list, if so, the highest version will be returned. + It defaults to all pockets except backports. + If the requested source package doesn't exist a PackageNotFoundException is raised. ''' - # Check if pocket has a valid value - if pocket not in _POCKETS: - raise PocketDoesNotExistError("Pocket '%s' does not exist." % - pocket) + if pocket is None: + pockets = frozenset(('Proposed', 'Updates', 'Security', 'Release')) + elif isinstance(pocket, basestring): + pockets = frozenset((pocket,)) + else: + pockets = frozenset(pocket) + + for pocket in pockets: + if pocket not in _POCKETS: + raise PocketDoesNotExistError("Pocket '%s' does not exist." % + pocket) dist = Distribution(self.distribution_link) # Check if series is already a DistoSeries object or not @@ -305,25 +315,40 @@ class Archive(BaseWrapper): else: series = dist.getDevelopmentSeries() - if (name, series.name, pocket) not in self._srcpkgs: - try: - srcpkg = self.getPublishedSources(source_name=name, - distro_series=series(), - pocket=pocket, - status='Published', - exact_match=True)[0] - index = (name, series.name, pocket) - self._srcpkgs[index] = SourcePackagePublishingHistory(srcpkg) - except IndexError: + index = (name, series.name, pockets) + if index not in self._srcpkgs: + params = { + 'source_name': name, + 'distro_series': series(), + 'status': 'Published', + 'exact_match': True, + } + if len(pockets) == 1: + params['pocket'] = list(pockets)[0] + + records = self.getPublishedSources(**params) + + latest = None + for record in records: + if record.pocket not in pockets: + continue + if latest is None or (Version(latest.source_package_version) + < Version(record.source_package_version)): + latest = record + + if latest is None: msg = "The package '%s' does not exist in the %s %s archive" % \ (name, dist.display_name, self.name) - if pocket == 'Release': - msg += " in '%s'" % series.name - else: - msg += " in '%s-%s'" % (series.name, pocket.lower()) + pockets = [series.name if pocket == 'Release' + else '%s-%s' % (series.name, pocket.lower()) + for pocket in pockets] + if len(pockets) > 1: + pockets[-2:] = [' or '.join(pockets[-2:])] + msg += " in " + ', '.join(pockets) raise PackageNotFoundException(msg) - return self._srcpkgs[(name, series.name, pocket)] + self._srcpkgs[index] = SourcePackagePublishingHistory(latest) + return self._srcpkgs[index] def copyPackage(self, source_name, version, from_archive, to_pocket, to_series=None, include_binaries=False): @@ -377,6 +402,16 @@ class SourcePackagePublishingHistory(BaseWrapper): ''' return self._lpobject.component_name + def getSeriesAndPocket(self): + ''' + Returns a human-readable release-pocket + ''' + series = DistroSeries(self._lpobject.distro_series_link) + release = series.name + if self._lpobject.pocket != 'Release': + release += '-' + self._lpobject.pocket.lower() + return release + def getChangelog(self, since_version=None): ''' Return the changelog, optionally since a particular version diff --git a/ubuntutools/misc.py b/ubuntutools/misc.py index ea5a5de..8e8fa98 100644 --- a/ubuntutools/misc.py +++ b/ubuntutools/misc.py @@ -122,7 +122,7 @@ def readlist(filename, uniq=True): return items -def split_release_pocket(release): +def split_release_pocket(release, default='Release'): '''Splits the release and pocket name. If the argument doesn't contain a pocket name then the 'Release' pocket @@ -130,7 +130,7 @@ def split_release_pocket(release): Returns the release and pocket name. ''' - pocket = 'Release' + pocket = default if release is None: raise ValueError('No release name specified')