diff options
| author | Michael Vogt <michael.vogt@ubuntu.com> | 2010-07-02 14:50:52 +0200 |
|---|---|---|
| committer | Michael Vogt <michael.vogt@ubuntu.com> | 2010-07-02 14:50:52 +0200 |
| commit | 03ce5718b828ade3940a8dd6c57a639f0d853cfc (patch) | |
| tree | 7ca419cb5d6eee52c3302757ee8d40fb40a3b1cb | |
| parent | a90b26aad2824d4bd224586cdf14c0ad21059ac3 (diff) | |
| parent | 0c4bbfa36f36d42cc3d700e58d531e05ba898e0e (diff) | |
| download | python-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.py | 24 | ||||
| -rw-r--r-- | apt/debfile.py | 257 | ||||
| -rw-r--r-- | apt/utils.py | 3 | ||||
| -rw-r--r-- | debian/changelog | 3 | ||||
| -rw-r--r-- | po/python-apt.pot | 191 | ||||
| -rw-r--r-- | tests/test_apt_cache.py | 22 |
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") |
