summaryrefslogtreecommitdiff
path: root/DistUpgrade/DistUpgradeControler.py
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2006-09-07 09:54:32 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2006-09-07 09:54:32 +0200
commit066ca0ae74c842d5e55f527cfdab05df5d77f631 (patch)
treecee5ed5bbc75cedd1de1fbc141a0a132ec834612 /DistUpgrade/DistUpgradeControler.py
parent288544afdf646aeebaa1dc7790612a1af098352b (diff)
parentd754e704d6e42bff9f1f8485e134fd4d04cb3a24 (diff)
downloadpython-apt-066ca0ae74c842d5e55f527cfdab05df5d77f631.tar.gz
* merged with mainline
Diffstat (limited to 'DistUpgrade/DistUpgradeControler.py')
-rw-r--r--DistUpgrade/DistUpgradeControler.py142
1 files changed, 123 insertions, 19 deletions
diff --git a/DistUpgrade/DistUpgradeControler.py b/DistUpgrade/DistUpgradeControler.py
index 3a775099..02d25121 100644
--- a/DistUpgrade/DistUpgradeControler.py
+++ b/DistUpgrade/DistUpgradeControler.py
@@ -1,6 +1,6 @@
# DistUpgradeControler.py
#
-# Copyright (c) 2004,2005 Canonical
+# Copyright (c) 2004-2006 Canonical
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
@@ -30,6 +30,7 @@ import subprocess
import logging
import re
import statvfs
+import shutil
from DistUpgradeConfigParser import DistUpgradeConfig
from aptsources import SourcesList, SourceEntry, Distribution, is_mirror
@@ -37,18 +38,78 @@ from gettext import gettext as _
import gettext
from DistUpgradeCache import MyCache
-
+class AptCdrom(object):
+ def __init__(self, view, path):
+ self.view = view
+ self.cdrompath = path
+
+ def restoreBackup(self, backup_ext):
+ " restore the backup copy of the cdroms.list file (*not* sources.list)! "
+ cdromstate = os.path.join(apt_pkg.Config.FindDir("Dir::State"),
+ apt_pkg.Config.Find("Dir::State::cdroms"))
+ if os.path.exists(cdromstate+backup_ext):
+ shutil.copy(cdromstate+backup_ext, cdromstate)
+ # mvo: we don't have to care about restoring the sources.list here because
+ # aptsources will do this for us anyway
+
+ def add(self, backup_ext=None):
+ " add a cdrom to apts database "
+ logging.debug("AptCdrom.add() called with '%s'", self.cdrompath)
+ # do backup (if needed) of the cdroms.list file
+ if backup_ext:
+ cdromstate = os.path.join(apt_pkg.Config.FindDir("Dir::State"),
+ apt_pkg.Config.Find("Dir::State::cdroms"))
+ shutil.copy(cdromstate, cdromstate+backup_ext)
+ # do the actual work
+ apt_pkg.Config.Set("Acquire::cdrom::mount",self.cdrompath)
+ apt_pkg.Config.Set("APT::CDROM::NoMount","true")
+ cdrom = apt_pkg.GetCdrom()
+ # FIXME: add cdrom progress here for the view
+ progress = self.view.getCdromProgress()
+ try:
+ res = cdrom.Add(progress)
+ except SystemError, e:
+ logging.error("can't add cdrom: %s" % e)
+ self.view.error(_("Failed to add the CD"),
+ _("There was a error adding the CD, the "
+ "upgrade will abort. Please report this as "
+ "a bug if this is a valid Ubuntu CD.\n\n"
+ "The error message was:\n'%s'" % e))
+ return False
+ logging.debug("AptCdrom.add() returned: %s" % res)
+ return res
+
+ def __nonzero__(self):
+ """ helper to use this as 'if cdrom:' """
+ return self.cdrompath is not None
class DistUpgradeControler(object):
- def __init__(self, distUpgradeView):
- gettext.bindtextdomain("update-manager",os.path.join(os.getcwd(),"mo"))
+ """ this is the controler that does most of the work """
+
+ def __init__(self, distUpgradeView, cdromPath=None, datadir=None):
+ # setup the pathes
+ localedir = "/usr/share/locale/update-manager/"
+ if datadir == None:
+ datadir = os.getcwd()
+ localedir = os.path.join(datadir,"mo")
+ gladedir = datadir
+ self.datadir = datadir
+
+ # init gettext
+ gettext.bindtextdomain("update-manager",localedir)
gettext.textdomain("update-manager")
+ # setup the view
self._view = distUpgradeView
self._view.updateStatus(_("Reading cache"))
self.cache = None
- self.config = DistUpgradeConfig()
+ # specific for the CDROM based upgrade
+ self.aptcdrom = AptCdrom(distUpgradeView, cdromPath)
+ self.useNetwork = True
+
+ # the configuration
+ self.config = DistUpgradeConfig(datadir)
self.sources_backup_ext = "."+self.config.get("Files","BackupExt")
# some constants here
@@ -61,14 +122,34 @@ class DistUpgradeControler(object):
# turn on debuging in the cache
apt_pkg.Config.Set("Debug::pkgProblemResolver","true")
- fd = os.open("/var/log/dist-upgrade-apt.log",
- os.O_RDWR|os.O_CREAT|os.O_TRUNC)
+ apt_pkg.Config.Set("Debug::pkgDepCache::AutoInstall","true")
+ # FIXME: make this "append"?
+ fd = os.open("/var/log/dist-upgrade/apt.log",
+ os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
os.dup2(fd,1)
os.dup2(fd,2)
def openCache(self):
- self.cache = MyCache(self._view.getOpCacheProgress())
+ self.cache = MyCache(self.config, self._view.getOpCacheProgress())
+ def prepare(self):
+ """ initial cache opening, sanity checking, network checking """
+ self.openCache()
+ if not self.cache.sanityCheck(self._view):
+ return False
+ # FIXME: we may try to find out a bit more about the network connection here and ask more
+ # inteligent questions
+ if self.aptcdrom:
+ res = self._view.askYesNoQuestion(_("Fetch data from the network for the upgrade?"),
+ _("The upgrade can use the network to check "
+ "the latest updates and to fetch packages that are not on the "
+ "current CD.\n"
+ "If you have fast or inexpensive network access you should answer "
+ "'Yes' here. If networking is expensive for you choose 'No'.")
+ )
+ self.useNetwork = res
+ logging.debug("useNetwork: '%s' (selected by user)" % res)
+ return True
def rewriteSourcesList(self, mirror_check=True):
logging.debug("rewriteSourcesList()")
@@ -166,7 +247,7 @@ class DistUpgradeControler(object):
) % (self.fromDist, self.toDist))
if res:
# re-init the sources and try again
- self.sources = SourcesList()
+ self.sources = SourcesList(matcherPath=".")
if not self.rewriteSourcesList(mirror_check=False):
#hm, still nothing useful ...
prim = _("Generate default sources?")
@@ -233,7 +314,7 @@ class DistUpgradeControler(object):
logging.debug("Install: %s" % " ".join(inst))
logging.debug("Upgrade: %s" % " ".join(up))
- def doPreUpdate(self):
+ def doPreUpgrade(self):
# FIXME: check out what packages are downloadable etc to
# compare the list after the update again
self.obsolete_pkgs = self.cache._getObsoletesPkgs()
@@ -242,6 +323,9 @@ class DistUpgradeControler(object):
logging.debug("Obsolete: %s" % " ".join(self.obsolete_pkgs))
def doUpdate(self):
+ if not self.useNetwork:
+ logging.debug("doUpdate() will not use the network because self.useNetwork==false")
+ return True
self.cache._list.ReadMainList()
progress = self._view.getFetchProgress()
# FIXME: retry here too? just like the DoDistUpgrade?
@@ -304,7 +388,7 @@ class DistUpgradeControler(object):
free = st_usr[statvfs.F_BAVAIL]*st_usr[statvfs.F_FRSIZE]
logging.debug("/usr on different fs than %s, free: %s" % (archivedir, free))
- safety_buffer = 1024*1024*75 # 75 Mb
+ safety_buffer = 1024*1024*100 # 100 Mb
logging.debug("using safety buffer: %s" % safety_buffer)
if (self.cache.additionalRequiredSpace+safety_buffer) > free:
free_at_least = apt_pkg.SizeToStr(self.cache.additionalRequiredSpace+safety_buffer-free)
@@ -347,8 +431,11 @@ class DistUpgradeControler(object):
self._view.getTerminal().call(["dpkg","--configure","-a"])
self._view.error(_("Could not install the upgrades"),
_("The upgrade aborts now. Your system "
- "can be in an unusable state. A recovery "
- "was run (dpkg --configure -a)."),
+ "could be in an unusable state. A recovery "
+ "was run (dpkg --configure -a).\n\n"
+ "Please report this bug against the 'update-manager' "
+ "package and include the files in /var/log/dist-upgrade/ "
+ "in the bugreport."),
"%s" % e)
return False
except IOError, e:
@@ -412,7 +499,16 @@ class DistUpgradeControler(object):
# mark packages that are now obsolete (and where not obsolete
# before) to be deleted. make sure to not delete any foreign
# (that is, not from ubuntu) packages
- remove_candidates = now_obsolete - self.obsolete_pkgs
+ if self.useNetwork:
+ # we can only do the obsoletes calculation here if we use a
+ # network. otherwise after rewriting the sources.list everything
+ # that is not on the CD becomes obsolete (not-downloadable)
+ remove_candidates = now_obsolete - self.obsolete_pkgs
+ else:
+ # initial remove candidates when no network is used should
+ # be the demotions to make sure we don't leave potential
+ # unsupported software
+ remove_candidates = set(installed_demotions)
remove_candidates |= set(self.forced_obsoletes)
logging.debug("remove_candidates: '%s'" % remove_candidates)
logging.debug("Start checking for obsolete pkgs")
@@ -445,6 +541,7 @@ class DistUpgradeControler(object):
def abort(self):
""" abort the upgrade, cleanup (as much as possible) """
self.sources.restoreBackup(self.sources_backup_ext)
+ self.aptcdrom.restoreBackup(self.sources_backup_ext)
# generate a new cache
self._view.updateStatus(_("Restoring original system state"))
self.openCache()
@@ -457,22 +554,27 @@ class DistUpgradeControler(object):
self._view.updateStatus(_("Checking package manager"))
self._view.setStep(1)
- self.openCache()
- if not self.cache.sanityCheck(self._view):
- abort(1)
+ if not self.prepare():
+ self.abort(1)
# run a "apt-get update" now
if not self.doUpdate():
sys.exit(1)
# do pre-upgrade stuff (calc list of obsolete pkgs etc)
- self.doPreUpdate()
+ self.doPreUpgrade()
# update sources.list
self._view.setStep(2)
self._view.updateStatus(_("Updating repository information"))
if not self.updateSourcesList():
self.abort()
+
+ # add cdrom (if we have one)
+ if (self.aptcdrom and
+ not self.aptcdrom.add(self.sources_backup_ext)):
+ sys.exit(1)
+
# then update the package index files
if not self.doUpdate():
self.abort()
@@ -494,7 +596,9 @@ class DistUpgradeControler(object):
"updated the essential package '%s' can "
"not be found anymore.\n"
"This indicates a serious error, please "
- "report this as a bug.") % pkg)
+ "report this bug against the 'update-manager' "
+ "package and include the files in /var/log/dist-upgrade/ "
+ "in the bugreport.") % pkg)
self.abort()
# calc the dist-upgrade and see if the removals are ok/expected