diff options
| -rw-r--r-- | DistUpgrade/DistUpgradeCache.py | 192 | ||||
| -rw-r--r-- | DistUpgrade/DistUpgradeControler.py | 204 | ||||
| -rw-r--r-- | DistUpgrade/removal_blacklist.txt | 2 |
3 files changed, 198 insertions, 200 deletions
diff --git a/DistUpgrade/DistUpgradeCache.py b/DistUpgrade/DistUpgradeCache.py new file mode 100644 index 00000000..26df7144 --- /dev/null +++ b/DistUpgrade/DistUpgradeCache.py @@ -0,0 +1,192 @@ + +import apt +import apt_pkg +import os +import re + +class MyCache(apt.Cache): + # init + def __init__(self, progress=None): + apt.Cache.__init__(self, progress) + self.to_install = [] + self.to_remove = [] + # turn on debuging + apt_pkg.Config.Set("Debug::pkgProblemResolver","true") + fd = os.open(os.path.expanduser("~/dist-upgrade-apt.log"), os.O_RDWR|os.O_CREAT|os.O_TRUNC) + os.dup2(fd,1) + os.dup2(fd,2) + + # a list of regexp that are not allowed to be removed + self.removal_blacklist = [] + for line in open("removal_blacklist.txt").readlines(): + line = line.strip() + if not line == "" or line.startswith("#"): + self.removal_blacklist.append(line) + + # properties + @property + def requiredDownload(self): + """ get the size of the packages that are required to download """ + pm = apt_pkg.GetPackageManager(self._depcache) + fetcher = apt_pkg.GetAcquire() + pm.GetArchives(fetcher, self._list, self._records) + return fetcher.FetchNeeded + @property + def isBroken(self): + """ is the cache broken """ + return self._depcache.BrokenCount > 0 + + # methods + def downloadable(self, pkg, useCandidate=True): + " check if the given pkg can be downloaded " + if useCandidate: + ver = self._depcache.GetCandidateVer(pkg._pkg) + else: + ver = pkg._pkg.CurrentVer + if ver == None: + return False + return ver.Downloadable + + def fixBroken(self): + """ try to fix broken dependencies on the system, may throw + SystemError when it can't""" + return self._depcache.FixBroken() + + def create_snapshot(self): + """ create a snapshot of the current changes """ + self.to_install = [] + self.to_remove = [] + for pkg in self.getChanges(): + if pkg.markedInstall or pkg.markedUpgrade: + self.to_install.append(pkg.name) + if pkg.markedDelete: + self.to_remove.append(pkg.name) + + def restore_snapshot(self): + """ restore a snapshot """ + for pkg in self: + pkg.markKeep() + for name in self.to_remove: + pkg = self[name] + pkg.markDelete() + for name in self.to_install: + pkg = self[name] + pkg.markInstall() + + def sanityCheck(self, view): + """ check if the cache is ok and if the required metapkgs + are installed + """ + if self.isBroken: + try: + logging.debug("Have broken pkgs, trying to fix them") + self.fixBroken() + except SystemError: + view.error(_("Broken packages"), + _("Your system contains broken packages " + "that couldn't be fixed with this " + "software. " + "Please fix them first using synaptic or " + "apt-get before proceeding.")) + return False + return True + + def distUpgrade(self, view): + try: + # upgrade (and make sure this way that the cache is ok) + self.upgrade(True) + self._installMetaPkgs(view) + if not self._verifyChanges(): + raise SystemError, _("A essential package would have to be removed") + except SystemError, e: + # FIXME: change the text to something more useful + self._view.error(_("Could not calculate the upgrade"), + _("A unresolvable problem occured while " + "calculating the upgrade. Please report " + "this as a bug. ")) + logging.debug("Dist-upgrade failed: '%s'", e) + return False + return True + + def _verifyChanges(self): + """ this function tests if the current changes don't violate + our constrains (blacklisted removals etc) + """ + for pkg in self.getChanges(): + if pkg.markedDelete and self._inRemovalBlacklist(pkg.name): + logging.debug("The package '%s' is marked for removal but it's in the removal blacklist", pkg.name) + return False + return True + + def _installMetaPkgs(self, view): + # now check for ubuntu-base + if not self["ubuntu-base"].isInstalled: + self["ubuntu-base"].markInstall() + + # now check for ubuntu-desktop, kubuntu-desktop, edubuntu-desktop + metapkgs = {"ubuntu-desktop": ["gdm","gnome-panel", "ubuntu-artwork"], + "kubuntu-desktop": ["kdm", "kicker", + "kubuntu-artwork-usplash"], + "edubuntu-desktop": ["edubuntu-artwork", "tuxpaint"] + } + # helper + def metaPkgInstalled(): + metapkg_found = False + for key in metapkgs: + if self.has_key(key) and (self[key].isInstalled or self[key].markedInstall): + metapkg_found=True + return metapkg_found + # check if we have a meta-pkg, if not, try to guess which one to pick + if not metaPkgInstalled(): + logging.debug("no {ubuntu,edubuntu,kubuntu}-desktop pkg installed") + for key in metapkgs: + deps_found = True + for pkg in metapkgs[key]: + deps_found &= self.has_key(pkg) and self[pkg].isInstalled + if deps_found: + logging.debug("guessing '%s' as missing meta-pkg" % key) + try: + self[key].markInstall() + except SystemError: + logging.error("failed to mark '%s' for install" % key) + view.error(_("Can't install '%s'" % key), + _("It was impossible to install a " + "required package. Please report " + "this as a bug. ")) + return False + # check if we actually found one + if not metaPkgInstalled() and len(self.missing_pkgs) == 0: + # FIXME: provide a list + view.error(_("Can't guess meta-package"), + _("Your system does not contain a " + "ubuntu-desktop, kubuntu-desktop or " + "edubuntu-desktop package and it was not " + "possible to detect which version of " + "ubuntu you are runing.\n " + "Please install one of the packages " + "above first using synaptic or " + "apt-get before proceeding.")) + return False + + # FIXME: check for ubuntu-desktop, kubuntu-dekstop, edubuntu-desktop + return True + + def _inRemovalBlacklist(self, pkgname): + for expr in self.removal_blacklist: + if re.compile(expr).match(pkgname): + return True + return False + + def _tryMarkObsoleteForRemoval(self, pkgname, remove_candidates): + # this is a delete candidate, only actually delete, + # if it dosn't remove other packages depending on it + # that are not obsolete as well + self.cache.create_snapshot() + self.cache[pkgname].markDelete() + for pkg in self.cache.getChanges(): + if pkg.name not in remove_candidates or \ + pkg.name in self.foreign_pkgs or \ + self._inRemovalBlacklist(pkg.name): + self.cache.restore_snapshot() + return False + return True diff --git a/DistUpgrade/DistUpgradeControler.py b/DistUpgrade/DistUpgradeControler.py index 80c4dd0c..fe679830 100644 --- a/DistUpgrade/DistUpgradeControler.py +++ b/DistUpgrade/DistUpgradeControler.py @@ -31,64 +31,8 @@ import re from UpdateManager.Common.SimpleGladeApp import SimpleGladeApp from SoftwareProperties.aptsources import SourcesList, SourceEntry from gettext import gettext as _ +from DistUpgradeCache import MyCache - -class MyCache(apt.Cache): - # init - def __init__(self, progress=None): - apt.Cache.__init__(self, progress) - self.to_install = [] - self.to_remove = [] - # turn on debuging - apt_pkg.Config.Set("Debug::pkgProblemResolver","true") - fd = os.open(os.path.expanduser("~/dist-upgrade-apt.log"), os.O_RDWR|os.O_CREAT|os.O_TRUNC) - os.dup2(fd,1) - os.dup2(fd,2) - - # properties - @property - def requiredDownload(self): - pm = apt_pkg.GetPackageManager(self._depcache) - fetcher = apt_pkg.GetAcquire() - pm.GetArchives(fetcher, self._list, self._records) - return fetcher.FetchNeeded - @property - def isBroken(self): - return self._depcache.BrokenCount > 0 - - # methods - def downloadable(self, pkg, useCandidate=True): - " check if the given pkg can be downloaded " - if useCandidate: - ver = self._depcache.GetCandidateVer(pkg._pkg) - else: - ver = pkg._pkg.CurrentVer - if ver == None: - return False - return ver.Downloadable - def fixBroken(self): - """ try to fix broken dependencies on the system, may throw - SystemError when it can't""" - return self._depcache.FixBroken() - def create_snapshot(self): - """ create a snapshot of the current changes """ - self.to_install = [] - self.to_remove = [] - for pkg in self.getChanges(): - if pkg.markedInstall or pkg.markedUpgrade: - self.to_install.append(pkg.name) - if pkg.markedDelete: - self.to_remove.append(pkg.name) - def restore_snapshot(self): - """ restore a snapshot """ - for pkg in self: - pkg.markKeep() - for name in self.to_remove: - pkg = self[name] - pkg.markDelete() - for name in self.to_install: - pkg = self[name] - pkg.markInstall() class DistUpgradeControler(object): @@ -109,74 +53,10 @@ class DistUpgradeControler(object): # be added before the dist-upgrade (e.g. missing ubuntu-desktop) self.missing_pkgs = [] - # a list of regexp that are not allowed to be removed - self.removal_blacklist = [] - for line in open("removal_blacklist.txt").readlines(): - line = line.strip() - if not line == "" or line.startswith("#"): - self.removal_blacklist.append(line) def openCache(self): self.cache = MyCache(self._view.getOpCacheProgress()) - def sanityCheck(self): - if self.cache.isBroken: - try: - logging.debug("Have broken pkgs, trying to fix them") - self.cache.fixBroken() - except SystemError: - self._view.error(_("Broken packages"), - _("Your system contains broken packages " - "that couldn't be fixed with this " - "software. " - "Please fix them first using synaptic or " - "apt-get before proceeding.")) - return False - - # now check for ubuntu-base - if not self.cache.has_key("ubuntu-base") or \ - not self.cache["ubuntu-base"].isInstalled: - self.missing_pkgs.append("ubuntu-base") - - # now check for ubuntu-desktop, kubuntu-desktop, edubuntu-desktop - metapkgs = {"ubuntu-desktop": ["gdm","gnome-panel", "ubuntu-artwork"], - "kubuntu-desktop": ["kdm", "kicker", - "kubuntu-artwork-usplash"], - "edubuntu-desktop": ["edubuntu-artwork", "tuxpaint"] - } - # helper - def metaPkgInstalled(): - metapkg_found = False - for key in metapkgs: - if self.cache.has_key(key) and (self.cache[key].isInstalled or self.cache[key].markedInstall): - metapkg_found=True - return metapkg_found - # check if we have a meta-pkg, if not, try to guess which one to pick - if not metaPkgInstalled(): - logging.debug("no {ubuntu,edubuntu,kubuntu}-desktop pkg installed") - for key in metapkgs: - deps_found = True - for pkg in metapkgs[key]: - deps_found &= self.cache.has_key(pkg) and self.cache[pkg].isInstalled - if deps_found: - logging.debug("guessing '%s' as missing meta-pkg" % key) - self.missing_pkgs.append(key) - # check if we actually found one - if not metaPkgInstalled() and len(self.missing_pkgs) == 0: - # FIXME: provide a list - self._view.error(_("Can't guess meta-package"), - _("Your system does not contain a " - "ubuntu-desktop, kubuntu-desktop or " - "edubuntu-desktop package and it was not " - "possible to detect which version of " - "ubuntu you are runing.\n " - "Please install one of the packages " - "above first using synaptic or " - "apt-get before proceeding.")) - return False - - # FIXME: check for ubuntu-desktop, kubuntu-dekstop, edubuntu-desktop - return True def updateSourcesList(self): self.sources = SourcesList() @@ -316,53 +196,8 @@ class DistUpgradeControler(object): return True def askDistUpgrade(self): - try: - # upgrade (and make sure this way that the cache is ok) - self.cache.upgrade(True) - # then add missing pkgs (like {ubuntu,kubuntu,edubuntu}-desktop) - for pkg in self.missing_pkgs: - logging.debug("Installing missing pkg: %s" % pkg) - self.cache[pkg].markInstall() - if not self._verifyChanges(): - raise SystemError, _("A essential package would have to be removed") - except SystemError, e: - # FIXME: change the text to something more useful - self._view.error(_("Could not calculate the upgrade"), - _("A unresolvable problem occured while " - "calculating the upgrade. Please report " - "this as a bug. ")) - logging.debug("Dist-upgrade failed: '%s'", e) + if not self.cache.distUpgrade(self._view): return False - - # now do some sanity checking, - try: - #are all missing_pkgs really installed? - for pkgname in self.missing_pkgs: - pkg = self.cache[pkgname] - if not (pkg.markedInstall or pkg.markedUpgrade): - logging.error("Missing pkg '%s' not installed after upgrade" % pkgname) - raise AssertionError - # do we still have ubuntu-base? - pkg = self.cache["ubuntu-base"] - if not (pkg.markedInstall or pkg.markedUpgrade or pkg.markedKeep): - logging.error("No ubuntu-base installed after upgrade") - raise AssertionError - # one desktop package? - found = False - for n in ["ubuntu-desktop","kubuntu-desktop","edubuntu-desktop"]: - pkg = self.cache[n] - if pkg.markedKeep or pkg.markedInstall or pkg.markedUpgrade: - found = True - if not found: - logging.error("No dekstop pkg installed after upgrade") - raise AssertionError - except AssertionError: - self._view.error(_("Could not calculate the upgrade"), - _("After calculation the upgrade one of the " - "essential packages can't be upgraded or " - "installed. Please report this as a bug. ")) - return False - changes = self.cache.getChanges() # log the changes for debuging self._logChanges() @@ -385,35 +220,6 @@ class DistUpgradeControler(object): return False return True - def _inRemovalBlacklist(self, pkgname): - for expr in self.removal_blacklist: - if re.compile(expr).match(pkgname): - return True - return False - - def _verifyChanges(self): - """ this function tests if the current changes don't violate - our constrains (blacklisted removals etc) - """ - for pkg in self.cache.getChanges(): - if pkg.markedDelete and self._inRemovalBlacklist(pkg.name): - logging.debug("The package '%s' is marked for removal but it's in the removal blacklist", pkg.name) - return False - return True - - def _tryMarkObsoleteForRemoval(self, pkgname, remove_candidates): - # this is a delete candidate, only actually delete, - # if it dosn't remove other packages depending on it - # that are not obsolete as well - self.cache.create_snapshot() - self.cache[pkgname].markDelete() - for pkg in self.cache.getChanges(): - if pkg.name not in remove_candidates or \ - pkg.name in self.foreign_pkgs or \ - self._inRemovalBlacklist(pkg.name): - self.cache.restore_snapshot() - return False - return True def doPostUpgrade(self): self.openCache() @@ -431,7 +237,7 @@ class DistUpgradeControler(object): logging.debug("Start checking for obsolete pkgs") for pkgname in remove_candidates: if pkgname not in self.foreign_pkgs: - if not self._tryMarkObsoleteForRemoval(pkgname, + if not self.cache._tryMarkObsoleteForRemoval(pkgname, remove_candidates): logging.debug("'%s' scheduled for remove but not in remove_candiates, skipping", pkgname) logging.debug("Finish checking for obsolete pkgs") @@ -462,8 +268,8 @@ class DistUpgradeControler(object): self._view.updateStatus(_("Checking the system")) self._view.setStep(1) self.openCache() - if not self.sanityCheck(): - sys.exit(1) + if not self.cache.sanityCheck(self._view): + abort(1) # do pre-upgrade stuff (calc list of obsolete pkgs etc) self.doPreUpdate() diff --git a/DistUpgrade/removal_blacklist.txt b/DistUpgrade/removal_blacklist.txt index 7d0ee2fb..86b2a831 100644 --- a/DistUpgrade/removal_blacklist.txt +++ b/DistUpgrade/removal_blacklist.txt @@ -1,7 +1,7 @@ # blacklist of packages that should never be removed +ubuntu-base ubuntu-desktop kubuntu-destkop edubuntu-desktop -ubuntu-base linux-image-.* linux-restricted-.* |
