diff options
| author | Sebastian Heinlein <sebi@glatzor.de> | 2008-08-26 20:03:29 +0200 |
|---|---|---|
| committer | Sebastian Heinlein <sebi@glatzor.de> | 2008-08-26 20:03:29 +0200 |
| commit | 7d2a6c05dfd99a40aea8b34909e529f5b082ec9d (patch) | |
| tree | 6d7adab4bf13d3af137481fc6954fcc0b828ae9d | |
| parent | 423a25e57a4c07c2803ef39e2d0d7a2b73d5ab7c (diff) | |
| parent | ee8376bb4355b58b7816ab5c184dba1af231d76b (diff) | |
| download | python-apt-7d2a6c05dfd99a40aea8b34909e529f5b082ec9d.tar.gz | |
Merge with consolidate branch
| -rw-r--r-- | apt/debfile.py | 509 | ||||
| -rw-r--r-- | apt/dpkg.py | 492 | ||||
| -rw-r--r-- | apt/progress.py | 4 | ||||
| -rw-r--r-- | aptsources/__init__.py | 4 | ||||
| -rw-r--r-- | aptsources/distinfo.py | 1 | ||||
| -rw-r--r-- | debian/changelog | 6 | ||||
| -rw-r--r-- | po/python-apt.pot | 2 | ||||
| -rw-r--r-- | python/progress.cc | 6 |
8 files changed, 512 insertions, 512 deletions
diff --git a/apt/debfile.py b/apt/debfile.py index ddde5bf1..4fcd6ec0 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -1,9 +1,41 @@ -import apt_inst -import apt_pkg -from apt_inst import arCheckMember +# Copyright (c) 2005-2007 Canonical +# +# AUTHOR: +# Michael Vogt <mvo@ubuntu.com> +# +# This file is part of GDebi +# +# GDebi 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; either version 2 of the License, or (at +# your option) any later version. +# +# GDebi 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 GDebi; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import warnings +warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) +import apt_inst, apt_pkg +import apt +import sys +import os from gettext import gettext as _ +from cache import Cache +from progress import DpkgInstallProgress +# Constants for comparing the local package file with the version in the cache +(VERSION_NONE, + VERSION_OUTDATED, + VERSION_SAME, + VERSION_NEWER) = range(4) + class NoDebArchiveException(IOError): pass @@ -11,15 +43,22 @@ class DebPackage(object): _supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma") - def __init__(self, filename=None): - self._section = {} + debug = 0 + + def __init__(self, filename=None, cache=None): + self._cache = cache + self.file = filename + self._needPkgs = [] + self._sections = {} + self._installedConflicts = set() + self._failureString = "" if filename: self.open(filename) def open(self, filename): " open given debfile " self.filename = filename - if not arCheckMember(open(self.filename), "debian-binary"): + if not apt_inst.arCheckMember(open(self.filename), "debian-binary"): raise NoDebArchiveException, _("This is not a valid DEB archive, missing '%s' member" % "debian-binary") control = apt_inst.debExtractControl(open(self.filename)) self._sections = apt_pkg.ParseSection(control) @@ -36,7 +75,7 @@ class DebPackage(object): # % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor) files.append(Name) for member in self._supported_data_members: - if arCheckMember(open(self.filename), member): + if apt_inst.arCheckMember(open(self.filename), member): try: apt_inst.debExtract(open(self.filename), extract_cb, member) break @@ -45,14 +84,456 @@ class DebPackage(object): return files filelist = property(filelist) + def _isOrGroupSatisfied(self, or_group): + """ this function gets a 'or_group' and analyzes if + at least one dependency of this group is already satisfied """ + self._dbg(2,"_checkOrGroup(): %s " % (or_group)) + + for dep in or_group: + depname = dep[0] + ver = dep[1] + oper = dep[2] + + # check for virtual pkgs + if not self._cache.has_key(depname): + if self._cache.isVirtualPackage(depname): + self._dbg(3,"_isOrGroupSatisfied(): %s is virtual dep" % depname) + for pkg in self._cache.getProvidingPackages(depname): + if pkg.isInstalled: + return True + continue + + inst = self._cache[depname] + instver = inst.installedVersion + if instver != None and apt_pkg.CheckDep(instver,oper,ver) == True: + return True + return False + + + def _satisfyOrGroup(self, or_group): + """ try to satisfy the or_group """ + + or_found = False + virtual_pkg = None + + for dep in or_group: + depname = dep[0] + ver = dep[1] + oper = dep[2] + + # if we don't have it in the cache, it may be virtual + if not self._cache.has_key(depname): + if not self._cache.isVirtualPackage(depname): + continue + providers = self._cache.getProvidingPackages(depname) + # if a package just has a single virtual provider, we + # just pick that (just like apt) + if len(providers) != 1: + continue + depname = providers[0].name + + # now check if we can satisfy the deps with the candidate(s) + # in the cache + cand = self._cache[depname] + candver = self._cache._depcache.GetCandidateVer(cand._pkg) + if not candver: + continue + if not apt_pkg.CheckDep(candver.VerStr,oper,ver): + continue + + # check if we need to install it + self._dbg(2,"Need to get: %s" % depname) + self._needPkgs.append(depname) + return True + + # if we reach this point, we failed + or_str = "" + for dep in or_group: + or_str += dep[0] + if dep != or_group[len(or_group)-1]: + or_str += "|" + self._failureString += _("Dependency is not satisfiable: %s\n" % or_str) + return False + + def _checkSinglePkgConflict(self, pkgname, ver, oper): + """ returns 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)) + pkgver = None + cand = self._cache[pkgname] + if cand.isInstalled: + pkgver = cand.installedVersion + elif cand.markedInstall: + pkgver = cand.candidateVersion + #print "pkg: %s" % pkgname + #print "ver: %s" % ver + #print "pkgver: %s " % pkgver + #print "oper: %s " % oper + if (pkgver and apt_pkg.CheckDep(pkgver,oper,ver) and + not self.replacesRealPkg(pkgname, oper, ver)): + self._failureString += _("Conflicts with the installed package '%s'" % cand.name) + return True + return False + + def _checkConflictsOrGroup(self, or_group): + """ check the or-group for conflicts with installed pkgs """ + self._dbg(2,"_checkConflictsOrGroup(): %s " % (or_group)) + + or_found = False + virtual_pkg = None + + for dep in or_group: + depname = dep[0] + ver = dep[1] + oper = dep[2] + + # check conflicts with virtual pkgs + if not self._cache.has_key(depname): + # FIXME: we have to check for virtual replaces here as + # well (to pass tests/gdebi-test8.deb) + if self._cache.isVirtualPackage(depname): + for pkg in self._cache.getProvidingPackages(depname): + self._dbg(3, "conflicts virtual check: %s" % pkg.name) + # P/C/R on virtal pkg, e.g. ftpd + if self.pkgName == pkg.name: + self._dbg(3, "conflict on self, ignoring") + continue + if self._checkSinglePkgConflict(pkg.name,ver,oper): + self._installedConflicts.add(pkg.name) + continue + if self._checkSinglePkgConflict(depname,ver,oper): + self._installedConflicts.add(depname) + return len(self._installedConflicts) != 0 + + def getConflicts(self): + """ + Return list of package names conflicting with this package. + + WARNING: This method will is deprecated. Please use the + attribute DebPackage.depends instead. + """ + return self.depends + + def conflicts(self): + """ + List of package names conflicting with this package + """ + conflicts = [] + key = "Conflicts" + if self._sections.has_key(key): + conflicts = apt_pkg.ParseDepends(self._sections[key]) + return conflicts + conflicts = property(conflicts) + + def getDepends(self): + """ + Return list of package names on which this package depends on. + + WARNING: This method will is deprecated. Please use the + attribute DebPackage.depends instead. + """ + return self.depends + + def depends(self): + """ + List of package names on which this package depends on + """ + depends = [] + # find depends + for key in ["Depends","PreDepends"]: + if self._sections.has_key(key): + depends.extend(apt_pkg.ParseDepends(self._sections[key])) + return depends + depends = property(depends) + + def getProvides(self): + """ + Return list of virtual packages which are provided by this package. + + WARNING: This method will is deprecated. Please use the + attribute DebPackage.provides instead. + """ + return self.provides + + def provides(self): + """ + List of virtual packages which are provided by this package + """ + provides = [] + key = "Provides" + if self._sections.has_key(key): + provides = apt_pkg.ParseDepends(self._sections[key]) + return provides + provides = property(provides) + + def getReplaces(self): + """ + Return list of packages which are replaced by this package. + + WARNING: This method will is deprecated. Please use the + attribute DebPackage.replaces instead. + """ + return self.replaces + + def replaces(self): + """ + List of packages which are replaced by this package + """ + replaces = [] + key = "Replaces" + if self._sections.has_key(key): + replaces = apt_pkg.ParseDepends(self._sections[key]) + return replaces + replaces = property(replaces) + def replacesRealPkg(self, pkgname, oper, ver): + """ + 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)) + pkgver = None + cand = self._cache[pkgname] + if cand.isInstalled: + pkgver = cand.installedVersion + elif cand.markedInstall: + pkgver = cand.candidateVersion + for or_group in self.getReplaces(): + for (name, ver, oper) in or_group: + if (name == pkgname and + apt_pkg.CheckDep(pkgver,oper,ver)): + self._dbg(3, "we have a replaces in our package for the conflict against '%s'" % (pkgname)) + return True + return False + + def checkConflicts(self): + """ check if the pkg conflicts with a existing or to be installed + package. Return True if the pkg is ok """ + res = True + for or_group in self.getConflicts(): + if self._checkConflictsOrGroup(or_group): + #print "Conflicts with a exisiting pkg!" + #self._failureString = "Conflicts with a exisiting pkg!" + res = False + return res + + + def compareToVersionInCache(self, useInstalled=True): + """ checks if the pkg is already installed or availabe in the cache + and if so in what version, returns if the version of the deb + is not available,older,same,newer + """ + self._dbg(3,"compareToVersionInCache") + pkgname = self._sections["Package"] + debver = self._sections["Version"] + self._dbg(1,"debver: %s" % debver) + if self._cache.has_key(pkgname): + if useInstalled: + cachever = self._cache[pkgname].installedVersion + else: + cachever = self._cache[pkgname].candidateVersion + if cachever != None: + cmp = apt_pkg.VersionCompare(cachever,debver) + self._dbg(1, "CompareVersion(debver,instver): %s" % cmp) + if cmp == 0: + return VERSION_SAME + elif cmp < 0: + return VERSION_NEWER + elif cmp > 0: + return VERSION_OUTDATED + return VERSION_NONE + + def checkDeb(self): + self._dbg(3,"checkDepends") + + # check arch + arch = self._sections["Architecture"] + if arch != "all" and arch != apt_pkg.Config.Find("APT::Architecture"): + self._dbg(1,"ERROR: Wrong architecture dude!") + self._failureString = _("Wrong architecture '%s'" % arch) + return False + + # check version + res = self.compareToVersionInCache() + if res == VERSION_OUTDATED: # the deb is older than the installed + self._failureString = _("A later version is already installed") + return False + + # FIXME: this sort of error handling sux + self._failureString = "" + + # check conflicts + if not self.checkConflicts(): + return False + + # try to satisfy the dependencies + res = self._satisfyDepends(self.getDepends()) + if not res: + return False + + # check for conflicts again (this time with the packages that are + # makeed for install) + if not self.checkConflicts(): + return False + + if self._cache._depcache.BrokenCount > 0: + self._failureString = _("Failed to satisfy all dependencies (broken cache)") + # clean the cache again + self._cache.clear() + return False + return True + + def satisfyDependsStr(self, dependsstr): + return self._satisfyDepends(apt_pkg.ParseDepends(dependsstr)) + + def _satisfyDepends(self, depends): + # turn off MarkAndSweep via a action group (if available) + try: + _actiongroup = apt_pkg.GetPkgActionGroup(self._cache._depcache) + except AttributeError, e: + pass + # check depends + for or_group in depends: + #print "or_group: %s" % or_group + #print "or_group satified: %s" % self._isOrGroupSatisfied(or_group) + if not self._isOrGroupSatisfied(or_group): + if not self._satisfyOrGroup(or_group): + return False + # now try it out in the cache + for pkg in self._needPkgs: + try: + self._cache[pkg].markInstall(fromUser=False) + except SystemError, e: + self._failureString = _("Cannot install '%s'" % pkg) + self._cache.clear() + return False + return True + + def missingDeps(self): + self._dbg(1, "Installing: %s" % self._needPkgs) + if self._needPkgs == None: + self.checkDeb() + return self._needPkgs + missingDeps = property(missingDeps) + + def requiredChanges(self): + """ gets the required changes to satisfy the depends. + returns a tuple with (install, remove, unauthenticated) + """ + install = [] + remove = [] + unauthenticated = [] + for pkg in self._cache: + if pkg.markedInstall or pkg.markedUpgrade: + install.append(pkg.name) + # check authentication, one authenticated origin is enough + # libapt will skip non-authenticated origins then + authenticated = False + for origin in pkg.candidateOrigin: + authenticated |= origin.trusted + if not authenticated: + unauthenticated.append(pkg.name) + if pkg.markedDelete: + remove.append(pkg.name) + return (install,remove, unauthenticated) + requiredChanges = property(requiredChanges) + + def _dbg(self, level, msg): + """Write debugging output to sys.stderr. + """ + if level <= self.debug: + print >> sys.stderr, msg + + def install(self, installProgress=None): + """ Install the package """ + if installProgress == None: + res = os.system("/usr/sbin/dpkg -i %s" % self.filename) + else: + installProgress.startUpdate() + res = installProgress.run(self.filename) + installProgress.finishUpdate() + return res + +class DscSrcPackage(DebPackage): + def __init__(self, filename=None, cache=None): + DebPackage.__init__(self, filename, cache) + self.depends = [] + self.conflicts = [] + self.binaries = [] + if filename != None: + self.open(filename) + def getConflicts(self): + return self.conflicts + def getDepends(self): + return self.depends + def open(self, file): + depends_tags = ["Build-Depends:", "Build-Depends-Indep:"] + conflicts_tags = ["Build-Conflicts:", "Build-Conflicts-Indep:"] + for line in open(file): + # check b-d and b-c + for tag in depends_tags: + if line.startswith(tag): + key = line[len(tag):].strip() + self.depends.extend(apt_pkg.ParseSrcDepends(key)) + for tag in conflicts_tags: + if line.startswith(tag): + key = line[len(tag):].strip() + self.conflicts.extend(apt_pkg.ParseSrcDepends(key)) + # check binary and source and version + if line.startswith("Source:"): + self.pkgName = line[len("Source:"):].strip() + if line.startswith("Binary:"): + self.binaries = [pkg.strip() for pkg in line[len("Binary:"):].split(",")] + if line.startswith("Version:"): + self._sections["Version"] = line[len("Version:"):].strip() + # we are at the end + if line.startswith("-----BEGIN PGP SIGNATURE-"): + break + s = _("Install Build-Dependencies for " + "source package '%s' that builds %s\n" + ) % (self.pkgName, " ".join(self.binaries)) + self._sections["Description"] = s + + def checkDeb(self): + if not self.checkConflicts(): + for pkgname in self._installedConflicts: + if self._cache[pkgname]._pkg.Essential: + raise Exception, _("A essential package would be removed") + self._cache[pkgname].markDelete() + # FIXME: a additional run of the checkConflicts() + # after _satisfyDepends() should probably be done + return self._satisfyDepends(self.depends) if __name__ == "__main__": - import sys - - d = DebPackage(sys.argv[1]) - print d["Section"] - print d["Maintainer"] - print "Files:" - print "\n".join(d.filelist) + + cache = Cache() + + vp = "www-browser" + print "%s virtual: %s" % (vp,cache.isVirtualPackage(vp)) + providers = cache.getProvidingPackages(vp) + print "Providers for %s :" % vp + for pkg in providers: + print " %s" % pkg.name + d = DebPackage(sys.argv[1], cache) + print "Deb: %s" % d.pkgname + if not d.checkDeb(): + print "can't be satified" + print d._failureString + print "missing deps: %s" % d.missingDeps + print d.requiredChanges + + print "Installing ..." + ret = d.install(DpkgInstallProgress()) + print ret + + #s = DscSrcPackage(cache, "../tests/3ddesktop_0.2.9-6.dsc") + #s.checkDep() + #print "Missing deps: ",s.missingDeps + #print "Print required changes: ", s.requiredChanges + + s = DscSrcPackage(cache=cache) + d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)" + print s._satisfyDepends(apt_pkg.ParseDepends(d)) diff --git a/apt/dpkg.py b/apt/dpkg.py deleted file mode 100644 index 7ebc551f..00000000 --- a/apt/dpkg.py +++ /dev/null @@ -1,492 +0,0 @@ -# Copyright (c) 2005-2007 Canonical -# -# AUTHOR: -# Michael Vogt <mvo@ubuntu.com> -# -# This file is part of GDebi -# -# GDebi 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; either version 2 of the License, or (at -# your option) any later version. -# -# GDebi 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 GDebi; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -import warnings -from warnings import warn -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) -import apt_inst, apt_pkg -import apt -import sys -import os -from gettext import gettext as _ -from cache import Cache -from progress import DpkgInstallProgress - -class DebPackage(object): - debug = 0 - - def __init__(self, cache, file=None): - cache.clear() - self._cache = cache - self.file = file - self._needPkgs = [] - self._sections = {} - self._installedConflicts = set() - self._failureString = "" - if file != None: - self.open(file) - - def open(self, file): - """ read a deb """ - control = apt_inst.debExtractControl(open(file)) - self._sections = apt_pkg.ParseSection(control) - self.pkgName = self._sections["Package"] - - def _isOrGroupSatisfied(self, or_group): - """ this function gets a 'or_group' and analyzes if - at least one dependency of this group is already satisfied """ - self._dbg(2,"_checkOrGroup(): %s " % (or_group)) - - for dep in or_group: - depname = dep[0] - ver = dep[1] - oper = dep[2] - - # check for virtual pkgs - if not self._cache.has_key(depname): - if self._cache.isVirtualPackage(depname): - self._dbg(3,"_isOrGroupSatisfied(): %s is virtual dep" % depname) - for pkg in self._cache.getProvidingPackages(depname): - if pkg.isInstalled: - return True - continue - - inst = self._cache[depname] - instver = inst.installedVersion - if instver != None and apt_pkg.CheckDep(instver,oper,ver) == True: - return True - return False - - - def _satisfyOrGroup(self, or_group): - """ try to satisfy the or_group """ - - or_found = False - virtual_pkg = None - - for dep in or_group: - depname = dep[0] - ver = dep[1] - oper = dep[2] - - # if we don't have it in the cache, it may be virtual - if not self._cache.has_key(depname): - if not self._cache.isVirtualPackage(depname): - continue - providers = self._cache.getProvidingPackages(depname) - # if a package just has a single virtual provider, we - # just pick that (just like apt) - if len(providers) != 1: - continue - depname = providers[0].name - - # now check if we can satisfy the deps with the candidate(s) - # in the cache - cand = self._cache[depname] - candver = self._cache._depcache.GetCandidateVer(cand._pkg) - if not candver: - continue - if not apt_pkg.CheckDep(candver.VerStr,oper,ver): - continue - - # check if we need to install it - self._dbg(2,"Need to get: %s" % depname) - self._needPkgs.append(depname) - return True - - # if we reach this point, we failed - or_str = "" - for dep in or_group: - or_str += dep[0] - if dep != or_group[len(or_group)-1]: - or_str += "|" - self._failureString += _("Dependency is not satisfiable: %s\n" % or_str) - return False - - def _checkSinglePkgConflict(self, pkgname, ver, oper): - """ returns 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)) - pkgver = None - cand = self._cache[pkgname] - if cand.isInstalled: - pkgver = cand.installedVersion - elif cand.markedInstall: - pkgver = cand.candidateVersion - #print "pkg: %s" % pkgname - #print "ver: %s" % ver - #print "pkgver: %s " % pkgver - #print "oper: %s " % oper - if (pkgver and apt_pkg.CheckDep(pkgver,oper,ver) and - not self.replacesRealPkg(pkgname, oper, ver)): - self._failureString += _("Conflicts with the installed package '%s'" % cand.name) - return True - return False - - def _checkConflictsOrGroup(self, or_group): - """ check the or-group for conflicts with installed pkgs """ - self._dbg(2,"_checkConflictsOrGroup(): %s " % (or_group)) - - or_found = False - virtual_pkg = None - - for dep in or_group: - depname = dep[0] - ver = dep[1] - oper = dep[2] - - # check conflicts with virtual pkgs - if not self._cache.has_key(depname): - # FIXME: we have to check for virtual replaces here as - # well (to pass tests/gdebi-test8.deb) - if self._cache.isVirtualPackage(depname): - for pkg in self._cache.getProvidingPackages(depname): - self._dbg(3, "conflicts virtual check: %s" % pkg.name) - # P/C/R on virtal pkg, e.g. ftpd - if self.pkgName == pkg.name: - self._dbg(3, "conflict on self, ignoring") - continue - if self._checkSinglePkgConflict(pkg.name,ver,oper): - self._installedConflicts.add(pkg.name) - continue - if self._checkSinglePkgConflict(depname,ver,oper): - self._installedConflicts.add(depname) - return len(self._installedConflicts) != 0 - - def getConflicts(self): - conflicts = [] - key = "Conflicts" - if self._sections.has_key(key): - conflicts = apt_pkg.ParseDepends(self._sections[key]) - return conflicts - - def getDepends(self): - depends = [] - # find depends - for key in ["Depends","PreDepends"]: - if self._sections.has_key(key): - depends.extend(apt_pkg.ParseDepends(self._sections[key])) - return depends - - def getProvides(self): - provides = [] - key = "Provides" - if self._sections.has_key(key): - provides = apt_pkg.ParseDepends(self._sections[key]) - return provides - - def getReplaces(self): - replaces = [] - key = "Replaces" - if self._sections.has_key(key): - replaces = apt_pkg.ParseDepends(self._sections[key]) - return replaces - - def replacesRealPkg(self, pkgname, oper, ver): - """ - 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)) - pkgver = None - cand = self._cache[pkgname] - if cand.isInstalled: - pkgver = cand.installedVersion - elif cand.markedInstall: - pkgver = cand.candidateVersion - for or_group in self.getReplaces(): - for (name, ver, oper) in or_group: - if (name == pkgname and - apt_pkg.CheckDep(pkgver,oper,ver)): - self._dbg(3, "we have a replaces in our package for the conflict against '%s'" % (pkgname)) - return True - return False - - def checkConflicts(self): - """ check if the pkg conflicts with a existing or to be installed - package. Return True if the pkg is ok """ - res = True - for or_group in self.getConflicts(): - if self._checkConflictsOrGroup(or_group): - #print "Conflicts with a exisiting pkg!" - #self._failureString = "Conflicts with a exisiting pkg!" - res = False - return res - - # some constants - (NO_VERSION, - VERSION_OUTDATED, - VERSION_SAME, - VERSION_IS_NEWER) = range(4) - - def compareToVersionInCache(self, useInstalled=True): - """ checks if the pkg is already installed or availabe in the cache - and if so in what version, returns if the version of the deb - is not available,older,same,newer - """ - self._dbg(3,"compareToVersionInCache") - pkgname = self._sections["Package"] - debver = self._sections["Version"] - self._dbg(1,"debver: %s" % debver) - if self._cache.has_key(pkgname): - if useInstalled: - cachever = self._cache[pkgname].installedVersion - else: - cachever = self._cache[pkgname].candidateVersion - if cachever != None: - cmp = apt_pkg.VersionCompare(cachever,debver) - self._dbg(1, "CompareVersion(debver,instver): %s" % cmp) - if cmp == 0: - return self.VERSION_SAME - elif cmp < 0: - return self.VERSION_IS_NEWER - elif cmp > 0: - return self.VERSION_OUTDATED - return self.NO_VERSION - - def checkDeb(self): - self._dbg(3,"checkDepends") - - # check arch - arch = self._sections["Architecture"] - if arch != "all" and arch != apt_pkg.Config.Find("APT::Architecture"): - self._dbg(1,"ERROR: Wrong architecture dude!") - self._failureString = _("Wrong architecture '%s'" % arch) - return False - - # check version - res = self.compareToVersionInCache() - if res == self.VERSION_OUTDATED: # the deb is older than the installed - self._failureString = _("A later version is already installed") - return False - - # FIXME: this sort of error handling sux - self._failureString = "" - - # check conflicts - if not self.checkConflicts(): - return False - - # try to satisfy the dependencies - res = self._satisfyDepends(self.getDepends()) - if not res: - return False - - # check for conflicts again (this time with the packages that are - # makeed for install) - if not self.checkConflicts(): - return False - - if self._cache._depcache.BrokenCount > 0: - self._failureString = _("Failed to satisfy all dependencies (broken cache)") - # clean the cache again - self._cache.clear() - return False - return True - - def satisfyDependsStr(self, dependsstr): - return self._satisfyDepends(apt_pkg.ParseDepends(dependsstr)) - - def _satisfyDepends(self, depends): - # turn off MarkAndSweep via a action group (if available) - try: - _actiongroup = apt_pkg.GetPkgActionGroup(self._cache._depcache) - except AttributeError, e: - pass - # check depends - for or_group in depends: - #print "or_group: %s" % or_group - #print "or_group satified: %s" % self._isOrGroupSatisfied(or_group) - if not self._isOrGroupSatisfied(or_group): - if not self._satisfyOrGroup(or_group): - return False - # now try it out in the cache - for pkg in self._needPkgs: - try: - self._cache[pkg].markInstall(fromUser=False) - except SystemError, e: - self._failureString = _("Cannot install '%s'" % pkg) - self._cache.clear() - return False - return True - - def missingDeps(self): - self._dbg(1, "Installing: %s" % self._needPkgs) - if self._needPkgs == None: - self.checkDeb() - return self._needPkgs - missingDeps = property(missingDeps) - - def requiredChanges(self): - """ gets the required changes to satisfy the depends. - returns a tuple with (install, remove, unauthenticated) - """ - install = [] - remove = [] - unauthenticated = [] - for pkg in self._cache: - if pkg.markedInstall or pkg.markedUpgrade: - install.append(pkg.name) - # check authentication, one authenticated origin is enough - # libapt will skip non-authenticated origins then - authenticated = False - for origin in pkg.candidateOrigin: - authenticated |= origin.trusted - if not authenticated: - unauthenticated.append(pkg.name) - if pkg.markedDelete: - remove.append(pkg.name) - return (install,remove, unauthenticated) - requiredChanges = property(requiredChanges) - - def filelist(self): - """ return the list of files in the deb """ - files = [] - def extract_cb(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor): - #print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u"\ - # % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor) - files.append(Name) - try: - try: - apt_inst.debExtract(open(self.file), extract_cb, "data.tar.gz") - except SystemError, e: - try: - apt_inst.debExtract(open(self.file), extract_cb, "data.tar.bz2") - except SystemError, e: - try: - apt_inst.debExtract(open(self.file), extract_cb, "data.tar.lzma") - except SystemError, e: - return [_("List of files could not be read, please report this as a bug")] - # IOError may happen because of gvfs madness (LP: #211822) - except IOError, e: - return [_("IOError during filelist read: %s" % e)] - return files - filelist = property(filelist) - - # properties - def __getitem__(self,item): - if not self._sections.has_key(item): - # Translators: it's for missing entries in the deb package, - # e.g. a missing "Maintainer" field - return _("%s is not available" % item) - return self._sections[item] - - def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ - if level <= self.debug: - print >> sys.stderr, msg - - def install(self, installProgress=None): - """ Install the package """ - if installProgress == None: - res = os.system("/usr/sbin/dpkg -i %s" % self.file) - else: - res = installProgress.run(self.file) - return res - -class DscSrcPackage(DebPackage): - def __init__(self, cache, file=None): - DebPackage.__init__(self, cache) - self.file = file - self.depends = [] - self.conflicts = [] - self.binaries = [] - if file != None: - self.open(file) - def getConflicts(self): - return self.conflicts - def getDepends(self): - return self.depends - def open(self, file): - depends_tags = ["Build-Depends:", "Build-Depends-Indep:"] - conflicts_tags = ["Build-Conflicts:", "Build-Conflicts-Indep:"] - for line in open(file): - # check b-d and b-c - for tag in depends_tags: - if line.startswith(tag): - key = line[len(tag):].strip() - self.depends.extend(apt_pkg.ParseSrcDepends(key)) - for tag in conflicts_tags: - if line.startswith(tag): - key = line[len(tag):].strip() - self.conflicts.extend(apt_pkg.ParseSrcDepends(key)) - # check binary and source and version - if line.startswith("Source:"): - self.pkgName = line[len("Source:"):].strip() - if line.startswith("Binary:"): - self.binaries = [pkg.strip() for pkg in line[len("Binary:"):].split(",")] - if line.startswith("Version:"): - self._sections["Version"] = line[len("Version:"):].strip() - # we are at the end - if line.startswith("-----BEGIN PGP SIGNATURE-"): - break - s = _("Install Build-Dependencies for " - "source package '%s' that builds %s\n" - ) % (self.pkgName, " ".join(self.binaries)) - self._sections["Description"] = s - - def checkDeb(self): - if not self.checkConflicts(): - for pkgname in self._installedConflicts: - if self._cache[pkgname]._pkg.Essential: - raise Exception, _("A essential package would be removed") - self._cache[pkgname].markDelete() - # FIXME: a additional run of the checkConflicts() - # after _satisfyDepends() should probably be done - return self._satisfyDepends(self.depends) - -if __name__ == "__main__": - - cache = Cache() - - vp = "www-browser" - print "%s virtual: %s" % (vp,cache.isVirtualPackage(vp)) - providers = cache.getProvidingPackages(vp) - print "Providers for %s :" % vp - for pkg in providers: - print " %s" % pkg.name - - d = DebPackage(cache, sys.argv[1]) - print "Deb: %s" % d.pkgName - if not d.checkDeb(): - print "can't be satified" - print d._failureString - print "missing deps: %s" % d.missingDeps - print d.requiredChanges - - print "Installing ..." - ret = d.install(DpkgInstallProgress()) - print ret - - #s = DscSrcPackage(cache, "../tests/3ddesktop_0.2.9-6.dsc") - #s.checkDep() - #print "Missing deps: ",s.missingDeps - #print "Print required changes: ", s.requiredChanges - - s = DscSrcPackage(cache) - d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)" - print s._satisfyDepends(apt_pkg.ParseDepends(d)) - - diff --git a/apt/progress.py b/apt/progress.py index 2ef100a8..09a3fb06 100644 --- a/apt/progress.py +++ b/apt/progress.py @@ -214,7 +214,7 @@ class InstallProgress(DumbInstallProgress): if pid == 0: # child res = pm.DoInstall(self.writefd) - os.exit(res) + os._exit(res) self.child_pid = pid res = self.waitChild() return res @@ -249,7 +249,7 @@ class DpkgInstallProgress(InstallProgress): # child res = os.system("/usr/bin/dpkg --status-fd %s -i %s" % \ (self.writefd, self.debfile)) - os.exit(res) + os._exit(os.WEXITSTATUS(res)) self.child_pid = pid res = self.waitChild() return res diff --git a/aptsources/__init__.py b/aptsources/__init__.py index 8d1c8b69..d6b3605c 100644 --- a/aptsources/__init__.py +++ b/aptsources/__init__.py @@ -1 +1,5 @@ + +import apt_pkg +# init the package system +apt_pkg.init() diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py index b962def6..a6c0faf8 100644 --- a/aptsources/distinfo.py +++ b/aptsources/distinfo.py @@ -128,7 +128,6 @@ class DistInfo: base_dir = "/usr/share/python-apt/templates"): self.metarelease_uri = '' self.templates = [] - apt_pkg.init() self.arch = apt_pkg.Config.Find("APT::Architecture") location = None diff --git a/debian/changelog b/debian/changelog index 8cac6ae2..a2ae598a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,12 @@ python-apt (0.7.7.2) UNRELEASED; urgency=low - do not change working dir in debExtractArchive() (LP: #184093) * apt/cache.py: - support "in" in apt.Cache() (LP: #251587) + * python/progress.cc: + - when pulse() does not return a boolean assume "true" + (thanks to Martin Pitt for telling me about the problem) + * aptsources/__init__.py, aptsources/distinfo.py: + - run apt_pkg.init() when aptsources gets imported and not + the distinfo function -- Michael Vogt <michael.vogt@ubuntu.com> Wed, 30 Jul 2008 10:24:30 +0200 diff --git a/po/python-apt.pot b/po/python-apt.pot index 7e731689..3d513b7b 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: 2008-07-31 12:00+0200\n" +"POT-Creation-Date: 2008-08-15 09:59+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" diff --git a/python/progress.cc b/python/progress.cc index 793265db..99ad0a25 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -185,8 +185,10 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) bool res = true; if(!PyArg_Parse(result, "b", &res)) { - // mvo: this is harmless, we shouldn't print anything here - //std::cerr << "result could not be parsed" << std::endl; + // most of the time the user who subclasses the pulse() + // method forgot to add a return {True,False} so we just + // assume he wants a True + return true; } // fetching can be canceld by returning false |
