summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2010-07-02 14:50:52 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2010-07-02 14:50:52 +0200
commit03ce5718b828ade3940a8dd6c57a639f0d853cfc (patch)
tree7ca419cb5d6eee52c3302757ee8d40fb40a3b1cb
parenta90b26aad2824d4bd224586cdf14c0ad21059ac3 (diff)
parent0c4bbfa36f36d42cc3d700e58d531e05ba898e0e (diff)
downloadpython-apt-03ce5718b828ade3940a8dd6c57a639f0d853cfc.tar.gz
merged lp:~kiwinote/python-apt/merge-gdebi-changes, this port the
DebPackage class fixes from gdebi into python-apt so that gdebi can use the class from python-apt directly
-rw-r--r--apt/cache.py24
-rw-r--r--apt/debfile.py257
-rw-r--r--apt/utils.py3
-rw-r--r--debian/changelog3
-rw-r--r--po/python-apt.pot191
-rw-r--r--tests/test_apt_cache.py22
6 files changed, 369 insertions, 131 deletions
diff --git a/apt/cache.py b/apt/cache.py
index 3962bb4f..26532c76 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -120,6 +120,7 @@ class Cache(object):
"""
if progress is None:
progress = apt.progress.base.OpProgress()
+ self.op_progress = progress
self._run_callbacks("cache_pre_open")
self._cache = apt_pkg.Cache(progress)
@@ -288,21 +289,28 @@ class Cache(object):
else:
return bool(pkg.has_provides and not pkg.has_versions)
- def get_providing_packages(self, virtual, candidate_only=True):
- """Return a list of all packages providing a virtual package.
+ def get_providing_packages(self, pkgname, candidate_only=True,
+ include_nonvirtual=False):
+ """Return a list of all packages providing a package.
Return a list of packages which provide the virtual package of the
- specified name. If 'candidate_only' is False, return all packages
- with at least one version providing the virtual package. Otherwise,
- return only those packages where the candidate version provides
- the virtual package.
+ specified name.
+
+ If 'candidate_only' is False, return all packages with at
+ least one version providing the virtual package. Otherwise,
+ return only those packages where the candidate version
+ provides the virtual package.
+
+ If 'include_nonvirtual' is True then it will search for all
+ packages providing pkgname, even if pkgname is not itself
+ a virtual pkg.
"""
providers = set()
get_candidate_ver = self._depcache.get_candidate_ver
try:
- vp = self._cache[virtual]
- if vp.has_versions:
+ vp = self._cache[pkgname]
+ if vp.has_versions and not include_nonvirtual:
return list(providers)
except KeyError:
return list(providers)
diff --git a/apt/debfile.py b/apt/debfile.py
index ccaa25e4..83a5d68c 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005-2009 Canonical
+# Copyright (c) 2005-2010 Canonical
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
@@ -17,25 +17,28 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Classes for working with locally available Debian packages."""
+import apt_inst
+import apt_pkg
+import gzip
import os
import sys
-import apt_inst
-import apt_pkg
from apt_pkg import gettext as _
-
-
-# Constants for comparing the local package file with the version in the cache
-(VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER) = range(4)
-
+from StringIO import StringIO
class NoDebArchiveException(IOError):
"""Exception which is raised if a file is no Debian archive."""
-
class DebPackage(object):
"""A Debian Package (.deb file)."""
+ # Constants for comparing the local package file with the version
+ # in the cache
+ (VERSION_NONE,
+ VERSION_OUTDATED,
+ VERSION_SAME,
+ VERSION_NEWER) = range(4)
+
_supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma")
debug = 0
@@ -53,7 +56,7 @@ class DebPackage(object):
self.open(filename)
def open(self, filename):
- " open given debfile "
+ """ open given debfile """
self.filename = filename
self._debfile = apt_inst.DebFile(self.filename)
control = self._debfile.control.extractdata("control")
@@ -90,20 +93,35 @@ class DebPackage(object):
# check for virtual pkgs
if not depname in self._cache:
if self._cache.is_virtual_package(depname):
- self._dbg(3, "_isOrGroupSatisfied(): %s is virtual dep" %
- depname)
+ self._dbg(3, "_is_or_group_satisfied(): %s is virtual dep" % depname)
for pkg in self._cache.get_providing_packages(depname):
if pkg.is_installed:
return True
continue
-
+ # check real dependency
inst = self._cache[depname].installed
if inst is not None and apt_pkg.check_dep(inst.version, oper, ver):
return True
+
+ # if no real dependency is installed, check if there is
+ # a package installed that provides this dependency
+ # (e.g. scrollkeeper dependecies are provided by rarian-compat)
+ # but only do that if there is no version required in the
+ # dependency (we do not supprot versionized dependencies)
+ if not oper:
+ for ppkg in self._cache.get_providing_packages(
+ depname, include_nonvirtual=True):
+ if ppkg.is_installed:
+ self._dbg(3, "found installed '%s' that provides '%s'" % (ppkg.name, depname))
+ return True
return False
def _satisfy_or_group(self, or_group):
"""Try to satisfy the or_group."""
+
+ or_found = False
+ virtual_pkg = None
+
for dep in or_group:
depname, ver, oper = dep
@@ -136,19 +154,18 @@ class DebPackage(object):
or_str = ""
for dep in or_group:
or_str += dep[0]
- if dep != or_group[-1]:
+ if ver and oper:
+ or_str += " (%s %s)" % (dep[2], dep[1])
+ if dep != or_group[len(or_group)-1]:
or_str += "|"
- self._failure_string += _("Dependency is not satisfiable: %s\n" %
- or_str)
+ self._failure_string += _("Dependency is not satisfiable: %s\n") % or_str
return False
def _check_single_pkg_conflict(self, pkgname, ver, oper):
"""Return True if a pkg conflicts with a real installed/marked pkg."""
# FIXME: deal with conflicts against its own provides
# (e.g. Provides: ftp-server, Conflicts: ftp-server)
- self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" %
- (pkgname, ver, oper))
-
+ self._dbg(3, "_check_single_pkg_conflict() pkg='%s' ver='%s' oper='%s'" % (pkgname, ver, oper))
pkg = self._cache[pkgname]
if pkg.is_installed:
pkgver = pkg.installed.version
@@ -163,7 +180,7 @@ class DebPackage(object):
if (apt_pkg.check_dep(pkgver, oper, ver) and not
self.replaces_real_pkg(pkgname, oper, ver)):
self._failure_string += _("Conflicts with the installed package "
- "'%s'" % pkg.name)
+ "'%s'") % pkg.name
return True
return False
@@ -171,6 +188,9 @@ class DebPackage(object):
"""Check the or-group for conflicts with installed pkgs."""
self._dbg(2, "_check_conflicts_or_group(): %s " % (or_group))
+ or_found = False
+ virtual_pkg = None
+
for dep in or_group:
depname = dep[0]
ver = dep[1]
@@ -187,7 +207,7 @@ class DebPackage(object):
if self.pkgname == pkg.name:
self._dbg(3, "conflict on self, ignoring")
continue
- if self._check_single_pkg_conflict(pkg.name, ver,
+ if self._check_single_pkg_conflict(pkg.name, ver,
oper):
self._installed_conflicts.add(pkg.name)
continue
@@ -209,7 +229,7 @@ class DebPackage(object):
"""List of package names on which this package depends on."""
depends = []
# find depends
- for key in "Depends", "PreDepends":
+ for key in "Depends", "Pre-Depends":
try:
depends.extend(apt_pkg.parse_depends(self._sections[key]))
except KeyError:
@@ -240,7 +260,7 @@ class DebPackage(object):
Return True if the deb packages replaces a real (not virtual)
packages named (pkgname, oper, ver).
"""
- self._dbg(3, "replacesPkg() %s %s %s" % (pkgname, oper, ver))
+ self._dbg(3, "replaces_real_pkg() %s %s %s" % (pkgname, oper, ver))
pkg = self._cache[pkgname]
if pkg.is_installed:
pkgver = pkg.installed.version
@@ -270,6 +290,57 @@ class DebPackage(object):
res = False
return res
+ def check_breaks_existing_packages(self):
+ """
+ check if installing the package would break exsisting
+ package on the system, e.g. system has:
+ smc depends on smc-data (= 1.4)
+ and user tries to installs smc-data 1.6
+ """
+ # show progress information as this step may take some time
+ size = float(len(self._cache))
+ steps = int(size/50)
+ debver = self._sections["Version"]
+ for (i, pkg) in enumerate(self._cache):
+ if i%steps == 0:
+ self._cache.op_progress.update(float(i)/size*100.0)
+ if not pkg.is_installed:
+ continue
+ # check if the exising dependencies are still satisfied
+ # with the package
+ ver = pkg._pkg.current_ver
+ for dep_or in pkg.installed.dependencies:
+ for dep in dep_or.or_dependencies:
+ if dep.name == self.pkgname:
+ if not apt_pkg.check_dep(debver, dep.relation, dep.version):
+ self._dbg(2, "would break (depends) %s" % pkg.name)
+ # TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+ self._failure_string += _("Breaks existing package '%(pkgname)s' dependency %(depname)s (%(deprelation)s %(depversion)s)") % {
+ 'pkgname' : pkg.name,
+ 'depname' : dep.name,
+ 'deprelation' : dep.relation,
+ 'depversion' : dep.version}
+ self._cache.op_progress.done()
+ return False
+ # now check if there are conflicts against this package on
+ # the existing system
+ if "Conflicts" in ver.depends_list:
+ for conflicts_ver_list in ver.depends_list["Conflicts"]:
+ for c_or in conflicts_ver_list:
+ if c_or.target_pkg.name == self.pkgname:
+ if apt_pkg.check_dep(debver, c_or.comp_type, c_or.target_ver):
+ self._dbg(2, "would break (conflicts) %s" % pkg.name)
+ # TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+ self._failureString += _("Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s %(targetver)s)") % {
+ 'pkgname' : pkg.name,
+ 'targetpkg' : c_or.target_pkg.name,
+ 'comptype' : c_or.comp_type,
+ 'targetver' : c_or.target_ver }
+ self._cache.op_progress.done()
+ return False
+ self._cache.op_progress.done()
+ return True
+
def compare_to_version_in_cache(self, use_installed=True):
"""Compare the package to the version available in the cache.
@@ -277,42 +348,49 @@ class DebPackage(object):
and if so in what version, returns one of (VERSION_NONE,
VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER).
"""
- self._dbg(3, "compareToVersionInCache")
+ self._dbg(3, "compare_to_version_in_cache")
pkgname = self._sections["Package"]
debver = self._sections["Version"]
self._dbg(1, "debver: %s" % debver)
if pkgname in self._cache:
if use_installed and self._cache[pkgname].installed:
cachever = self._cache[pkgname].installed.version
- else:
+ elif self._cache[pkgname].candidate:
cachever = self._cache[pkgname].candidate.version
+ else:
+ return self.VERSION_NONE
if cachever is not None:
- cmpres = apt_pkg.version_compare(cachever, debver)
- self._dbg(1, "CompareVersion(debver,instver): %s" % cmpres)
- if cmpres == 0:
- return VERSION_SAME
- elif cmpres < 0:
- return VERSION_NEWER
- elif cmpres > 0:
- return VERSION_OUTDATED
- return VERSION_NONE
+ cmp = apt_pkg.version_compare(cachever, debver)
+ self._dbg(1, "CompareVersion(debver,instver): %s" % cmp)
+ if cmp == 0:
+ return self.VERSION_SAME
+ elif cmp < 0:
+ return self.VERSION_NEWER
+ elif cmp > 0:
+ return self.VERSION_OUTDATED
+ return self.VERSION_NONE
def check(self):
"""Check if the package is installable."""
self._dbg(3, "check_depends")
# check arch
+ if not "Architecture" in self._sections:
+ self._dbg(1, "ERROR: no architecture field")
+ self._failure_string = _("No Architecture field in the package")
+ return False
arch = self._sections["Architecture"]
if arch != "all" and arch != apt_pkg.config.find("APT::Architecture"):
self._dbg(1, "ERROR: Wrong architecture dude!")
- self._failure_string = _("Wrong architecture '%s'" % arch)
+ self._failure_string = _("Wrong architecture '%s'") % arch
return False
# check version
- if self.compare_to_version_in_cache() == VERSION_OUTDATED:
- # the deb is older than the installed
- self._failure_string = _("A later version is already installed")
- return False
+ if self.compare_to_version_in_cache() == self.VERSION_OUTDATED:
+ if self._cache[self.pkgname].installed:
+ # the deb is older than the installed
+ self._failure_string = _("A later version is already installed")
+ return False
# FIXME: this sort of error handling sux
self._failure_string = ""
@@ -321,6 +399,11 @@ class DebPackage(object):
if not self.check_conflicts():
return False
+ # check if installing it would break anything on the
+ # current system
+ if not self.check_breaks_existing_packages():
+ return False
+
# try to satisfy the dependencies
if not self._satisfy_depends(self.depends):
return False
@@ -332,7 +415,7 @@ class DebPackage(object):
if self._cache._depcache.broken_count > 0:
self._failure_string = _("Failed to satisfy all dependencies "
- "(broken cache)")
+ "(broken cache)")
# clean the cache again
self._cache.clear()
return False
@@ -352,17 +435,16 @@ class DebPackage(object):
# check depends
for or_group in depends:
#print "or_group: %s" % or_group
- #print "or_group satified: %s" % self._is_or_group_satisfied(
- # or_group)
+ #print "or_group satified: %s" % self._is_or_group_satisfied(or_group)
if not self._is_or_group_satisfied(or_group):
if not self._satisfy_or_group(or_group):
return False
# now try it out in the cache
for pkg in self._need_pkgs:
try:
- self._cache[pkg].mark_install(fromUser=False)
- except SystemError:
- self._failure_string = _("Cannot install '%s'" % pkg)
+ self._cache[pkg].mark_install(from_user=False)
+ except SystemError, e:
+ self._failure_string = _("Cannot install '%s'") % pkg
self._cache.clear()
return False
return True
@@ -398,6 +480,75 @@ class DebPackage(object):
remove.append(pkg.name)
return (install, remove, unauthenticated)
+ @property
+ def control_filelist(self):
+ """ return the list of files in control.tar.gt """
+ try:
+ from debian.debfile import DebFile
+ except:
+ raise Exception(_("Python-debian module not available"))
+ content = []
+ for name in DebFile(self.filename).control:
+ if name and name != ".":
+ content.append(name)
+ return sorted(content)
+
+ def to_hex(self, in_data):
+ hex = ""
+ for (i, c) in enumerate(in_data):
+ if i%80 == 0:
+ hex += "\n"
+ hex += "%2.2x " % ord(c)
+ return hex
+
+ def to_strish(self, in_data):
+ s = ""
+ for c in in_data:
+ if ord(c) < 10 or ord(c) > 127:
+ s += " "
+ else:
+ s += c
+ return s
+
+ def _get_content(self, part, name, auto_decompress=True, auto_hex=True):
+ data = part.get_content(name)
+ # check for zip content
+ if name.endswith(".gz") and auto_decompress:
+ io = StringIO(data)
+ gz = gzip.GzipFile(fileobj=io)
+ data = _("Automatically decompressed:\n\n")
+ data += gz.read()
+ # auto-convert to hex
+ try:
+ data = unicode(data, "utf-8")
+ except Exception, e:
+ new_data = _("Automatically converted to printable ascii:\n")
+ new_data += self.to_strish(data)
+ return new_data
+ return data
+
+ def control_content(self, name):
+ """ return the content of a specific control.tar.gz file """
+ try:
+ from debian.debfile import DebFile
+ except:
+ raise Exception(_("Python-debian module not available"))
+ control = DebFile(self.filename).control
+ if name in control:
+ return self._get_content(control, name)
+ return ""
+
+ def data_content(self, name):
+ """ return the content of a specific control.tar.gz file """
+ try:
+ from debian.debfile import DebFile
+ except:
+ raise Exception(_("Python-debian module not available"))
+ data = DebFile(self.filename).data
+ if name in data:
+ return self._get_content(data, name)
+ return ""
+
def _dbg(self, level, msg):
"""Write debugging output to sys.stderr."""
if level <= self.debug:
@@ -419,18 +570,18 @@ class DebPackage(object):
install_progress.finishUpdate()
return res
-
class DscSrcPackage(DebPackage):
"""A locally available source package."""
def __init__(self, filename=None, cache=None):
DebPackage.__init__(self, None, cache)
+ self.filename = filename
self._depends = []
self._conflicts = []
self.pkgname = ""
self.binaries = []
- if filename is not None:
- self.open(filename)
+ if self.filename is not None:
+ self.open(self.filename)
@property
def depends(self):
@@ -446,7 +597,6 @@ class DscSrcPackage(DebPackage):
"""Open the package."""
depends_tags = ["Build-Depends", "Build-Depends-Indep"]
conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"]
-
fobj = open(file)
tagfile = apt_pkg.TagFile(fobj)
try:
@@ -481,11 +631,10 @@ class DscSrcPackage(DebPackage):
if self._cache[pkgname]._pkg.essential:
raise Exception(_("An essential package would be removed"))
self._cache[pkgname].mark_delete()
- # FIXME: a additional run of the checkConflicts()
- # after _satisfyDepends() should probably be done
+ # FIXME: a additional run of the check_conflicts()
+ # after _satisfy_depends() should probably be done
return self._satisfy_depends(self.depends)
-
def _test():
"""Test function"""
from apt.cache import Cache
@@ -494,7 +643,7 @@ def _test():
cache = Cache()
vp = "www-browser"
- #print "%s virtual: %s" % (vp, cache.isVirtualPackage(vp))
+ print "%s virtual: %s" % (vp, cache.is_virtual_package(vp))
providers = cache.get_providing_packages(vp)
print "Providers for %s :" % vp
for pkg in providers:
@@ -508,6 +657,8 @@ def _test():
print "missing deps: %s" % d.missing_deps
print d.required_changes
+ print d.filelist
+
print "Installing ..."
ret = d.install(DpkgInstallProgress())
print ret
diff --git a/apt/utils.py b/apt/utils.py
index 80ba6d65..4b3da39f 100644
--- a/apt/utils.py
+++ b/apt/utils.py
@@ -33,6 +33,9 @@ def get_maintenance_end_date(release_date, m_months):
support_end_year = (release_date.year + years +
(release_date.month + months)/12)
support_end_month = (release_date.month + months) % 12
+ if support_end_month == 0:
+ support_end_month = 12
+ support_end_year -= 1
return (support_end_year, support_end_month)
diff --git a/debian/changelog b/debian/changelog
index b1c7c1b5..69db957f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,9 @@ python-apt (0.7.96) UNRELEASED; urgency=low
- add new "dpkg_journal_dirty" property that can be used to
detect a interrupted dpkg (the famous
"E: dpkg was interrupted, you must manually run 'dpkg --configure -a'")
+ * merged lp:~kiwinote/python-apt/merge-gdebi-changes, this port the
+ DebPackage class fixes from gdebi into python-apt so that gdebi can
+ use the class from python-apt directly
[ Martin Pitt ]
* tests/test_apt_cache.py: Test accessing the record of all packages during
diff --git a/po/python-apt.pot b/po/python-apt.pot
index b67d7988..9c10c43f 100644
--- a/po/python-apt.pot
+++ b/po/python-apt.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-03-03 19:34+0100\n"
+"POT-Creation-Date: 2010-07-02 14:12+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -23,257 +23,267 @@ msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:12
+#: ../data/templates/Ubuntu.info.in:13
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:31
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:74
msgid "Ubuntu 10.04 'Lucid Lynx'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:30
+#: ../data/templates/Ubuntu.info.in:92
msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:72
+#: ../data/templates/Ubuntu.info.in:135
msgid "Ubuntu 9.10 'Karmic Koala'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:90
+#: ../data/templates/Ubuntu.info.in:153
msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:132
+#: ../data/templates/Ubuntu.info.in:196
msgid "Ubuntu 9.04 'Jaunty Jackalope'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:150
+#: ../data/templates/Ubuntu.info.in:214
msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:192
+#: ../data/templates/Ubuntu.info.in:257
msgid "Ubuntu 8.10 'Intrepid Ibex'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:210
+#: ../data/templates/Ubuntu.info.in:275
msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:253
+#: ../data/templates/Ubuntu.info.in:319
msgid "Ubuntu 8.04 'Hardy Heron'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:271
+#: ../data/templates/Ubuntu.info.in:337
msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:308
+#: ../data/templates/Ubuntu.info.in:382
msgid "Ubuntu 7.10 'Gutsy Gibbon'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:326
+#: ../data/templates/Ubuntu.info.in:400
msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:361
+#: ../data/templates/Ubuntu.info.in:445
msgid "Ubuntu 7.04 'Feisty Fawn'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:379
+#: ../data/templates/Ubuntu.info.in:463
msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:413
+#: ../data/templates/Ubuntu.info.in:505
msgid "Ubuntu 6.10 'Edgy Eft'"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:418
+#: ../data/templates/Ubuntu.info.in:510
msgid "Community-maintained"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:424
+#: ../data/templates/Ubuntu.info.in:516
msgid "Restricted software"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:431
+#: ../data/templates/Ubuntu.info.in:523
msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:465
+#: ../data/templates/Ubuntu.info.in:565
msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
msgstr ""
#. CompDescriptionLong
-#: ../data/templates/Ubuntu.info.in:468
+#: ../data/templates/Ubuntu.info.in:568
msgid "Canonical-supported Open Source software"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:470
+#: ../data/templates/Ubuntu.info.in:570
msgid "Community-maintained (universe)"
msgstr ""
#. CompDescriptionLong
-#: ../data/templates/Ubuntu.info.in:471
+#: ../data/templates/Ubuntu.info.in:571
msgid "Community-maintained Open Source software"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:473
+#: ../data/templates/Ubuntu.info.in:573
msgid "Non-free drivers"
msgstr ""
#. CompDescriptionLong
-#: ../data/templates/Ubuntu.info.in:474
+#: ../data/templates/Ubuntu.info.in:574
msgid "Proprietary drivers for devices"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:476
+#: ../data/templates/Ubuntu.info.in:576
msgid "Restricted software (Multiverse)"
msgstr ""
#. CompDescriptionLong
-#: ../data/templates/Ubuntu.info.in:477
+#: ../data/templates/Ubuntu.info.in:577
msgid "Software restricted by copyright or legal issues"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:483
+#: ../data/templates/Ubuntu.info.in:583
msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:495
+#: ../data/templates/Ubuntu.info.in:599
msgid "Important security updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:500
+#: ../data/templates/Ubuntu.info.in:604
msgid "Recommended updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:505
+#: ../data/templates/Ubuntu.info.in:609
msgid "Pre-released updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:510
+#: ../data/templates/Ubuntu.info.in:614
msgid "Unsupported updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:517
+#: ../data/templates/Ubuntu.info.in:625
msgid "Ubuntu 5.10 'Breezy Badger'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:531
+#: ../data/templates/Ubuntu.info.in:639
msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:543
+#: ../data/templates/Ubuntu.info.in:655
msgid "Ubuntu 5.10 Security Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:548
+#: ../data/templates/Ubuntu.info.in:660
msgid "Ubuntu 5.10 Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:553
+#: ../data/templates/Ubuntu.info.in:665
msgid "Ubuntu 5.10 Backports"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:560
+#: ../data/templates/Ubuntu.info.in:676
msgid "Ubuntu 5.04 'Hoary Hedgehog'"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:574
+#: ../data/templates/Ubuntu.info.in:690
msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:577 ../data/templates/Debian.info.in:149
+#: ../data/templates/Ubuntu.info.in:693 ../data/templates/Debian.info.in:149
msgid "Officially supported"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:586
+#: ../data/templates/Ubuntu.info.in:706
msgid "Ubuntu 5.04 Security Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:591
+#: ../data/templates/Ubuntu.info.in:711
msgid "Ubuntu 5.04 Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:596
+#: ../data/templates/Ubuntu.info.in:716
msgid "Ubuntu 5.04 Backports"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:602
+#: ../data/templates/Ubuntu.info.in:722
msgid "Ubuntu 4.10 'Warty Warthog'"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:608
+#: ../data/templates/Ubuntu.info.in:728
msgid "Community-maintained (Universe)"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:610
+#: ../data/templates/Ubuntu.info.in:730
msgid "Non-free (Multiverse)"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:616
+#: ../data/templates/Ubuntu.info.in:736
msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:619
+#: ../data/templates/Ubuntu.info.in:739
msgid "No longer officially supported"
msgstr ""
#. CompDescription
-#: ../data/templates/Ubuntu.info.in:621
+#: ../data/templates/Ubuntu.info.in:741
msgid "Restricted copyright"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:628
+#: ../data/templates/Ubuntu.info.in:748
msgid "Ubuntu 4.10 Security Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:633
+#: ../data/templates/Ubuntu.info.in:753
msgid "Ubuntu 4.10 Updates"
msgstr ""
#. Description
-#: ../data/templates/Ubuntu.info.in:638
+#: ../data/templates/Ubuntu.info.in:758
msgid "Ubuntu 4.10 Backports"
msgstr ""
@@ -384,11 +394,11 @@ msgstr ""
msgid "Invalid unicode in description for '%s' (%s). Please report."
msgstr ""
-#: ../apt/package.py:999 ../apt/package.py:1105
+#: ../apt/package.py:1007 ../apt/package.py:1112
msgid "The list of changes is not available"
msgstr ""
-#: ../apt/package.py:1109
+#: ../apt/package.py:1118
#, python-format
msgid ""
"The list of changes is not available yet.\n"
@@ -397,52 +407,97 @@ msgid ""
"until the changes become available or try again later."
msgstr ""
-#: ../apt/package.py:1115
+#: ../apt/package.py:1125
msgid ""
"Failed to download the list of changes. \n"
"Please check your Internet connection."
msgstr ""
-#: ../apt/debfile.py:73
+#: ../apt/debfile.py:142
#, python-format
-msgid "List of files for '%s' could not be read"
+msgid "Dependency is not satisfiable: %s\n"
msgstr ""
-#: ../apt/debfile.py:141
+#: ../apt/debfile.py:163
#, python-format
-msgid "Dependency is not satisfiable: %s\n"
+msgid "Conflicts with the installed package '%s'"
msgstr ""
-#: ../apt/debfile.py:165
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:297
#, python-format
-msgid "Conflicts with the installed package '%s'"
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s (%(deprelation)"
+"s %(depversion)s)"
msgstr ""
-#: ../apt/debfile.py:308
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:313
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s %"
+"(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:359
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:364
#, python-format
msgid "Wrong architecture '%s'"
msgstr ""
#. the deb is older than the installed
-#: ../apt/debfile.py:314
+#: ../apt/debfile.py:371
msgid "A later version is already installed"
msgstr ""
-#: ../apt/debfile.py:334
+#: ../apt/debfile.py:396
msgid "Failed to satisfy all dependencies (broken cache)"
msgstr ""
-#: ../apt/debfile.py:365
+#: ../apt/debfile.py:425
#, python-format
msgid "Cannot install '%s'"
msgstr ""
-#: ../apt/debfile.py:472
+#: ../apt/debfile.py:467 ../apt/debfile.py:513 ../apt/debfile.py:524
+msgid "Python-debian module not available"
+msgstr ""
+
+#: ../apt/debfile.py:497
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:503
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:549
+msgid "List of files could not be read, please report this as a bug"
+msgstr ""
+
+#: ../apt/debfile.py:552
+#, python-format
+msgid "IOError during filelist read: %s"
+msgstr ""
+
+#. Translators: it's for missing entries in the deb package,
+#. e.g. a missing "Maintainer" field
+#: ../apt/debfile.py:559
+#, python-format
+msgid "%s is not available"
+msgstr ""
+
+#: ../apt/debfile.py:632
#, python-format
msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
msgstr ""
-#: ../apt/debfile.py:482
+#: ../apt/debfile.py:642
msgid "An essential package would be removed"
msgstr ""
@@ -493,6 +548,6 @@ msgstr ""
msgid "Please insert a Disc in the drive and press enter"
msgstr ""
-#: ../apt/cache.py:131
+#: ../apt/cache.py:135
msgid "Building data structures"
msgstr ""
diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py
index b27ed778..653a0f48 100644
--- a/tests/test_apt_cache.py
+++ b/tests/test_apt_cache.py
@@ -6,12 +6,15 @@
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
"""Unit tests for verifying the correctness of check_dep, etc in apt_pkg."""
+import os
+import tempfile
import unittest
+import sys
+sys.path.insert(0, "..")
+
import apt
import apt_pkg
-import os
-import tempfile
class TestAptCache(unittest.TestCase):
@@ -42,6 +45,21 @@ class TestAptCache(unittest.TestCase):
self.assert_(len(r['Description']) > 0)
self.assert_(str(r).startswith('Package: %s\n' % pkg.name))
+ def test_get_provided_packages(self):
+ cache = apt.Cache()
+ # a true virtual pkg
+ l = cache.get_providing_packages("mail-transport-agent")
+ self.assertTrue(len(l) > 0)
+ # this is a not virtual (transitional) package provided by another
+ l = cache.get_providing_packages("scrollkeeper")
+ self.assertEqual(l, [])
+ # now inlcude nonvirtual packages in the search (rarian-compat
+ # provides scrollkeeper)
+ l = cache.get_providing_packages("scrollkeeper",
+ include_nonvirtual=True)
+ self.assertTrue(len(l), 1)
+
+
def test_dpkg_journal_dirty(self):
# backup old value
old_status = apt_pkg.Config.find_file("Dir::State::status")