From c359f7532d6fe3f5b17bb9dae4b8bc6a6282f232 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Sun, 28 Feb 2010 15:47:25 +0000 Subject: [PATCH] Debian integration: consider uninstalled packages too As well as adding installed packages to the list of candidates, also add the latest available version we could install using apt-get. --- tests/dpkg/apt-cache | 38 ++++++++++++++++++++++++ tests/testdistro.py | 12 +++++--- tests/testreader.py | 2 +- zeroinstall/injector/distro.py | 65 +++++++++++++++++++++++++++++++++++------- 4 files changed, 102 insertions(+), 15 deletions(-) create mode 100755 tests/dpkg/apt-cache diff --git a/tests/dpkg/apt-cache b/tests/dpkg/apt-cache new file mode 100755 index 0000000..45d0c63 --- /dev/null +++ b/tests/dpkg/apt-cache @@ -0,0 +1,38 @@ +#!/bin/sh +if [ "$4" = "python-bittorrent" ]; then +cat < +Original-Maintainer: Michael Janssen +Architecture: all +Source: bittorrent +Version: 3.4.2-11.1ubuntu3 +Replaces: bittorrent (<< 3.4.2-10ubuntu2) +Provides: python2.5-bittorrent, python2.6-bittorrent +Depends: python (>= 2.3), python-central (>= 0.6.11) +Filename: pool/main/b/bittorrent/python-bittorrent_3.4.2-11.1ubuntu3_all.deb +Size: 53142 +MD5sum: ba5781c15297a424fc9590d36c92851c +SHA1: f37f18302020d75354411f67a8d2d101ff056eb2 +SHA256: b16e0afba58076bc683a2a4bced8f807a5102dbe41fcde63eab2d38b86ffa621 +Description: Scatter-gather network file transfer + BitTorrent is a tool for distributing files. It's extremely + easy to use - downloads are started by clicking on hyperlinks. + Whenever more than one person is downloading at once + they send pieces of the file(s) to each other, thus relieving + the central server's bandwidth burden. Even with many + simultaneous downloads, the upload burden on the central server + remains quite small, since each new downloader introduces new + upload capacity. + . + This package contains the python modules. +Homepage: http://bitconjurer.org/BitTorrent/ +Python-Version: >= 2.3 +Bugs: https://bugs.launchpad.net/ubuntu/+filebug +Origin: Ubuntu + +EOF +fi diff --git a/tests/testdistro.py b/tests/testdistro.py index 8729114..12252d6 100755 --- a/tests/testdistro.py +++ b/tests/testdistro.py @@ -74,12 +74,16 @@ class TestDistro(BaseTest): self.assertEquals({}, self.feed.implementations) host.get_package_info('python-bittorrent', self.factory) - self.assertEquals(1, len(self.feed.implementations)) - bittorrent = self.feed.implementations['package:deb:python-bittorrent:3.4.2-10'] - self.assertEquals('3.4.2-10', bittorrent.get_version()) + self.assertEquals(2, len(self.feed.implementations)) + bittorrent_installed = self.feed.implementations['package:deb:python-bittorrent:3.4.2-10'] + bittorrent_uninstalled = self.feed.implementations['package:deb:python-bittorrent:3.4.2-11.1'] + self.assertEquals('3.4.2-10', bittorrent_installed.get_version()) + self.assertTrue(bittorrent_installed.installed) + self.assertFalse(bittorrent_uninstalled.installed) + self.feed = model.ZeroInstallFeed(empty_feed, local_path = '/empty.xml') host.get_package_info('libxcomposite-dev', self.factory) - self.assertEquals(2, len(self.feed.implementations)) + self.assertEquals(1, len(self.feed.implementations)) libxcomposite = self.feed.implementations['package:deb:libxcomposite-dev:0.3.1-1'] self.assertEquals('0.3.1-1', libxcomposite.get_version()) diff --git a/tests/testreader.py b/tests/testreader.py index d9a5cf5..36870f7 100755 --- a/tests/testreader.py +++ b/tests/testreader.py @@ -215,7 +215,7 @@ class TestReader(BaseTest): iface = model.Interface(foo_iface_uri) reader.update(iface, tmp.name, True) - assert len(iface.implementations) == 1 + assert len(iface.implementations) == 2 impl = iface.implementations['package:deb:python-bittorrent:3.4.2-10'] assert impl.id == 'package:deb:python-bittorrent:3.4.2-10' diff --git a/zeroinstall/injector/distro.py b/zeroinstall/injector/distro.py index 3b21998..88da953 100644 --- a/zeroinstall/injector/distro.py +++ b/zeroinstall/injector/distro.py @@ -7,7 +7,7 @@ Integration with native distribution package managers. # See the README file for details, or visit http://0install.net. from zeroinstall import _ -import os, re, glob +import os, re, glob, subprocess from logging import warn, info from zeroinstall.injector import namespaces, model from zeroinstall.support import basedir @@ -183,7 +183,7 @@ class CachedDistribution(Distribution): if cache_version is None: raise Exception(_('Old cache format')) - + versions = self.versions for line in stream: package, version, zi_arch = line[:-1].split('\t') @@ -220,6 +220,10 @@ class DebianDistribution(CachedDistribution): cache_leaf = 'dpkg-status.cache' + def __init__(self, dpkg_status): + CachedDistribution.__init__(self, dpkg_status) + self.apt_cache = Cache('apt-cache-cache', '/var/cache/apt/pkgcache.bin') + def generate_cache(self): cache = [] @@ -242,14 +246,55 @@ class DebianDistribution(CachedDistribution): def get_package_info(self, package, factory): try: - version, machine = self.versions[package][0] + installed_version, machine = self.versions[package][0] except KeyError: - return + installed_version = None + else: + impl = factory('package:deb:%s:%s' % (package, installed_version)) + impl.version = model.parse_version(installed_version) + if machine != '*': + impl.machine = machine - impl = factory('package:deb:%s:%s' % (package, version)) - impl.version = model.parse_version(version) - if machine != '*': - impl.machine = machine + # Check to see whether we could get a newer version using apt-get + + cached = self.apt_cache.get(package) + if cached is None: + try: + child = subprocess.Popen(['apt-cache', 'show', '--no-all-versions', '--', package], stdout = subprocess.PIPE) + arch = version = None + for line in child.stdout: + line = line.strip() + if line.startswith('Version: '): + version = line[9:] + if ':' in version: + # Debian's 'epoch' system + version = version.split(':', 1)[1] + version = try_cleanup_distro_version(version) + elif line.startswith('Architecture: '): + debarch = line[14:] + if debarch == 'amd64\n': + arch = 'x86_64' + else: + arch = '*' + if version and arch: + cached = '%s\t%s' % (version, arch) + else: + cached = '-' + child.wait() + except Exception, ex: + warn("'apt-cache show %s' failed: %s", package, ex) + cached = '-' + # (multi-arch support? can there be multiple candidates?) + self.apt_cache.put(package, cached) + + if cached != '-': + candidate_version, candidate_arch = cached.split('\t') + if candidate_version and candidate_version != installed_version: + impl = factory('package:deb:%s:%s' % (package, candidate_version)) + impl.version = model.parse_version(candidate_version) + impl.installed = False + if candidate_arch != '*': + impl.machine = candidate_arch def get_score(self, disto_name): return int(disto_name == 'Debian') @@ -258,7 +303,7 @@ class RPMDistribution(CachedDistribution): """An RPM-based distribution.""" cache_leaf = 'rpm-status.cache' - + def generate_cache(self): cache = [] @@ -351,5 +396,5 @@ def get_host_distribution(): _host_distribution = RPMDistribution(_rpm_db) else: _host_distribution = Distribution() - + return _host_distribution -- 2.11.4.GIT