home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / DistUpgrade / DistUpgradeController.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-10-12  |  48.8 KB  |  1,277 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import warnings
  5. warnings.filterwarnings('ignore', 'apt API not stable yet', FutureWarning)
  6. import apt
  7. import apt_pkg
  8. import sys
  9. import os
  10. import subprocess
  11. import logging
  12. import re
  13. import statvfs
  14. import shutil
  15. import glob
  16. import time
  17. import copy
  18. import ConfigParser
  19. from stat import *
  20. from utils import country_mirror, url_downloadable
  21. from string import Template
  22. import DistUpgradeView
  23. from DistUpgradeConfigParser import DistUpgradeConfig
  24. from DistUpgradeFetcherCore import country_mirror
  25. from DistUpgradeQuirks import DistUpgradeQuirks
  26. from DistUpgradeAptCdrom import AptCdrom
  27. from DistUpgradeAufs import setupAufs, aufsOptionsAndEnvironmentSetup
  28. from sourceslist import SourcesList, SourceEntry, is_mirror
  29. from distro import Distribution, get_distro, NoDistroTemplateException
  30. from DistUpgradeGettext import gettext as _
  31. from DistUpgradeGettext import ngettext
  32. import gettext
  33. from DistUpgradeCache import *
  34. from DistUpgradeApport import *
  35.  
  36. class NoBackportsFoundException(Exception):
  37.     pass
  38.  
  39.  
  40. class DistUpgradeController(object):
  41.     ''' this is the controller that does most of the work '''
  42.     
  43.     def __init__(self, distUpgradeView, options = None, datadir = None):
  44.         localedir = '/usr/share/locale/update-manager/'
  45.         if datadir == None:
  46.             datadir = os.getcwd()
  47.             localedir = os.path.join(datadir, 'mo')
  48.             gladedir = datadir
  49.         
  50.         self.datadir = datadir
  51.         self.options = options
  52.         gettext.bindtextdomain('update-manager', localedir)
  53.         gettext.textdomain('update-manager')
  54.         logging.debug("Using '%s' view" % distUpgradeView.__class__.__name__)
  55.         self._view = distUpgradeView
  56.         self._view.updateStatus(_('Reading cache'))
  57.         self.cache = None
  58.         if not (self.options) or self.options.withNetwork == None:
  59.             self.useNetwork = True
  60.         else:
  61.             self.useNetwork = self.options.withNetwork
  62.         if options:
  63.             cdrompath = options.cdromPath
  64.         else:
  65.             cdrompath = None
  66.         self.aptcdrom = AptCdrom(distUpgradeView, cdrompath)
  67.         self.config = DistUpgradeConfig(datadir)
  68.         self.sources_backup_ext = '.' + self.config.get('Files', 'BackupExt')
  69.         self.config.add_section('Options')
  70.         self.config.set('Options', 'withNetwork', str(self.useNetwork))
  71.         aufsOptionsAndEnvironmentSetup(self.options, self.config)
  72.         self.fromDist = self.config.get('Sources', 'From')
  73.         self.toDist = self.config.get('Sources', 'To')
  74.         self.origin = self.config.get('Sources', 'ValidOrigin')
  75.         self.arch = apt_pkg.Config.Find('APT::Architecture')
  76.         if not os.environ.has_key('RELEASE_UPGRADE_NO_FORCE_OVERWRITE'):
  77.             logging.debug('enable dpkg --force-overwrite')
  78.             apt_pkg.Config.Set('DPkg::Options::', '--force-overwrite')
  79.         
  80.         self._partialUpgrade = False
  81.         self.quirks = DistUpgradeQuirks(self, self.config)
  82.         os.environ['RELEASE_UPGRADE_IN_PROGRESS'] = '1'
  83.         os.environ['PYCENTRAL_NO_DPKG_QUERY'] = '1'
  84.         os.environ['PYCENTRAL_FORCE_OVERWRITE'] = '1'
  85.         os.environ['PATH'] = '%s:%s' % (os.getcwd() + '/imported', os.environ['PATH'])
  86.         maxRetries = self.config.getint('Network', 'MaxRetries')
  87.         apt_pkg.Config.Set('Acquire::Retries', str(maxRetries))
  88.         apt_pkg.Config.Set('Dpkg::MaxArgs', str(65536))
  89.         apt_pkg.Config.Set('Dpkg::MaxArgBytes', str(131072))
  90.         apt_pkg.Config.Set('Acquire::http::Timeout', '20')
  91.         apt_pkg.Config.Set('Acquire::ftp::Timeout', '20')
  92.         self.forced_obsoletes = self.config.getlist('Distro', 'ForcedObsoletes')
  93.         self.valid_mirrors = self.config.getListFromFile('Sources', 'ValidMirrors')
  94.  
  95.     
  96.     def openCache(self, lock = True):
  97.         logging.debug('openCache()')
  98.         if self.cache is not None:
  99.             self.cache.releaseLock()
  100.             self.cache.unlockListsDir()
  101.         
  102.         
  103.         try:
  104.             self.cache = MyCache(self.config, self._view, self.quirks, self._view.getOpCacheProgress(), lock)
  105.             self.apt_cache = self.cache
  106.         except CacheExceptionDpkgInterrupted:
  107.             e = None
  108.             logging.warning('dpkg interrupted, calling dpkg --configure -a')
  109.             self._view.getTerminal().call([
  110.                 'dpkg',
  111.                 '--configure',
  112.                 '-a'])
  113.             self.cache = MyCache(self.config, self._view, self.quirks, self._view.getOpCacheProgress())
  114.         except CacheExceptionLockingFailed:
  115.             e = None
  116.             logging.error('Cache can not be locked (%s)' % e)
  117.             self._view.error(_('Unable to get exclusive lock'), _('This usually means that another package management application (like apt-get or aptitude) already running. Please close that application first.'))
  118.             sys.exit(1)
  119.  
  120.         self.cache.partialUpgrade = self._partialUpgrade
  121.         logging.debug('/openCache()')
  122.  
  123.     
  124.     def _isRemoteLogin(self):
  125.         ''' check if we are running form a remote login '''
  126.         if os.environ.has_key('SSH_CONNECTION') or os.environ.has_key('SSH_TTY'):
  127.             return True
  128.         out = subprocess.Popen([
  129.             'who',
  130.             '-m',
  131.             '--ips'], stdout = subprocess.PIPE).communicate()[0]
  132.         logging.debug("who -m --ips: '%s'" % out)
  133.         if '(' not in out:
  134.             return False
  135.         ip = out.strip().rsplit('(')[1]
  136.         ip = ip.strip(')')
  137.         if not ip.startswith(':'):
  138.             return True
  139.         return False
  140.  
  141.     
  142.     def _viewSupportsSSH(self):
  143.         '''
  144.       Returns True if this view support upgrades over ssh.
  145.       In theory all views should support it, but for savety
  146.       we do only allow text ssh upgrades (see LP: #322482)
  147.       '''
  148.         supported = self.config.getlist('View', 'SupportSSH')
  149.         if self._view.__class__.__name__ in supported:
  150.             return True
  151.         return False
  152.  
  153.     
  154.     def _sshMagic(self):
  155.         ''' this will check for server mode and if we run over ssh.
  156.             if this is the case, we will ask and spawn a additional
  157.             daemon (to be sure we have a spare one around in case
  158.             of trouble)
  159.         '''
  160.         pidfile = os.path.join('/var/run/release-upgrader-sshd.pid')
  161.         if not os.path.exists(pidfile) and self._isRemoteLogin():
  162.             if not self._viewSupportsSSH():
  163.                 logging.error('upgrade over ssh not alllowed')
  164.                 self._view.error(_('Upgrading over remote connection not supported'), _('You are running the upgrade over a remote ssh connection with a frontend that does not support this. The upgrade will abort now. Please try without ssh.'))
  165.                 sys.exit(1)
  166.                 return False
  167.             port = 9004
  168.             res = self._view.askYesNoQuestion(_('Continue running under SSH?'), _("This session appears to be running under ssh. It is not recommended to perform a upgrade over ssh currently because in case of failure it is harder to recover.\n\nIf you continue, a additional ssh daemon will be started at port '%s'.\nDo you want to continue?") % port)
  169.             if res == False:
  170.                 sys.exit(1)
  171.             
  172.             res = subprocess.call([
  173.                 '/usr/sbin/sshd',
  174.                 '-o',
  175.                 'PidFile=%s' % pidfile,
  176.                 '-p',
  177.                 str(port)])
  178.             if res == 0:
  179.                 self._view.information(_('Starting additional sshd'), _("To make recovery in case of failure easier, an additional sshd will be started on port '%s'. If anything goes wrong with the running ssh you can still connect to the additional one.\n") % port)
  180.             
  181.         
  182.         return True
  183.  
  184.     
  185.     def _tryUpdateSelf(self):
  186.         ''' this is a helper that is run if we are started from a CD
  187.             and we have network - we will then try to fetch a update
  188.             of ourself
  189.         '''
  190.         MetaReleaseCore = MetaReleaseCore
  191.         import MetaRelease
  192.         DistUpgradeFetcherSelf = DistUpgradeFetcherSelf
  193.         import DistUpgradeFetcherSelf
  194.         forceLTS = False
  195.         if self.release == 'dapper' or self.release == 'hardy':
  196.             forceLTS = True
  197.         
  198.         m = MetaReleaseCore(useDevelopmentRelease = False, forceLTS = forceLTS)
  199.         while m.downloading:
  200.             self._view.processEvents()
  201.             time.sleep(0.1)
  202.         if m.new_dist is None:
  203.             logging.error('No new dist found')
  204.             return False
  205.         progress = self._view.getFetchProgress()
  206.         fetcher = DistUpgradeFetcherSelf(new_dist = m.new_dist, progress = progress, options = self.options, view = self._view)
  207.         fetcher.run()
  208.  
  209.     
  210.     def _pythonSymlinkCheck(self):
  211.         ''' sanity check that /usr/bin/python points to the default
  212.             python version. Users tend to modify this symlink, which
  213.             breaks stuff in obscure ways (Ubuntu #75557).
  214.         '''
  215.         logging.debug('_pythonSymlinkCheck run')
  216.         SafeConfigParser = SafeConfigParser
  217.         NoOptionError = NoOptionError
  218.         import ConfigParser
  219.         if os.path.exists('/usr/share/python/debian_defaults'):
  220.             config = SafeConfigParser()
  221.             config.readfp(file('/usr/share/python/debian_defaults'))
  222.             
  223.             try:
  224.                 expected_default = config.get('DEFAULT', 'default-version')
  225.             except NoOptionError:
  226.                 logging.debug("no default version for python found in '%s'" % config)
  227.                 return False
  228.  
  229.             
  230.             try:
  231.                 fs_default_version = os.readlink('/usr/bin/python')
  232.             except OSError:
  233.                 e = None
  234.                 logging.error('os.readlink failed (%s)' % e)
  235.                 return False
  236.  
  237.             if fs_default_version not in (expected_default, os.path.join('/usr/bin', expected_default)):
  238.                 logging.debug("python symlink points to: '%s', but expected is '%s' or '%s'" % (fs_default_version, expected_default, os.path.join('/usr/bin', expected_default)))
  239.                 return False
  240.         
  241.         return True
  242.  
  243.     
  244.     def prepare(self):
  245.         ''' initial cache opening, sanity checking, network checking '''
  246.         self.release = release = subprocess.Popen([
  247.             'lsb_release',
  248.             '-c',
  249.             '-s'], stdout = subprocess.PIPE).communicate()[0].strip()
  250.         logging.debug("lsb-release: '%s'" % release)
  251.         if not release == self.fromDist or release == self.toDist:
  252.             logging.error("Bad upgrade: '%s' != '%s' " % (release, self.fromDist))
  253.             self._view.error(_('Can not upgrade'), _("An upgrade from '%s' to '%s' is not supported with this tool." % (release, self.toDist)))
  254.             sys.exit(1)
  255.         
  256.         if self.config.getWithDefault('Aufs', 'EnableFullOverlay', False):
  257.             aufs_rw_dir = self.config.get('Aufs', 'RWDir')
  258.             if not setupAufs(aufs_rw_dir):
  259.                 logging.error('aufs setup failed')
  260.                 self._view.error(_('Sandbox setup failed'), _('It was not possible to create the sandbox environment.'))
  261.                 return False
  262.             logging.info('running in aufs overlay mode')
  263.             self._view.information(_('Sandbox mode'), _("This upgrade is running in sandbox (test) mode. All changes are written to '%s' and will be lost on the next reboot.\n\n*No* changes written to a systemdir from now until the next reboot are permanent.") % aufs_rw_dir)
  264.         
  265.         if self.options and self.options.havePrerequists:
  266.             backportsdir = os.getcwd() + '/backports'
  267.             logging.info("using backports in '%s' " % backportsdir)
  268.             logging.debug('have: %s' % glob.glob(backportsdir + '/*.udeb'))
  269.             if os.path.exists(backportsdir + '/usr/bin/dpkg'):
  270.                 apt_pkg.Config.Set('Dir::Bin::dpkg', backportsdir + '/usr/bin/dpkg')
  271.             
  272.             if os.path.exists(backportsdir + '/usr/lib/apt/methods'):
  273.                 apt_pkg.Config.Set('Dir::Bin::methods', backportsdir + '/usr/lib/apt/methods')
  274.             
  275.             conf = backportsdir + '/etc/apt/apt.conf.d/01ubuntu'
  276.             if os.path.exists(conf):
  277.                 logging.debug("adding config '%s'" % conf)
  278.                 apt_pkg.ReadConfigFile(apt_pkg.Config, conf)
  279.             
  280.         
  281.         self._sshMagic()
  282.         if not self._pythonSymlinkCheck():
  283.             logging.error('pythonSymlinkCheck() failed, aborting')
  284.             self._view.error(_('Can not upgrade'), _("Your python install is corrupted. Please fix the '/usr/bin/python' symlink."))
  285.             sys.exit(1)
  286.         
  287.         
  288.         try:
  289.             self.openCache()
  290.         except SystemError:
  291.             e = None
  292.             logging.error("openCache() failed: '%s'" % e)
  293.             return False
  294.  
  295.         if not self.cache.sanityCheck(self._view):
  296.             return False
  297.         self.serverMode = self.cache.needServerMode()
  298.         if self.serverMode:
  299.             os.environ['RELEASE_UPGRADE_MODE'] = 'server'
  300.         else:
  301.             os.environ['RELEASE_UPGRADE_MODE'] = 'desktop'
  302.         if not self.checkViewDepends():
  303.             logging.error('checkViewDepends() failed')
  304.             return False
  305.         if os.path.exists('/usr/bin/debsig-verify'):
  306.             logging.error('debsig-verify is installed')
  307.             self._view.error(_("Package 'debsig-verify' is installed"), _("The upgrade can not continue with that package installed.\nPlease remove it with synaptic or 'apt-get remove debsig-verify' first and run the upgrade again."))
  308.             self.abort()
  309.         
  310.         if self.aptcdrom and self.options and self.options.withNetwork == None:
  311.             res = self._view.askYesNoQuestion(_('Include latest updates from the Internet?'), _("The upgrade system can use the internet to automatically download the latest updates and install them during the upgrade.  If you have a network connection this is highly recommended.\n\nThe upgrade will take longer, but when it is complete, your system will be fully up to date.  You can choose not to do this, but you should install the latest updates soon after upgrading.\nIf you answer 'no' here, the network is not used at all."), 'Yes')
  312.             self.useNetwork = res
  313.             self.config.set('Options', 'withNetwork', str(self.useNetwork))
  314.             logging.debug("useNetwork: '%s' (selected by user)" % res)
  315.             if res:
  316.                 self._tryUpdateSelf()
  317.             
  318.         
  319.         return True
  320.  
  321.     
  322.     def _sourcesListEntryDownloadable(self, entry):
  323.         '''
  324.         helper that checks if a sources.list entry points to 
  325.         something downloadable
  326.         '''
  327.         logging.debug('verifySourcesListEntry: %s' % entry)
  328.         if not self.useNetwork:
  329.             logging.debug('skiping downloadable check (no network)')
  330.             return True
  331.         uri = '%s/dists/%s/Release' % (entry.uri, entry.dist)
  332.         return url_downloadable(uri, logging.debug)
  333.  
  334.     
  335.     def rewriteSourcesList(self, mirror_check = True):
  336.         logging.debug('rewriteSourcesList()')
  337.         sync_components = self.config.getlist('Sources', 'Components')
  338.         if self.config.getWithDefault('Sources', 'AllowThirdParty', False) or 'RELEASE_UPRADER_ALLOW_THIRD_PARTY' in os.environ:
  339.             logging.warning('mirror check skipped, *overriden* via config')
  340.             mirror_check = False
  341.         
  342.         if mirror_check == True and self.useNetwork:
  343.             for pkgname in self.config.getlist('Distro', 'BaseMetaPkgs'):
  344.                 if (not self.cache.has_key(pkgname) or len(self.cache[pkgname].candidateOrigin) == 0 or len(self.cache[pkgname].candidateOrigin) == 1) and self.cache[pkgname].candidateOrigin[0].archive == 'now':
  345.                     logging.debug("BaseMetaPkg '%s' has no candidateOrigin" % pkgname)
  346.                     
  347.                     try:
  348.                         distro = get_distro()
  349.                         distro.get_sources(self.sources)
  350.                         distro.enable_component('main')
  351.                     except NoDistroTemplateException:
  352.                         e = None
  353.                         logging.warning('get_distro().enable_component("man") failed, overwriting sources.list instead as last resort')
  354.                         s = '# auto generated by update-manager'
  355.                         s += 'deb http://archive.ubuntu.com/ubuntu %s main restricted' % self.toDist
  356.                         s += 'deb http://archive.ubuntu.com/ubuntu %s-updates main restricted' % self.toDist
  357.                         s += 'deb http://security.ubuntu.com/ubuntu %s-security main restricted' % self.toDist
  358.                         open('/etc/apt/sources.list', 'w').write(s)
  359.  
  360.                     break
  361.                     continue
  362.             
  363.         
  364.         fromDists = [
  365.             self.fromDist,
  366.             self.fromDist + '-security',
  367.             self.fromDist + '-updates',
  368.             self.fromDist + '-proposed',
  369.             self.fromDist + '-backports']
  370.         toDists = [
  371.             self.toDist,
  372.             self.toDist + '-security',
  373.             self.toDist + '-updates',
  374.             self.toDist + '-proposed',
  375.             self.toDist + '-backports']
  376.         self.sources_disabled = False
  377.         foundToDist = False
  378.         found_components = { }
  379.         for entry in self.sources.list[:]:
  380.             if entry.invalid or entry.disabled:
  381.                 continue
  382.             
  383.             if entry.uri.startswith('cdrom:') and entry.dist == self.fromDist:
  384.                 entry.disabled = True
  385.                 continue
  386.             elif entry.uri.startswith('cdrom:'):
  387.                 continue
  388.             
  389.             cdist = '%s-commercial' % self.fromDist
  390.             if not (entry.disabled) and entry.uri.startswith('http://archive.canonical.com') and entry.dist == cdist:
  391.                 entry.dist = self.toDist
  392.                 entry.comps = [
  393.                     'partner']
  394.                 logging.debug("transitioned commercial to '%s' " % entry)
  395.                 continue
  396.             
  397.             if not (entry.disabled) and entry.uri.startswith('http://landscape.canonical.com/packages/%s' % self.fromDist):
  398.                 logging.debug('commenting landscape.canonical.com out')
  399.                 entry.disabled = True
  400.                 continue
  401.             
  402.             if not (entry.disabled) and 'old-releases.ubuntu.com/' in entry.uri:
  403.                 logging.debug('upgrade from old-releases.ubuntu.com detected')
  404.                 for uri in [
  405.                     'http://%sarchive.ubuntu.com/ubuntu' % country_mirror(),
  406.                     'http://archive.ubuntu.com/ubuntu']:
  407.                     test_entry = copy.copy(entry)
  408.                     test_entry.uri = uri
  409.                     test_entry.dist = self.toDist
  410.                     if self._sourcesListEntryDownloadable(test_entry):
  411.                         logging.info('transition from old-release.u.c to %s' % uri)
  412.                         entry.uri = uri
  413.                         break
  414.                         continue
  415.                 
  416.             
  417.             logging.debug("examining: '%s'" % entry)
  418.             validMirror = self.isMirror(entry.uri)
  419.             if validMirror or not mirror_check:
  420.                 validMirror = True
  421.                 validTo = True
  422.                 if entry.disabled and entry.type == 'deb-src' and entry.uri.startswith('http://security.ubuntu.com') or entry.uri.startswith('http://archive.canonical.com'):
  423.                     validTo = False
  424.                 
  425.                 if entry.dist in toDists:
  426.                     logging.debug("entry '%s' is already set to new dist" % entry)
  427.                     foundToDist |= validTo
  428.                 elif entry.dist in fromDists:
  429.                     foundToDist |= validTo
  430.                     entry.dist = toDists[fromDists.index(entry.dist)]
  431.                     logging.debug("entry '%s' updated to new dist" % entry)
  432.                 else:
  433.                     entry.disabled = True
  434.                     self.sources_disabled = True
  435.                     logging.debug("entry '%s' was disabled (unknown dist)" % entry)
  436.                 if entry.type == 'deb' and 'ports.ubuntu.com' not in entry.uri:
  437.                     if self.arch == 'powerpc' or self.arch == 'sparc':
  438.                         logging.debug("moving %s source entry to 'ports.ubuntu.com' " % self.arch)
  439.                         entry.uri = 'http://ports.ubuntu.com/ubuntu-ports/'
  440.                     
  441.                 for d in [
  442.                     '%s' % self.toDist,
  443.                     '%s-updates' % self.toDist,
  444.                     '%s-security' % self.toDist]:
  445.                     found_components.setdefault(d, set())
  446.                     if not (entry.disabled) and entry.dist == d and entry.type == 'deb':
  447.                         for comp in entry.comps:
  448.                             if comp not in sync_components:
  449.                                 continue
  450.                             
  451.                             found_components[d].add(comp)
  452.                         
  453.                 
  454.             
  455.             if not validMirror:
  456.                 if entry.dist == self.fromDist:
  457.                     entry.dist = self.toDist
  458.                 
  459.                 entry.comment += ' ' + _('disabled on upgrade to %s') % self.toDist
  460.                 entry.disabled = True
  461.                 self.sources_disabled = True
  462.                 logging.debug("entry '%s' was disabled (unknown mirror)" % entry)
  463.                 continue
  464.             entry
  465.         
  466.         for entry in self.sources.list[:]:
  467.             if entry.invalid and entry.disabled and entry.type == 'deb-src' and entry.uri.startswith('cdrom:') or entry.dist == self.toDist:
  468.                 continue
  469.             
  470.             if found_components.has_key(entry.dist):
  471.                 logging.info("fixing components inconsistency from '%s'" % entry)
  472.                 entry.comps.extend(list(found_components[self.toDist] - found_components[entry.dist]))
  473.                 logging.info("to new entry '%s'" % entry)
  474.                 del found_components[entry.dist]
  475.                 continue
  476.         
  477.         return foundToDist
  478.  
  479.     
  480.     def updateSourcesList(self):
  481.         logging.debug('updateSourcesList()')
  482.         self.sources = SourcesList(matcherPath = '.')
  483.         if not self.rewriteSourcesList(mirror_check = True):
  484.             logging.error('No valid mirror found')
  485.             res = self._view.askYesNoQuestion(_('No valid mirror found'), _("While scanning your repository information no mirror entry for the upgrade was found.This can happen if you run a internal mirror or if the mirror information is out of date.\n\nDo you want to rewrite your 'sources.list' file anyway? If you choose 'Yes' here it will update all '%s' to '%s' entries.\nIf you select 'no' the update will cancel.") % (self.fromDist, self.toDist))
  486.             if res:
  487.                 self.sources = SourcesList(matcherPath = '.')
  488.                 if not self.rewriteSourcesList(mirror_check = False) and self.useNetwork:
  489.                     prim = _('Generate default sources?')
  490.                     secon = _("After scanning your 'sources.list' no valid entry for '%s' was found.\n\nShould default entries for '%s' be added? If you select 'No', the update will cancel.") % (self.fromDist, self.toDist)
  491.                     if not self._view.askYesNoQuestion(prim, secon):
  492.                         self.abort()
  493.                     
  494.                     logging.info('generate new default sources.list')
  495.                     uri = 'http://archive.ubuntu.com/ubuntu'
  496.                     comps = [
  497.                         'main',
  498.                         'restricted']
  499.                     self.sources.add('deb', uri, self.toDist, comps)
  500.                     self.sources.add('deb', uri, self.toDist + '-updates', comps)
  501.                     self.sources.add('deb', 'http://security.ubuntu.com/ubuntu/', self.toDist + '-security', comps)
  502.                 
  503.             else:
  504.                 self.abort()
  505.         
  506.         self.sources.backup(self.sources_backup_ext)
  507.         self.sources.save()
  508.         
  509.         try:
  510.             sourceslist = apt_pkg.GetPkgSourceList()
  511.             sourceslist.ReadMainList()
  512.         except SystemError:
  513.             logging.error('Repository information invalid after updating (we broke it!)')
  514.             self._view.error(_('Repository information invalid'), _('Upgrading the repository information resulted in a invalid file. Please report this as a bug.'))
  515.             return False
  516.  
  517.         if self.sources_disabled:
  518.             self._view.information(_('Third party sources disabled'), _("Some third party entries in your sources.list were disabled. You can re-enable them after the upgrade with the 'software-properties' tool or your package manager."))
  519.         
  520.         return True
  521.  
  522.     
  523.     def _logChanges(self):
  524.         logging.debug('About to apply the following changes')
  525.         inst = []
  526.         up = []
  527.         rm = []
  528.         held = []
  529.         keep = []
  530.         for pkg in self.cache:
  531.             if pkg.markedInstall:
  532.                 inst.append(pkg.name)
  533.                 continue
  534.             if pkg.markedUpgrade:
  535.                 up.append(pkg.name)
  536.                 continue
  537.             if pkg.markedDelete:
  538.                 rm.append(pkg.name)
  539.                 continue
  540.             if pkg.isInstalled and pkg.isUpgradable:
  541.                 held.append(pkg.name)
  542.                 continue
  543.             if pkg.isInstalled and pkg.markedKeep:
  544.                 keep.append(pkg.name)
  545.                 continue
  546.         
  547.         logging.debug('Keep at same version: %s' % ' '.join(keep))
  548.         logging.debug('Upgradable, but held- back: %s' % ' '.join(held))
  549.         logging.debug('Remove: %s' % ' '.join(rm))
  550.         logging.debug('Install: %s' % ' '.join(inst))
  551.         logging.debug('Upgrade: %s' % ' '.join(up))
  552.  
  553.     
  554.     def doPostInitialUpdate(self):
  555.         logging.debug('doPostInitialUpdate')
  556.         if not self._partialUpgrade:
  557.             self.quirks.run('PostInitialUpdate')
  558.         
  559.         if len(self.cache.reqReinstallPkgs) > 0:
  560.             logging.warning('packages in reqReinstall state, trying to fix')
  561.             self.cache.fixReqReinst(self._view)
  562.             self.openCache()
  563.         
  564.         if len(self.cache.reqReinstallPkgs) > 0:
  565.             reqreinst = self.cache.reqReinstallPkgs
  566.             header = ngettext('Package in inconsistent state', 'Packages in inconsistent state', len(reqreinst))
  567.             summary = ngettext("The package '%s' is in an inconsistent state and needs to be reinstalled, but no archive can be found for it. Please reinstall the package manually or remove it from the system.", "The packages '%s' are in an inconsistent state and need to be reinstalled, but no archive can be found for them. Please reinstall the packages manually or remove them from the system.", len(reqreinst)) % ', '.join(reqreinst)
  568.             self._view.error(header, summary)
  569.             return False
  570.         self.obsolete_pkgs = self.cache._getObsoletesPkgs()
  571.         self.foreign_pkgs = self.cache._getForeignPkgs(self.origin, self.fromDist, self.toDist)
  572.         if self.serverMode:
  573.             self.tasks = self.cache.installedTasks
  574.         
  575.         logging.debug('Foreign: %s' % ' '.join(self.foreign_pkgs))
  576.         logging.debug('Obsolete: %s' % ' '.join(self.obsolete_pkgs))
  577.         return True
  578.  
  579.     
  580.     def doUpdate(self, showErrors = True, forceRetries = None):
  581.         logging.debug('running doUpdate() (showErrors=%s)' % showErrors)
  582.         if not self.useNetwork:
  583.             logging.debug('doUpdate() will not use the network because self.useNetwork==false')
  584.             return True
  585.         self.cache._list.ReadMainList()
  586.         progress = self._view.getFetchProgress()
  587.         currentRetry = 0
  588.         if forceRetries is not None:
  589.             maxRetries = forceRetries
  590.         else:
  591.             maxRetries = self.config.getint('Network', 'MaxRetries')
  592.         while currentRetry < maxRetries:
  593.             
  594.             try:
  595.                 res = self.cache.update(progress)
  596.             except (SystemError, IOError):
  597.                 e = None
  598.                 logging.error("IOError/SystemError in cache.update(): '%s'. Retrying (currentRetry: %s)" % (e, currentRetry))
  599.                 currentRetry += 1
  600.                 continue
  601.  
  602.             return True
  603.         logging.error('doUpdate() failed completely')
  604.         if showErrors:
  605.             self._view.error(_('Error during update'), _('A problem occurred during the update. This is usually some sort of network problem, please check your network connection and retry.'), '%s' % e)
  606.         
  607.         return False
  608.  
  609.     
  610.     def _checkFreeSpace(self):
  611.         ''' this checks if we have enough free space on /var and /usr'''
  612.         err_sum = _('Not enough free disk space')
  613.         err_long = _("The upgrade is now aborted. The upgrade needs a total of %s free space on disk '%s'. Please free at least an additional %s of disk space on '%s'. Empty your trash and remove temporary packages of former installations using 'sudo apt-get clean'.")
  614.         if self.config.getWithDefault('FreeSpace', 'SkipCheck', False):
  615.             logging.warning('free space check skipped via config override')
  616.             return True
  617.         
  618.         try:
  619.             self.cache.checkFreeSpace()
  620.         except NotEnoughFreeSpaceError:
  621.             self.config.getWithDefault('FreeSpace', 'SkipCheck', False)
  622.             e = self.config.getWithDefault('FreeSpace', 'SkipCheck', False)
  623.             for required in e.free_space_required_list:
  624.                 self._view.error(err_sum, err_long % (required.size_total, required.dir, required.size_needed, required.dir))
  625.             
  626.             return False
  627.  
  628.         return True
  629.  
  630.     
  631.     def askDistUpgrade(self):
  632.         demotions = set()
  633.         demotions_file = self.config.get('Distro', 'Demotions')
  634.         if os.path.exists(demotions_file):
  635.             (map,)((lambda pkgname: demotions.add(pkgname.strip())), filter((lambda line: not line.startswith('#')), open(demotions_file).readlines()))
  636.         
  637.         self.installed_demotions = _[1]
  638.         if not self.cache.distUpgrade(self._view, self.serverMode, self._partialUpgrade):
  639.             return False
  640.         changes = self.cache.getChanges()
  641.         self._logChanges()
  642.         if not self._checkFreeSpace():
  643.             return False
  644.         res = self._view.confirmChanges(_('Do you want to start the upgrade?'), changes, self.cache.requiredDownload)
  645.         return res
  646.  
  647.     
  648.     def _disableAptCronJob(self):
  649.         self._aptCronJobPerms = 493
  650.         if os.path.exists('/etc/cron.daily/apt'):
  651.             self._aptCronJobPerms = os.stat('/etc/cron.daily/apt')[ST_MODE]
  652.             logging.debug('disabling apt cron job (%s)' % oct(self._aptCronJobPerms))
  653.             os.chmod('/etc/cron.daily/apt', 420)
  654.         
  655.  
  656.     
  657.     def _enableAptCronJob(self):
  658.         if os.path.exists('/etc/cron.daily/apt'):
  659.             logging.debug('enabling apt cron job')
  660.             os.chmod('/etc/cron.daily/apt', self._aptCronJobPerms)
  661.         
  662.  
  663.     
  664.     def doDistUpgradeFetching(self):
  665.         self._disableAptCronJob()
  666.         currentRetry = 0
  667.         fprogress = self._view.getFetchProgress()
  668.         iprogress = self._view.getInstallProgress(self.cache)
  669.         maxRetries = self.config.getint('Network', 'MaxRetries')
  670.         while currentRetry < maxRetries:
  671.             
  672.             try:
  673.                 pm = apt_pkg.GetPackageManager(self.cache._depcache)
  674.                 fetcher = apt_pkg.GetAcquire(fprogress)
  675.                 res = self.cache._fetchArchives(fetcher, pm)
  676.             except IOError:
  677.                 e = None
  678.                 logging.error("IOError in cache.commit(): '%s'. Retrying (currentTry: %s)" % (e, currentRetry))
  679.                 currentRetry += 1
  680.                 continue
  681.  
  682.             return True
  683.         logging.error('giving up on fetching after maximum retries')
  684.         self._view.error(_('Could not download the upgrades'), _('The upgrade is now aborted. Please check your Internet connection or installation media and try again. All files downloaded so far are kept.'), '%s' % e)
  685.         self._enableAptCronJob()
  686.         self.abort()
  687.  
  688.     
  689.     def enableApport(self, fname = '/etc/default/apport'):
  690.         ''' enable apoprt '''
  691.         if not os.path.exists(fname):
  692.             return None
  693.         logging.debug('enabling apport')
  694.         shutil.copy('etc-default-apport', '/etc/default/apport')
  695.         subprocess.call([
  696.             '/etc/init.d/apport',
  697.             'start'])
  698.  
  699.     
  700.     def doDistUpgrade(self):
  701.         if self.config.getWithDefault('Distro', 'EnableApport', False):
  702.             self.enableApport()
  703.         
  704.         currentRetry = 0
  705.         fprogress = self._view.getFetchProgress()
  706.         iprogress = self._view.getInstallProgress(self.cache)
  707.         maxRetries = self.config.getint('Network', 'MaxRetries')
  708.         if not self._partialUpgrade:
  709.             self.quirks.run('StartUpgrade')
  710.         
  711.         while currentRetry < maxRetries:
  712.             
  713.             try:
  714.                 res = self.cache.commit(fprogress, iprogress)
  715.             except SystemError:
  716.                 e = None
  717.                 logging.error('SystemError from cache.commit(): %s' % e)
  718.                 pre_configure_errors = [
  719.                     'E:Internal Error, Could not perform immediate configuration',
  720.                     "E:Couldn't configure pre-depend "]
  721.                 for preconf_error in pre_configure_errors:
  722.                     if str(e).startswith(preconf_error):
  723.                         logging.debug('detected preconfigure error, restorting state')
  724.                         self._enableAptCronJob()
  725.                         msg = _('Error during commit')
  726.                         msg += "\n'%s'\n" % str(e)
  727.                         msg += _('Restoring original system state')
  728.                         self._view.error(_('Could not install the upgrades'), msg)
  729.                         self.abort()
  730.                         continue
  731.                 
  732.                 msg = _('The upgrade is now aborted. Your system could be in an unusable state. A recovery will run now (dpkg --configure -a).')
  733.                 if not self._partialUpgrade:
  734.                     if not run_apport():
  735.                         msg += _("\n\nPlease report this bug against the 'update-manager' package and include the files in /var/log/dist-upgrade/ in the bug report.\n%s" % e)
  736.                     
  737.                 
  738.                 self._view.error(_('Could not install the upgrades'), msg)
  739.                 self._view.getTerminal().call([
  740.                     'dpkg',
  741.                     '--configure',
  742.                     '-a'])
  743.                 self._enableAptCronJob()
  744.                 return False
  745.                 except IOError:
  746.                     e = None
  747.                     logging.error("IOError in cache.commit(): '%s'. Retrying (currentTry: %s)" % (e, currentRetry))
  748.                     currentRetry += 1
  749.                     continue
  750.                 except:
  751.                     None<EXCEPTION MATCH>IOError
  752.                 
  753.  
  754.             self._enableAptCronJob()
  755.             return True
  756.         logging.error('giving up on fetching after maximum retries')
  757.         self._view.error(_('Could not download the upgrades'), _('The upgrade is now aborted. Please check your Internet connection or installation media and try again. '), '%s' % e)
  758.         self.abort()
  759.  
  760.     
  761.     def doPostUpgrade(self):
  762.         self.openCache()
  763.         if not self._partialUpgrade:
  764.             self.quirks.run('PostUpgrade')
  765.         
  766.         now_obsolete = self.cache._getObsoletesPkgs()
  767.         now_foreign = self.cache._getForeignPkgs(self.origin, self.fromDist, self.toDist)
  768.         logging.debug('Obsolete: %s' % ' '.join(now_obsolete))
  769.         logging.debug('Foreign: %s' % ' '.join(now_foreign))
  770.         for pkg in self.config.getlist('Distro', 'BaseMetaPkgs'):
  771.             if pkg in now_obsolete:
  772.                 logging.error("the BaseMetaPkg '%s' is in the obsolete list, something is wrong, ignoring the obsoletes" % pkg)
  773.                 now_obsolete = set()
  774.                 break
  775.                 continue
  776.         
  777.         if not self.config.getWithDefault('Distro', 'RemoveObsoletes', True):
  778.             logging.debug('Skipping obsolete Removal')
  779.             return True
  780.         for pkg in self.config.getlist('Distro', 'MetaPkgs'):
  781.             if self.cache.has_key(pkg) and self.cache[pkg].isInstalled:
  782.                 self.forced_obsoletes.extend(self.config.getlist(pkg, 'ForcedObsoletes'))
  783.                 continue
  784.             self.config.getWithDefault('Distro', 'RemoveObsoletes', True)
  785.         
  786.         self.forced_obsoletes.extend(self.cache.identifyObsoleteKernels())
  787.         logging.debug('forced_obsoletes: %s', self.forced_obsoletes)
  788.         if self.useNetwork:
  789.             remove_candidates = now_obsolete - self.obsolete_pkgs
  790.         else:
  791.             remove_candidates = set(self.installed_demotions)
  792.         remove_candidates |= set(self.forced_obsoletes)
  793.         unused_dependencies = self.cache._getUnusedDependencies()
  794.         logging.debug('Unused dependencies: %s' % ' '.join(unused_dependencies))
  795.         remove_candidates |= set(unused_dependencies)
  796.         if not self.config.getWithDefault('Distro', 'RemoveObsoletes', True):
  797.             logging.debug('Skipping RemoveObsoletes as stated in the config')
  798.             remove_candidates = set()
  799.         
  800.         logging.debug("remove_candidates: '%s'" % remove_candidates)
  801.         logging.debug('Start checking for obsolete pkgs')
  802.         for pkgname in remove_candidates:
  803.             if pkgname not in self.foreign_pkgs:
  804.                 self._view.processEvents()
  805.                 if not self.cache.tryMarkObsoleteForRemoval(pkgname, remove_candidates, self.foreign_pkgs):
  806.                     logging.debug("'%s' scheduled for remove but not safe to remove, skipping", pkgname)
  807.                 
  808.             self.cache.tryMarkObsoleteForRemoval(pkgname, remove_candidates, self.foreign_pkgs)
  809.         
  810.         logging.debug('Finish checking for obsolete pkgs')
  811.         changes = self.cache.getChanges()
  812.         ' '.join([] % []([ pkg.name for pkg in changes ]))
  813.         summary = _('Remove obsolete packages?')
  814.         actions = [
  815.             _('_Keep'),
  816.             _('_Remove')]
  817.         if len(changes) > 0 and self._view.confirmChanges(summary, changes, 0, actions, False):
  818.             fprogress = self._view.getFetchProgress()
  819.             iprogress = self._view.getInstallProgress(self.cache)
  820.             
  821.             try:
  822.                 res = self.cache.commit(fprogress, iprogress)
  823.             except (SystemError, IOError):
  824.                 'The following packages are remove candidates: %s'
  825.                 e = 'The following packages are remove candidates: %s'
  826.                 logging.debug
  827.                 logging.error('cache.commit() in doPostUpgrade() failed: %s' % e)
  828.                 self._view.error(_('Error during commit'), _('A problem occurred during the clean-up. Please see the below message for more information. '), '%s' % e)
  829.             except:
  830.                 'The following packages are remove candidates: %s'<EXCEPTION MATCH>(SystemError, IOError)
  831.             
  832.  
  833.         'The following packages are remove candidates: %s'
  834.         if not self._partialUpgrade:
  835.             self.runPostInstallScripts()
  836.         
  837.         return True
  838.  
  839.     
  840.     def runPostInstallScripts(self):
  841.         ''' 
  842.         scripts that are run in any case after the distupgrade finished 
  843.         whether or not it was successfull
  844.         '''
  845.         for script in self.config.getlist('Distro', 'PostInstallScripts'):
  846.             if not os.path.exists(script):
  847.                 logging.warning("PostInstallScript: '%s' not found" % script)
  848.                 continue
  849.             
  850.             logging.debug("Running PostInstallScript: '%s'" % script)
  851.             
  852.             try:
  853.                 os.chmod(script, 493)
  854.                 self._view.getTerminal().call([
  855.                     script], hidden = True)
  856.             continue
  857.             except Exception:
  858.                 e = None
  859.                 logging.error('got error from PostInstallScript %s (%s)' % (script, e))
  860.                 continue
  861.             
  862.  
  863.         
  864.  
  865.     
  866.     def abort(self):
  867.         ''' abort the upgrade, cleanup (as much as possible) '''
  868.         if hasattr(self, 'sources'):
  869.             self.sources.restoreBackup(self.sources_backup_ext)
  870.         
  871.         if hasattr(self, 'aptcdrom'):
  872.             self.aptcdrom.restoreBackup(self.sources_backup_ext)
  873.         
  874.         self._view.updateStatus(_('Restoring original system state'))
  875.         self._view.abort()
  876.         self.openCache()
  877.         sys.exit(1)
  878.  
  879.     
  880.     def _checkDep(self, depstr):
  881.         ''' check if a given depends can be satisfied '''
  882.         for or_group in apt_pkg.ParseDepends(depstr):
  883.             logging.debug("checking: '%s' " % or_group)
  884.             for dep in or_group:
  885.                 depname = dep[0]
  886.                 ver = dep[1]
  887.                 oper = dep[2]
  888.                 if not self.cache.has_key(depname):
  889.                     logging.error("_checkDep: '%s' not in cache" % depname)
  890.                     return False
  891.                 inst = self.cache[depname]
  892.                 instver = inst.installedVersion
  893.                 if instver != None and apt_pkg.CheckDep(instver, oper, ver) == True:
  894.                     return True
  895.             
  896.         
  897.         logging.error("depends '%s' is not satisfied" % depstr)
  898.         return False
  899.  
  900.     
  901.     def checkViewDepends(self):
  902.         ''' check if depends are satisfied '''
  903.         logging.debug('checkViewDepends()')
  904.         res = True
  905.         depends = self.config.getlist('View', 'Depends')
  906.         depends.extend(self.config.getlist(self._view.__class__.__name__, 'Depends'))
  907.         for dep in depends:
  908.             logging.debug("depends: '%s'", dep)
  909.             res &= self._checkDep(dep)
  910.             if not res:
  911.                 self._view.error(_('Required depends is not installed'), _("The required dependency '%s' is not installed. " % dep))
  912.                 sys.exit(1)
  913.                 continue
  914.         
  915.         return res
  916.  
  917.     
  918.     def _verifyBackports(self):
  919.         backportslist = self.config.getlist('PreRequists', 'Packages')
  920.         i = 0
  921.         noCache = apt_pkg.Config.Find('Acquire::http::No-Cache', 'false')
  922.         maxRetries = self.config.getint('Network', 'MaxRetries')
  923.         while i < maxRetries:
  924.             self.doUpdate(showErrors = False)
  925.             self.openCache()
  926.             for pkgname in backportslist:
  927.                 if not self.cache.has_key(pkgname):
  928.                     logging.error("Can not find backport '%s'" % pkgname)
  929.                     raise NoBackportsFoundException, pkgname
  930.                 self.cache.has_key(pkgname)
  931.             
  932.             if self._allBackportsAuthenticated(backportslist):
  933.                 break
  934.             
  935.             logging.debug('setting a cache control header to turn off caching temporarily')
  936.             apt_pkg.Config.Set('Acquire::http::No-Cache', 'true')
  937.             i += 1
  938.         if i == maxRetries:
  939.             logging.error('pre-requists item is NOT trusted, giving up')
  940.             return False
  941.         apt_pkg.Config.Set('Acquire::http::No-Cache', noCache)
  942.         return True
  943.  
  944.     
  945.     def _allBackportsAuthenticated(self, backportslist):
  946.         if apt_pkg.Config.FindB('APT::Get::AllowUnauthenticated', False) == True:
  947.             logging.warning('skip authentication check because of APT::Get::AllowUnauthenticated==true')
  948.             return True
  949.         
  950.         try:
  951.             b = self.config.getboolean('Distro', 'AllowUnauthenticated')
  952.             if b:
  953.                 return True
  954.         except ConfigParser.NoOptionError:
  955.             apt_pkg.Config.FindB('APT::Get::AllowUnauthenticated', False) == True
  956.             e = apt_pkg.Config.FindB('APT::Get::AllowUnauthenticated', False) == True
  957.         except:
  958.             apt_pkg.Config.FindB('APT::Get::AllowUnauthenticated', False) == True
  959.  
  960.         for pkgname in backportslist:
  961.             pkg = self.cache[pkgname]
  962.             for cand in pkg.candidateOrigin:
  963.                 if cand.trusted:
  964.                     break
  965.                     continue
  966.                 apt_pkg.Config.FindB('APT::Get::AllowUnauthenticated', False) == True
  967.             else:
  968.                 return False
  969.         
  970.         return True
  971.  
  972.     
  973.     def isMirror(self, uri):
  974.         ''' check if uri is a known mirror '''
  975.         for mirror in self.valid_mirrors:
  976.             if is_mirror(mirror, uri):
  977.                 return True
  978.         
  979.         return False
  980.  
  981.     
  982.     def _getPreReqMirrorLines(self, dumb = False):
  983.         ''' get sources.list snippet lines for the current mirror '''
  984.         lines = ''
  985.         sources = SourcesList(matcherPath = '.')
  986.         for entry in sources.list:
  987.             if entry.invalid or entry.disabled:
  988.                 continue
  989.             
  990.             if entry.type == 'deb' and self.isMirror(entry.uri) and not entry.uri.startswith('http://security.ubuntu.com') and not entry.uri.startswith('http://archive.ubuntu.com'):
  991.                 new_line = 'deb %s %s-backports main/debian-installer\n' % (entry.uri, self.fromDist)
  992.                 if new_line not in lines:
  993.                     lines += new_line
  994.                 
  995.             
  996.             if dumb and entry.type == 'deb' and 'main' in entry.comps:
  997.                 lines += 'deb %s %s-backports main/debian-installer\n' % (entry.uri, self.fromDist)
  998.                 continue
  999.         
  1000.         return lines
  1001.  
  1002.     
  1003.     def _addPreRequistsSourcesList(self, template, out, dumb = False):
  1004.         ''' add prerequists based on template into the path outfile '''
  1005.         logging.debug("writing prerequists sources.list at: '%s' " % out)
  1006.         outfile = open(out, 'w')
  1007.         mirrorlines = self._getPreReqMirrorLines(dumb)
  1008.         for line in open(template):
  1009.             template = Template(line)
  1010.             outline = template.safe_substitute(mirror = mirrorlines)
  1011.             outfile.write(outline)
  1012.             logging.debug("adding '%s' prerequists" % outline)
  1013.         
  1014.         outfile.close()
  1015.         return True
  1016.  
  1017.     
  1018.     def getRequiredBackports(self):
  1019.         ''' download the backports specified in DistUpgrade.cfg '''
  1020.         logging.debug('getRequiredBackports()')
  1021.         res = True
  1022.         backportsdir = os.path.join(os.getcwd(), 'backports')
  1023.         if not os.path.exists(backportsdir):
  1024.             os.mkdir(backportsdir)
  1025.         
  1026.         backportslist = self.config.getlist('PreRequists', 'Packages')
  1027.         if self.aptcdrom and not (self.useNetwork):
  1028.             logging.debug('Searching for pre-requists on CDROM')
  1029.             p = os.path.join(self.aptcdrom.cdrompath, 'dists/stable/main/dist-upgrader/binary-%s/' % apt_pkg.Config.Find('APT::Architecture'))
  1030.             found_pkgs = set()
  1031.             for udeb in glob.glob(p + '*_*.udeb'):
  1032.                 logging.debug("copying pre-req '%s' to '%s'" % (udeb, backportsdir))
  1033.                 found_pkgs.add(os.path.basename(udeb).split('_')[0])
  1034.                 shutil.copy(udeb, backportsdir)
  1035.             
  1036.             if not set(backportslist) == found_pkgs:
  1037.                 logging.error("Expected backports: '%s' but got '%s'" % (set(backportslist), found_pkgs))
  1038.                 return False
  1039.             return self.setupRequiredBackports(backportsdir)
  1040.         conf_option = 'SourcesList'
  1041.         if self.config.has_option('PreRequists', conf_option + '-%s' % self.arch):
  1042.             conf_option = conf_option + '-%s' % self.arch
  1043.         
  1044.         prereq_template = self.config.get('PreRequists', conf_option)
  1045.         if not os.path.exists(prereq_template):
  1046.             logging.error("sourceslist not found '%s'" % prereq_template)
  1047.             return False
  1048.         outpath = os.path.join(apt_pkg.Config.FindDir('Dir::Etc::sourceparts'), prereq_template)
  1049.         outfile = os.path.join(apt_pkg.Config.FindDir('Dir::Etc::sourceparts'), prereq_template)
  1050.         self._addPreRequistsSourcesList(prereq_template, outfile)
  1051.         
  1052.         try:
  1053.             self._verifyBackports()
  1054.         except NoBackportsFoundException:
  1055.             os.path.exists(prereq_template)
  1056.             e = os.path.exists(prereq_template)
  1057.             self._addPreRequistsSourcesList(prereq_template, outfile, dumb = True)
  1058.             
  1059.             try:
  1060.                 self._verifyBackports()
  1061.             except NoBackportsFoundException:
  1062.                 e = None
  1063.                 logging.warning("no backport for '%s' found" % e)
  1064.  
  1065.             return False
  1066.  
  1067.         cachedir = apt_pkg.Config.Find('Dir::Cache::archives')
  1068.         cwd = os.getcwd()
  1069.         if not os.path.exists(os.path.join(backportsdir, 'partial')):
  1070.             os.mkdir(os.path.join(backportsdir, 'partial'))
  1071.         
  1072.         os.chdir(backportsdir)
  1073.         apt_pkg.Config.Set('Dir::Cache::archives', backportsdir)
  1074.         for pkgname in backportslist:
  1075.             pkg = self.cache[pkgname]
  1076.             ver = self.cache._depcache.GetCandidateVer(pkg._pkg)
  1077.             if not ver:
  1078.                 logging.error("No candidate for '%s'" % pkgname)
  1079.                 os.unlink(outpath)
  1080.                 return False
  1081.             if ver.FileList == None:
  1082.                 logging.error("No ver.FileList for '%s'" % pkgname)
  1083.                 os.unlink(outpath)
  1084.                 return False
  1085.             logging.debug("marking '%s' for install" % pkgname)
  1086.             pkg.markInstall(autoFix = False)
  1087.         
  1088.         fetcher = apt_pkg.GetAcquire(self._view.getFetchProgress())
  1089.         pm = apt_pkg.GetPackageManager(self.cache._depcache)
  1090.         
  1091.         try:
  1092.             res = True
  1093.             self.cache._fetchArchives(fetcher, pm)
  1094.         except IOError:
  1095.             ver.FileList == None
  1096.             e = ver.FileList == None
  1097.             ver
  1098.             logging.error("_fetchArchives returned '%s'" % e)
  1099.             res = False
  1100.         except:
  1101.             ver.FileList == None
  1102.  
  1103.         os.unlink(outpath)
  1104.         apt_pkg.Config.Set('Dir::Cache::archives', cachedir)
  1105.         os.chdir(cwd)
  1106.         return self.setupRequiredBackports(backportsdir)
  1107.  
  1108.     
  1109.     def setupRequiredBackports(self, backportsdir):
  1110.         ''' setup the required backports in a evil way '''
  1111.         if not glob.glob(backportsdir + '/*.udeb'):
  1112.             logging.error('no backports found in setupRequiredBackports()')
  1113.             return False
  1114.         for deb in glob.glob(backportsdir + '/*.udeb'):
  1115.             logging.debug("extracting udeb '%s' " % deb)
  1116.             if os.system('dpkg-deb -x %s %s' % (deb, backportsdir)) != 0:
  1117.                 return False
  1118.         
  1119.         os.environ['LD_LIBRARY_PATH'] = backportsdir + '/usr/lib'
  1120.         os.environ['PYTHONPATH'] = backportsdir + '/usr/lib/python%s.%s/site-packages/' % (sys.version_info[0], sys.version_info[1])
  1121.         os.environ['PATH'] = '%s:%s' % (backportsdir + '/usr/bin', os.environ['PATH'])
  1122.         logging.shutdown()
  1123.         shutil.copy('/var/log/dist-upgrade/main.log', '/var/log/dist-upgrade/main_pre_req.log')
  1124.         args = sys.argv + [
  1125.             '--have-prerequists']
  1126.         if not S_IMODE(os.stat(sys.argv[0])[ST_MODE]) & S_IXUSR == S_IXUSR:
  1127.             os.chmod(sys.argv[0], 493)
  1128.         
  1129.         os.execve(sys.argv[0], args, os.environ)
  1130.  
  1131.     
  1132.     def preDoDistUpgrade(self):
  1133.         ''' this runs right before apt calls out to dpkg '''
  1134.         if os.path.exists('/usr/bin/killall'):
  1135.             subprocess.call([
  1136.                 'killall',
  1137.                 '-q',
  1138.                 'update-notifier'])
  1139.         
  1140.         if self.fromDist == 'dapper' and 'DISPLAY' in os.environ and 'SUDO_USER' in os.environ:
  1141.             out = subprocess.Popen([
  1142.                 'sudo',
  1143.                 '-u',
  1144.                 os.environ['SUDO_USER'],
  1145.                 './theme-switch-helper.py',
  1146.                 '-g'], stdout = subprocess.PIPE).communicate()[0]
  1147.             if 'Crux' in out:
  1148.                 subprocess.call([
  1149.                     'sudo',
  1150.                     '-u',
  1151.                     os.environ['SUDO_USER'],
  1152.                     './theme-switch-helper.py',
  1153.                     '--defaults'])
  1154.             
  1155.         
  1156.         return True
  1157.  
  1158.     
  1159.     def fullUpgrade(self):
  1160.         self._view.updateStatus(_('Checking package manager'))
  1161.         self._view.setStep(DistUpgradeView.STEP_PREPARE)
  1162.         if not self.prepare():
  1163.             logging.error('self.prepared() failed')
  1164.             self._view.error(_('Preparing the upgrade failed'), _("Preparing the system for the upgrade failed. Please report this as a bug against the 'update-manager' package and include the files in /var/log/dist-upgrade/ in the bug report."))
  1165.             sys.exit(1)
  1166.         
  1167.         if self.config.has_section('PreRequists') and self.options and self.options.havePrerequists == False:
  1168.             logging.debug('need backports')
  1169.             if not self.getRequiredBackports():
  1170.                 self._view.error(_('Getting upgrade prerequisites failed'), _("The system was unable to get the prerequisites for the upgrade. The upgrade will abort now and restore the original system state.\n\nPlease report this as a bug against the 'update-manager' package and include the files in /var/log/dist-upgrade/ in the bug report."))
  1171.                 self.abort()
  1172.             
  1173.         
  1174.         self.doUpdate(showErrors = False, forceRetries = 1)
  1175.         self.openCache()
  1176.         if not self.doPostInitialUpdate():
  1177.             self.abort()
  1178.         
  1179.         self._view.setStep(DistUpgradeView.STEP_MODIFY_SOURCES)
  1180.         self._view.updateStatus(_('Updating repository information'))
  1181.         if not self.updateSourcesList():
  1182.             self.abort()
  1183.         
  1184.         if self.aptcdrom and not self.aptcdrom.add(self.sources_backup_ext):
  1185.             sys.exit(1)
  1186.         
  1187.         if not self.doUpdate():
  1188.             self.abort()
  1189.         
  1190.         self._view.updateStatus(_('Checking package manager'))
  1191.         self.openCache()
  1192.         for pkg in self.config.getlist('Distro', 'BaseMetaPkgs'):
  1193.             if not self.cache.has_key(pkg):
  1194.                 logging.error("No '%s' after sources.list rewrite+update" % pkg)
  1195.                 self._view.error(_('Invalid package information'), _("After your package information was updated the essential package '%s' can not be found anymore.\nThis indicates a serious error, please report this bug against the 'update-manager' package and include the files in /var/log/dist-upgrade/ in the bug report.") % pkg)
  1196.                 self.abort()
  1197.                 continue
  1198.         
  1199.         self._view.updateStatus(_('Calculating the changes'))
  1200.         if not self.askDistUpgrade():
  1201.             self.abort()
  1202.         
  1203.         self._view.setStep(DistUpgradeView.STEP_FETCH)
  1204.         self._view.updateStatus(_('Fetching'))
  1205.         if not self.doDistUpgradeFetching():
  1206.             self.abort()
  1207.         
  1208.         self.preDoDistUpgrade()
  1209.         self._view.setStep(DistUpgradeView.STEP_INSTALL)
  1210.         self._view.updateStatus(_('Upgrading'))
  1211.         if not self.doDistUpgrade():
  1212.             self.runPostInstallScripts()
  1213.             self._view.information(_('Upgrade complete'), _('The upgrade is completed but there were errors during the upgrade process.'))
  1214.             sys.exit(1)
  1215.         
  1216.         self._view.setStep(DistUpgradeView.STEP_CLEANUP)
  1217.         self._view.updateStatus(_('Searching for obsolete software'))
  1218.         self.doPostUpgrade()
  1219.         self._view.setStep(DistUpgradeView.STEP_REBOOT)
  1220.         self._view.updateStatus(_('System upgrade is complete.'))
  1221.         if self._view.confirmRestart():
  1222.             p = subprocess.Popen('/sbin/reboot')
  1223.             sys.exit(0)
  1224.         
  1225.  
  1226.     
  1227.     def run(self):
  1228.         self._view.processEvents()
  1229.         self.fullUpgrade()
  1230.  
  1231.     
  1232.     def doPartialUpgrade(self):
  1233.         ''' partial upgrade mode, useful for repairing '''
  1234.         STEP_PREPARE = STEP_PREPARE
  1235.         STEP_MODIFY_SOURCES = STEP_MODIFY_SOURCES
  1236.         STEP_FETCH = STEP_FETCH
  1237.         STEP_INSTALL = STEP_INSTALL
  1238.         STEP_CLEANUP = STEP_CLEANUP
  1239.         STEP_REBOOT = STEP_REBOOT
  1240.         import DistUpgrade.DistUpgradeView
  1241.         self._view.setStep(STEP_PREPARE)
  1242.         self._view.hideStep(STEP_MODIFY_SOURCES)
  1243.         self._view.hideStep(STEP_REBOOT)
  1244.         self._partialUpgrade = True
  1245.         self.prepare()
  1246.         if not self.doPostInitialUpdate():
  1247.             return False
  1248.         if not self.askDistUpgrade():
  1249.             return False
  1250.         self._view.setStep(STEP_FETCH)
  1251.         self._view.updateStatus(_('Fetching'))
  1252.         if not self.doDistUpgradeFetching():
  1253.             return False
  1254.         self._view.setStep(STEP_INSTALL)
  1255.         self._view.updateStatus(_('Upgrading'))
  1256.         if not self.doDistUpgrade():
  1257.             self._view.information(_('Upgrade complete'), _('The upgrade is completed but there were errors during the upgrade process.'))
  1258.             return False
  1259.         self._view.setStep(STEP_CLEANUP)
  1260.         if not self.doPostUpgrade():
  1261.             self._view.information(_('Upgrade complete'), _('The upgrade is completed but there were errors during the upgrade process.'))
  1262.             return False
  1263.         self._view.information(_('Upgrade complete'), _('The partial upgrade was completed.'))
  1264.         return True
  1265.  
  1266.  
  1267. if __name__ == '__main__':
  1268.     from DistUpgradeView import DistUpgradeView
  1269.     from DistUpgradeViewText import DistUpgradeViewText
  1270.     from DistUpgradeCache import MyCache
  1271.     logging.basicConfig(level = logging.DEBUG)
  1272.     v = DistUpgradeViewText()
  1273.     dc = DistUpgradeController(v)
  1274.     dc._disableAptCronJob()
  1275.     dc._enableAptCronJob()
  1276.  
  1277.