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 / DistUpgradeCache.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-10-12  |  36.4 KB  |  1,056 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 os
  9. import os.path as os
  10. import re
  11. import logging
  12. import string
  13. import statvfs
  14. import time
  15. import gettext
  16. import datetime
  17. import threading
  18. import ConfigParser
  19. from subprocess import Popen, PIPE
  20. from DistUpgradeGettext import gettext as _
  21. from DistUpgradeGettext import ngettext
  22. from DistUpgradeConfigParser import DistUpgradeConfig
  23. from DistUpgradeView import FuzzyTimeToStr
  24.  
  25. class CacheException(Exception):
  26.     pass
  27.  
  28.  
  29. class CacheExceptionLockingFailed(CacheException):
  30.     pass
  31.  
  32.  
  33. class CacheExceptionDpkgInterrupted(CacheException):
  34.     pass
  35.  
  36. KERNEL_INITRD_SIZE = 15 * 1024 * 1024
  37.  
  38. class FreeSpaceRequired(object):
  39.     ''' FreeSpaceRequired object:
  40.     
  41.     This exposes:
  42.     - the total size required (size_total)
  43.     - the dir that requires the space (dir)
  44.     - the additional space that is needed (size_needed)
  45.     '''
  46.     
  47.     def __init__(self, size_total, dir, size_needed):
  48.         self.size_total = size_total
  49.         self.dir = dir
  50.         self.size_needed = size_needed
  51.  
  52.     
  53.     def __str__(self):
  54.         return 'FreeSpaceRequired Object: Dir: %s size_total: %s size_needed: %s' % (self.dir, self.size_total, self.size_needed)
  55.  
  56.  
  57.  
  58. class NotEnoughFreeSpaceError(CacheException):
  59.     ''' 
  60.     Exception if there is not enough free space for this operation 
  61.     
  62.     '''
  63.     
  64.     def __init__(self, free_space_required_list):
  65.         self.free_space_required_list = free_space_required_list
  66.  
  67.  
  68.  
  69. class MyCache(apt.Cache):
  70.     ReInstReq = 1
  71.     HoldReInstReq = 3
  72.     
  73.     def __init__(self, config, view, quirks, progress = None, lock = True):
  74.         apt.Cache.__init__(self, progress)
  75.         self.to_install = []
  76.         self.to_remove = []
  77.         self.view = view
  78.         self.quirks = quirks
  79.         self.lock = False
  80.         self.partialUpgrade = False
  81.         self.config = config
  82.         self.metapkgs = self.config.getlist('Distro', 'MetaPkgs')
  83.         self._listsLock = -1
  84.         if lock:
  85.             
  86.             try:
  87.                 apt_pkg.PkgSystemLock()
  88.                 self.lockListsDir()
  89.                 self.lock = True
  90.             except SystemError:
  91.                 e = None
  92.                 if 'dpkg --configure -a' in str(e):
  93.                     raise CacheExceptionDpkgInterrupted, e
  94.                 'dpkg --configure -a' in str(e)
  95.                 raise CacheExceptionLockingFailed, e
  96.             except:
  97.                 None<EXCEPTION MATCH>SystemError
  98.             
  99.  
  100.         None<EXCEPTION MATCH>SystemError
  101.         self.removal_blacklist = config.getListFromFile('Distro', 'RemovalBlacklistFile')
  102.         self.uname = Popen([
  103.             'uname',
  104.             '-r'], stdout = PIPE).communicate()[0].strip()
  105.         self._initAptLog()
  106.         if config.get('Sources', 'From') == 'hardy' and 'RELEASE_UPGRADE_NO_RECOMMENDS' not in os.environ:
  107.             apt_pkg.Config.Set('APT::Install-Recommends', 'true')
  108.         
  109.  
  110.     
  111.     def reqReinstallPkgs(self):
  112.         ''' return the packages not downloadable packages in reqreinst state '''
  113.         reqreinst = set()
  114.         for pkg in self:
  115.             if not (pkg.candidateDownloadable):
  116.                 if pkg._pkg.InstState == self.ReInstReq or pkg._pkg.InstState == self.HoldReInstReq:
  117.                     reqreinst.add(pkg.name)
  118.                     continue
  119.         
  120.         return reqreinst
  121.  
  122.     reqReinstallPkgs = property(reqReinstallPkgs)
  123.     
  124.     def fixReqReinst(self, view):
  125.         ''' check for reqreinst state and offer to fix it '''
  126.         reqreinst = self.reqReinstallPkgs
  127.         if len(reqreinst) > 0:
  128.             header = ngettext('Remove package in bad state', 'Remove packages in bad state', len(reqreinst))
  129.             summary = ngettext("The package '%s' is in an inconsistent state and needs to be reinstalled, but no archive can be found for it. Do you want to remove this package now to continue?", "The packages '%s' are in an inconsistent state and need to be reinstalled, but no archives can be found for them. Do you want to remove these packages now to continue?", len(reqreinst)) % ', '.join(reqreinst)
  130.             if view.askYesNoQuestion(header, summary):
  131.                 self.releaseLock()
  132.                 cmd = [
  133.                     'dpkg',
  134.                     '--remove',
  135.                     '--force-remove-reinstreq'] + list(reqreinst)
  136.                 view.getTerminal().call(cmd)
  137.                 self.getLock()
  138.                 return True
  139.         
  140.         return False
  141.  
  142.     
  143.     def _initAptLog(self):
  144.         ''' init logging, create log file'''
  145.         logdir = self.config.getWithDefault('Files', 'LogDir', '/var/log/dist-upgrade')
  146.         apt_pkg.Config.Set('Dir::Log', logdir)
  147.         apt_pkg.Config.Set('Dir::Log::Terminal', 'apt-term.log')
  148.         self.logfd = os.open(os.path.join(logdir, 'apt.log'), os.O_RDWR | os.O_CREAT | os.O_APPEND | os.O_SYNC, 420)
  149.         os.write(self.logfd, 'Log time: %s\n' % datetime.datetime.now())
  150.         apt_pkg.Config.Set('Debug::pkgProblemResolver', 'true')
  151.         apt_pkg.Config.Set('Debug::pkgDepCache::AutoInstall', 'true')
  152.  
  153.     
  154.     def _startAptResolverLog(self):
  155.         if hasattr(self, 'old_stdout'):
  156.             os.close(self.old_stdout)
  157.             os.close(self.old_stderr)
  158.         
  159.         self.old_stdout = os.dup(1)
  160.         self.old_stderr = os.dup(2)
  161.         os.dup2(self.logfd, 1)
  162.         os.dup2(self.logfd, 2)
  163.  
  164.     
  165.     def _stopAptResolverLog(self):
  166.         os.fsync(1)
  167.         os.fsync(2)
  168.         os.dup2(self.old_stdout, 1)
  169.         os.dup2(self.old_stderr, 2)
  170.  
  171.     
  172.     def withResolverLog(f):
  173.         ''' decorator to ensure that the apt output is logged '''
  174.         
  175.         def wrapper(*args, **kwargs):
  176.             args[0]._startAptResolverLog()
  177.             res = f(*args, **kwargs)
  178.             args[0]._stopAptResolverLog()
  179.             return res
  180.  
  181.         return wrapper
  182.  
  183.     
  184.     def requiredDownload(self):
  185.         ''' get the size of the packages that are required to download '''
  186.         pm = apt_pkg.GetPackageManager(self._depcache)
  187.         fetcher = apt_pkg.GetAcquire()
  188.         pm.GetArchives(fetcher, self._list, self._records)
  189.         return fetcher.FetchNeeded
  190.  
  191.     requiredDownload = property(requiredDownload)
  192.     
  193.     def additionalRequiredSpace(self):
  194.         ''' get the size of the additional required space on the fs '''
  195.         return self._depcache.UsrSize
  196.  
  197.     additionalRequiredSpace = property(additionalRequiredSpace)
  198.     
  199.     def isBroken(self):
  200.         ''' is the cache broken '''
  201.         return self._depcache.BrokenCount > 0
  202.  
  203.     isBroken = property(isBroken)
  204.     
  205.     def lockListsDir(self):
  206.         name = apt_pkg.Config.FindDir('Dir::State::Lists') + 'lock'
  207.         self._listsLock = apt_pkg.GetLock(name)
  208.         if self._listsLock < 0:
  209.             e = "Can not lock '%s' " % name
  210.             raise CacheExceptionLockingFailed, e
  211.         self._listsLock < 0
  212.  
  213.     
  214.     def unlockListsDir(self):
  215.         if self._listsLock > 0:
  216.             os.close(self._listsLock)
  217.             self._listsLock = -1
  218.         
  219.  
  220.     
  221.     def update(self, fprogress = None):
  222.         '''
  223.         our own update implementation is required because we keep the lists
  224.         dir lock
  225.         '''
  226.         self.unlockListsDir()
  227.         res = apt.Cache.update(self, fprogress)
  228.         self.lockListsDir()
  229.         if res == False:
  230.             raise IOError('apt.cache.update() returned False, but did not raise exception?!?')
  231.         res == False
  232.  
  233.     
  234.     def commit(self, fprogress, iprogress):
  235.         logging.info('cache.commit()')
  236.         if self.lock:
  237.             self.releaseLock()
  238.         
  239.         apt.Cache.commit(self, fprogress, iprogress)
  240.  
  241.     
  242.     def releaseLock(self, pkgSystemOnly = True):
  243.         if self.lock:
  244.             
  245.             try:
  246.                 apt_pkg.PkgSystemUnLock()
  247.                 self.lock = False
  248.             except SystemError:
  249.                 e = None
  250.                 logging.debug('failed to SystemUnLock() (%s) ' % e)
  251.             except:
  252.                 None<EXCEPTION MATCH>SystemError
  253.             
  254.  
  255.         None<EXCEPTION MATCH>SystemError
  256.  
  257.     
  258.     def getLock(self, pkgSystemOnly = True):
  259.         if not self.lock:
  260.             
  261.             try:
  262.                 apt_pkg.PkgSystemLock()
  263.                 self.lock = True
  264.             except SystemError:
  265.                 e = None
  266.                 logging.debug('failed to SystemLock() (%s) ' % e)
  267.             except:
  268.                 None<EXCEPTION MATCH>SystemError
  269.             
  270.  
  271.         None<EXCEPTION MATCH>SystemError
  272.  
  273.     
  274.     def downloadable(self, pkg, useCandidate = True):
  275.         ''' check if the given pkg can be downloaded '''
  276.         if useCandidate:
  277.             ver = self._depcache.GetCandidateVer(pkg._pkg)
  278.         else:
  279.             ver = pkg._pkg.CurrentVer
  280.         if ver == None:
  281.             logging.warning("no version information for '%s' (useCandidate=%s)" % (pkg.name, useCandidate))
  282.             return False
  283.         return ver.Downloadable
  284.  
  285.     
  286.     def fixBroken(self):
  287.         """ try to fix broken dependencies on the system, may throw
  288.             SystemError when it can't"""
  289.         return self._depcache.FixBroken()
  290.  
  291.     
  292.     def create_snapshot(self):
  293.         ''' create a snapshot of the current changes '''
  294.         self.to_install = []
  295.         self.to_remove = []
  296.         for pkg in self.getChanges():
  297.             if pkg.markedInstall or pkg.markedUpgrade:
  298.                 self.to_install.append(pkg.name)
  299.             
  300.             if pkg.markedDelete:
  301.                 self.to_remove.append(pkg.name)
  302.                 continue
  303.         
  304.  
  305.     
  306.     def clear(self):
  307.         self._depcache.Init()
  308.  
  309.     
  310.     def restore_snapshot(self):
  311.         ''' restore a snapshot '''
  312.         actiongroup = apt_pkg.GetPkgActionGroup(self._depcache)
  313.         self.clear()
  314.         for name in self.to_remove:
  315.             pkg = self[name]
  316.             pkg.markDelete()
  317.         
  318.         for name in self.to_install:
  319.             pkg = self[name]
  320.             pkg.markInstall(autoFix = False, autoInst = False)
  321.         
  322.  
  323.     
  324.     def needServerMode(self):
  325.         ''' 
  326.         This checks if we run on a desktop or a server install.
  327.         
  328.         A server install has more freedoms, for a desktop install
  329.         we force a desktop meta package to be install on the upgrade.
  330.  
  331.         We look for a installed desktop meta pkg and for key 
  332.         dependencies, if none of those are installed we assume
  333.         server mode
  334.         '''
  335.         metapkgs = self.config.getlist('Distro', 'MetaPkgs')
  336.         for key in metapkgs:
  337.             if self.has_key(key) and self[key].isInstalled:
  338.                 logging.debug("needServerMode(): run in 'desktop' mode, (because of pkg '%s')" % key)
  339.                 return False
  340.             deps_found = True
  341.             for pkg in self.config.getlist(key, 'KeyDependencies'):
  342.                 if self.has_key(pkg):
  343.                     pass
  344.                 deps_found &= self[pkg].isInstalled
  345.             
  346.             if deps_found:
  347.                 logging.debug("needServerMode(): run in 'desktop' mode, (because of key deps for '%s')" % key)
  348.                 return False
  349.         
  350.         logging.debug('needServerMode(): can not find a desktop meta package or key deps, running in server mode')
  351.         return True
  352.  
  353.     
  354.     def sanityCheck(self, view):
  355.         ''' check if the cache is ok and if the required metapkgs
  356.             are installed
  357.         '''
  358.         if self.isBroken:
  359.             
  360.             try:
  361.                 logging.debug('Have broken pkgs, trying to fix them')
  362.                 self.fixBroken()
  363.             except SystemError:
  364.                 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."))
  365.                 return False
  366.             
  367.  
  368.         None<EXCEPTION MATCH>SystemError
  369.         return True
  370.  
  371.     
  372.     def markInstall(self, pkg, reason = ''):
  373.         logging.debug("Installing '%s' (%s)" % (pkg, reason))
  374.         if self.has_key(pkg):
  375.             self[pkg].markInstall()
  376.             if not self[pkg].markedInstall or self[pkg].markedUpgrade:
  377.                 logging.error("Installing/upgrading '%s' failed" % pkg)
  378.             
  379.         
  380.  
  381.     
  382.     def markUpgrade(self, pkg, reason = ''):
  383.         logging.debug("Upgrading '%s' (%s)" % (pkg, reason))
  384.         if self.has_key(pkg) and self[pkg].isInstalled:
  385.             self[pkg].markUpgrade()
  386.             if not self[pkg].markedUpgrade:
  387.                 logging.error("Upgrading '%s' failed" % pkg)
  388.             
  389.         
  390.  
  391.     
  392.     def markRemove(self, pkg, reason = ''):
  393.         logging.debug("Removing '%s' (%s)" % (pkg, reason))
  394.         if self.has_key(pkg):
  395.             self[pkg].markDelete()
  396.         
  397.  
  398.     
  399.     def markPurge(self, pkg, reason = ''):
  400.         logging.debug("Purging '%s' (%s)" % (pkg, reason))
  401.         if self.has_key(pkg):
  402.             self._depcache.MarkDelete(self[pkg]._pkg, True)
  403.         
  404.  
  405.     
  406.     def keepInstalledRule(self):
  407.         ''' run after the dist-upgrade to ensure that certain
  408.             packages are kept installed '''
  409.         
  410.         def keepInstalled(self, pkgname, reason):
  411.             if self.has_key(pkgname) and self[pkgname].isInstalled and self[pkgname].markedDelete:
  412.                 self.markInstall(pkgname, reason)
  413.             
  414.  
  415.         for pkgname in self.config.getlist('Distro', 'KeepInstalledPkgs'):
  416.             keepInstalled(self, pkgname, 'Distro KeepInstalledPkgs rule')
  417.         
  418.         for key in self.metapkgs:
  419.             if self.has_key(key):
  420.                 if self[key].isInstalled or self[key].markedInstall:
  421.                     for pkgname in self.config.getlist(key, 'KeepInstalledPkgs'):
  422.                         keepInstalled(self, pkgname, '%s KeepInstalledPkgs rule' % key)
  423.                     
  424.         
  425.         if self.config.get('Options', 'withNetwork') == 'True':
  426.             logging.debug('Running KeepInstalledSection rules')
  427.             for section in self.config.getlist('Distro', 'KeepInstalledSection'):
  428.                 for pkg in self:
  429.                     if pkg.markedDelete and pkg.section == section:
  430.                         keepInstalled(self, pkg.name, 'Distro KeepInstalledSection rule: %s' % section)
  431.                         continue
  432.                 
  433.             
  434.             for key in self.metapkgs:
  435.                 if self.has_key(key):
  436.                     if self[key].isInstalled or self[key].markedInstall:
  437.                         for section in self.config.getlist(key, 'KeepInstalledSection'):
  438.                             for pkg in self:
  439.                                 if pkg.markedDelete and pkg.section == section:
  440.                                     keepInstalled(self, pkg.name, '%s KeepInstalledSection rule: %s' % (key, section))
  441.                                     continue
  442.                             
  443.                         
  444.             
  445.         
  446.  
  447.     
  448.     def postUpgradeRule(self):
  449.         ''' run after the upgrade was done in the cache '''
  450.         for rule, action in [
  451.             ('Install', self.markInstall),
  452.             ('Upgrade', self.markUpgrade),
  453.             ('Remove', self.markRemove),
  454.             ('Purge', self.markPurge)]:
  455.             for pkg in self.config.getlist('Distro', 'PostUpgrade%s' % rule):
  456.                 action(pkg, 'Distro PostUpgrade%s rule' % rule)
  457.             
  458.             for key in self.metapkgs:
  459.                 if self.has_key(key):
  460.                     if self[key].isInstalled or self[key].markedInstall:
  461.                         for pkg in self.config.getlist(key, 'PostUpgrade%s' % rule):
  462.                             action(pkg, '%s PostUpgrade%s rule' % (key, rule))
  463.                         
  464.             
  465.         
  466.         if not self.partialUpgrade:
  467.             self.quirks.run('PostDistUpgradeCache')
  468.         
  469.  
  470.     
  471.     def identifyObsoleteKernels(self):
  472.         logging.debug('identifyObsoleteKernels()')
  473.         obsolete_kernels = set()
  474.         version = self.config.get('KernelRemoval', 'Version')
  475.         basenames = self.config.getlist('KernelRemoval', 'BaseNames')
  476.         types = self.config.getlist('KernelRemoval', 'Types')
  477.         for pkg in self:
  478.             for base in basenames:
  479.                 basename = '%s-%s-' % (base, version)
  480.                 for type in types:
  481.                     if pkg.name.startswith(basename) and pkg.name.endswith(type) and pkg.isInstalled:
  482.                         if pkg.name == '%s-%s' % (base, self.uname):
  483.                             logging.debug('skipping running kernel %s' % pkg.name)
  484.                             continue
  485.                         
  486.                         logging.debug("removing obsolete kernel '%s'" % pkg.name)
  487.                         obsolete_kernels.add(pkg.name)
  488.                         continue
  489.                 
  490.             
  491.         
  492.         logging.debug("identifyObsoleteKernels found '%s'" % obsolete_kernels)
  493.         return obsolete_kernels
  494.  
  495.     
  496.     def checkForNvidia(self):
  497.         ''' 
  498.         this checks for nvidia hardware and checks what driver is needed
  499.         '''
  500.         logging.debug('nvidiaUpdate()')
  501.         
  502.         try:
  503.             NvidiaDetection = NvidiaDetection
  504.             import NvidiaDetector.nvidiadetector
  505.         except ImportError:
  506.             e = None
  507.             logging.error('NvidiaDetector can not be imported %s' % e)
  508.             return False
  509.  
  510.         
  511.         try:
  512.             nv = NvidiaDetection(datadir = './modaliases/')
  513.             for oldDriver in nv.oldPackages:
  514.                 if self.has_key(oldDriver) and self[oldDriver].isInstalled:
  515.                     self.markRemove(oldDriver, 'old nvidia driver')
  516.                     break
  517.                     continue
  518.             else:
  519.                 return False
  520.             driver = None.selectDriver()
  521.             logging.debug("nv.selectDriver() returned '%s'" % driver)
  522.             if self.has_key(driver):
  523.                 if not self[driver].markedInstall:
  524.                     pass
  525.                 if not (self[driver].markedUpgrade):
  526.                     self[driver].markInstall()
  527.                     logging.info('installing %s as suggested by NvidiaDetector' % driver)
  528.                     return True
  529.         except Exception:
  530.             e = None
  531.             logging.error('NvidiaDetection returned a error: %s' % e)
  532.  
  533.         return False
  534.  
  535.     
  536.     def checkForKernel(self):
  537.         ''' check for the running kernel and try to ensure that we have
  538.             an updated version
  539.         '''
  540.         logging.debug("Kernel uname: '%s' " % self.uname)
  541.         
  542.         try:
  543.             (version, build, flavour) = self.uname.split('-')
  544.         except Exception:
  545.             e = None
  546.             logging.warning("Can't parse kernel uname: '%s' (self compiled?)" % e)
  547.             return False
  548.  
  549.         dmesg = Popen([
  550.             'dmesg'], stdout = PIPE).communicate()[0]
  551.         if 'WARNING: NR_CPUS limit' in dmesg:
  552.             logging.debug('UP kernel on SMP system!?!')
  553.             flavour = 'generic'
  554.         
  555.         kernel = 'linux-image-%s' % flavour
  556.         if not self.has_key(kernel):
  557.             logging.warning("No kernel: '%s'" % kernel)
  558.             return False
  559.         if not self[kernel].isInstalled or self[kernel].markedInstall:
  560.             logging.debug("Selecting new kernel '%s'" % kernel)
  561.             self[kernel].markInstall()
  562.         
  563.         return True
  564.  
  565.     
  566.     def checkPriority(self):
  567.         need = ('required',)
  568.         removeEssentialOk = self.config.getlist('Distro', 'RemoveEssentialOk')
  569.         for pkg in self:
  570.             ver = pkg._pcache._depcache.GetCandidateVer(pkg._pkg)
  571.             if ver and ver.Priority == 0:
  572.                 logging.error('Package %s has no priority set' % pkg.name)
  573.                 continue
  574.             
  575.             if pkg.candidateDownloadable:
  576.                 if not pkg.isInstalled:
  577.                     pass
  578.                 if not (pkg.markedInstall) and pkg.name not in removeEssentialOk and pkg.priority in need:
  579.                     self.markInstall(pkg.name, "priority in required set '%s' but not scheduled for install" % need)
  580.                     continue
  581.         
  582.  
  583.     
  584.     def updateGUI(self, view, lock):
  585.         while lock.locked():
  586.             view.processEvents()
  587.             time.sleep(0.01)
  588.  
  589.     
  590.     def distUpgrade(self, view, serverMode, partialUpgrade):
  591.         lock = threading.Lock()
  592.         lock.acquire()
  593.         t = threading.Thread(target = self.updateGUI, args = (self.view, lock))
  594.         t.start()
  595.         
  596.         try:
  597.             self.upgrade(True)
  598.             self.checkPriority()
  599.             self.keepInstalledRule()
  600.             self.checkForKernel()
  601.             self.checkForNvidia()
  602.             self.postUpgradeRule()
  603.             if not serverMode:
  604.                 self._installMetaPkgs(view)
  605.             
  606.             self._verifyChanges()
  607.         except SystemError:
  608.             e = None
  609.             lock.release()
  610.             t.join()
  611.             details = _('An unresolvable problem occurred while calculating the upgrade:\n%s\n\n This can be caused by:\n * Upgrading to a pre-release version of Ubuntu\n * Running the current pre-release version of Ubuntu\n * Unofficial software packages not provided by Ubuntu\n\n' % e)
  612.             if partialUpgrade:
  613.                 details += _('This is most likely a transient problem, please try again later.')
  614.             else:
  615.                 details += _("If none of this applies, then please report this bug against the 'update-manager' package and include the files in /var/log/dist-upgrade/ in the bug report.")
  616.             self._stopAptResolverLog()
  617.             view.error(_('Could not calculate the upgrade'), details)
  618.             self._startAptResolverLog()
  619.             logging.error("Dist-upgrade failed: '%s'", e)
  620.             return False
  621.  
  622.         lock.release()
  623.         t.join()
  624.         untrusted = []
  625.         for pkg in self.getChanges():
  626.             if pkg.markedDelete:
  627.                 continue
  628.             
  629.             if pkg.markedDowngrade:
  630.                 for ver in pkg._pkg.VersionList:
  631.                     if apt_pkg.VersionCompare(ver.VerStr, pkg.installedVersion) < 0:
  632.                         for verFileIter, index in ver.FileList:
  633.                             indexfile = pkg._list.FindIndex(verFileIter)
  634.                             if indexfile and not (indexfile.IsTrusted):
  635.                                 untrusted.append(pkg.name)
  636.                                 break
  637.                                 continue
  638.                         
  639.                 
  640.                 continue
  641.             
  642.             origins = pkg.candidateOrigin
  643.             trusted = False
  644.             for origin in origins:
  645.                 trusted |= origin.trusted
  646.             
  647.             if not trusted:
  648.                 untrusted.append(pkg.name)
  649.                 continue
  650.         
  651.         
  652.         try:
  653.             b = self.config.getboolean('Distro', 'AllowUnauthenticated')
  654.             if b:
  655.                 logging.warning('AllowUnauthenticated set!')
  656.                 return True
  657.         except ConfigParser.NoOptionError:
  658.             e = None
  659.  
  660.         if len(untrusted) > 0:
  661.             untrusted.sort()
  662.             logging.error("Unauthenticated packages found: '%s'" % ' '.join(untrusted))
  663.             self._stopAptResolverLog()
  664.             view.error(_('Error authenticating some packages'), _('It was not possible to authenticate some packages. This may be a transient network problem. You may want to try again later. See below for a list of unauthenticated packages.'), '\n'.join(untrusted))
  665.             self._startAptResolverLog()
  666.             return False
  667.         return True
  668.  
  669.     distUpgrade = withResolverLog(distUpgrade)
  670.     
  671.     def _verifyChanges(self):
  672.         """ this function tests if the current changes don't violate
  673.             our constrains (blacklisted removals etc)
  674.         """
  675.         removeEssentialOk = self.config.getlist('Distro', 'RemoveEssentialOk')
  676.         for pkg in self.getChanges():
  677.             if pkg.markedDelete and self._inRemovalBlacklist(pkg.name):
  678.                 logging.debug("The package '%s' is marked for removal but it's in the removal blacklist", pkg.name)
  679.                 raise SystemError, _("The package '%s' is marked for removal but it is in the removal blacklist.") % pkg.name
  680.             self._inRemovalBlacklist(pkg.name)
  681.             if pkg.markedDelete and pkg._pkg.Essential == True and pkg.name not in removeEssentialOk:
  682.                 logging.debug("The package '%s' is marked for removal but it's a ESSENTIAL package", pkg.name)
  683.                 raise SystemError, _("The essential package '%s' is marked for removal.") % pkg.name
  684.             pkg.name not in removeEssentialOk
  685.         
  686.         badVersions = self.config.getlist('Distro', 'BadVersions')
  687.         for bv in badVersions:
  688.             (pkgname, ver) = bv.split('_')
  689.             if self.has_key(pkgname) and self[pkgname].candidateVersion == ver:
  690.                 if self[pkgname].markedInstall or self[pkgname].markedUpgrade:
  691.                     raise SystemError, "Trying to install blacklisted version '%s'" % bv
  692.             self[pkgname].markedUpgrade
  693.         
  694.         return True
  695.  
  696.     
  697.     def installedTasks(self):
  698.         tasks = { }
  699.         installed_tasks = set()
  700.         for pkg in self:
  701.             if not pkg._lookupRecord():
  702.                 logging.debug("no PkgRecord found for '%s', skipping " % pkg.name)
  703.                 continue
  704.             
  705.             for line in pkg._pcache._records.Record.split('\n'):
  706.                 if line.startswith('Task:'):
  707.                     for task in line[len('Task:'):].split(','):
  708.                         task = task.strip()
  709.                         if not tasks.has_key(task):
  710.                             tasks[task] = set()
  711.                         
  712.                         tasks[task].add(pkg.name)
  713.                     
  714.             
  715.         
  716.         for task in tasks:
  717.             installed = True
  718.             for pkgname in tasks[task]:
  719.                 if not self[pkgname].isInstalled:
  720.                     installed = False
  721.                     break
  722.                     continue
  723.             
  724.             if installed:
  725.                 installed_tasks.add(task)
  726.                 continue
  727.         
  728.         return installed_tasks
  729.  
  730.     installedTasks = property(installedTasks)
  731.     
  732.     def installTasks(self, tasks):
  733.         logging.debug('running installTasks')
  734.         for pkg in self:
  735.             if pkg.markedInstall or pkg.isInstalled:
  736.                 continue
  737.             
  738.             pkg._lookupRecord()
  739.             if not hasattr(pkg._pcache._records, 'Record') and pkg._pcache._records.Record:
  740.                 logging.warning("can not find Record for '%s'" % pkg.name)
  741.                 continue
  742.             
  743.             for line in pkg._pcache._records.Record.split('\n'):
  744.                 if line.startswith('Task:'):
  745.                     for task in line[len('Task:'):].split(','):
  746.                         task = task.strip()
  747.                         if task in tasks:
  748.                             pkg.markInstall()
  749.                             continue
  750.                     
  751.             
  752.         
  753.         return True
  754.  
  755.     
  756.     def _installMetaPkgs(self, view):
  757.         
  758.         def metaPkgInstalled():
  759.             ''' 
  760.             internal helper that checks if at least one meta-pkg is 
  761.             installed or marked install
  762.             '''
  763.             for key in metapkgs:
  764.                 if self.has_key(key):
  765.                     pkg = self[key]
  766.                     if pkg.isInstalled and pkg.markedDelete:
  767.                         logging.debug("metapkg '%s' installed but markedDelete" % pkg.name)
  768.                     
  769.                     if pkg.isInstalled or not (pkg.markedDelete) or self[key].markedInstall:
  770.                         return True
  771.                     continue
  772.                 self[key].markedInstall
  773.             
  774.             return False
  775.  
  776.         metapkgs = self.config.getlist('Distro', 'MetaPkgs')
  777.         for pkg in self.config.getlist('Distro', 'BaseMetaPkgs'):
  778.             self[pkg].markInstall()
  779.         
  780.         for key in metapkgs:
  781.             
  782.             try:
  783.                 if self.has_key(key) and self[key].isInstalled:
  784.                     logging.debug("Marking '%s' for upgrade" % key)
  785.                     self[key].markUpgrade()
  786.             continue
  787.             except SystemError:
  788.                 (None, None)
  789.                 e = (None, None)
  790.                 logging.debug("Can't mark '%s' for upgrade (%s)" % (key, e))
  791.                 raise SystemError, _("Can not mark '%s' for upgrade") % key
  792.                 continue
  793.             
  794.  
  795.         
  796.         if not metaPkgInstalled():
  797.             view.error(_("Can't guess meta-package"), _('Your system does not contain a ubuntu-desktop, kubuntu-desktop, xubuntu-desktop or edubuntu-desktop package and it was not possible to detect which version of Ubuntu you are running.\n Please install one of the packages above first using synaptic or apt-get before proceeding.'))
  798.             return False
  799.         return True
  800.  
  801.     
  802.     def _inRemovalBlacklist(self, pkgname):
  803.         for expr in self.removal_blacklist:
  804.             if re.compile(expr).match(pkgname):
  805.                 return True
  806.         
  807.         return False
  808.  
  809.     
  810.     def tryMarkObsoleteForRemoval(self, pkgname, remove_candidates, foreign_pkgs):
  811.         if pkgname.endswith(self.uname):
  812.             logging.debug("skipping running kernel pkg '%s'" % pkgname)
  813.             return False
  814.         if self._inRemovalBlacklist(pkgname):
  815.             logging.debug("skipping '%s' (in removalBlacklist)" % pkgname)
  816.             return False
  817.         for section in self.config.getlist('Distro', 'KeepInstalledSection'):
  818.             if self.has_key(pkgname) and self[pkgname].section == section:
  819.                 logging.debug("skipping '%s' (in KeepInstalledSection)" % pkgname)
  820.                 return False
  821.         
  822.         if not self.has_key(pkgname):
  823.             return True
  824.         
  825.         try:
  826.             purge = self.config.getboolean('Distro', 'PurgeObsoletes')
  827.         except ConfigParser.NoOptionError:
  828.             self.has_key(pkgname)
  829.             e = self.has_key(pkgname)
  830.             self[pkgname].section == section
  831.             purge = False
  832.         except:
  833.             self._inRemovalBlacklist(pkgname)
  834.  
  835.         actiongroup = apt_pkg.GetPkgActionGroup(self._depcache)
  836.         self.create_snapshot()
  837.         
  838.         try:
  839.             self[pkgname].markDelete(purge = purge)
  840.             self.view.processEvents()
  841.             for pkg in self.getChanges():
  842.                 if pkg.name not in remove_candidates and pkg.name in foreign_pkgs or self._inRemovalBlacklist(pkg.name):
  843.                     logging.debug("package '%s' has unwanted removals, skipping" % pkgname)
  844.                     self.restore_snapshot()
  845.                     return False
  846.         except (SystemError, KeyError):
  847.             self._inRemovalBlacklist(pkgname)
  848.             e = self._inRemovalBlacklist(pkgname)
  849.             pkgname.endswith(self.uname)
  850.             logging.warning("_tryMarkObsoleteForRemoval failed for '%s' (%s: %s)" % (pkgname, repr(e), e))
  851.             self.restore_snapshot()
  852.             return False
  853.  
  854.         return True
  855.  
  856.     tryMarkObsoleteForRemoval = withResolverLog(tryMarkObsoleteForRemoval)
  857.     
  858.     def _getObsoletesPkgs(self):
  859.         ''' get all package names that are not downloadable '''
  860.         obsolete_pkgs = set()
  861.         for pkg in self:
  862.             if pkg.isInstalled:
  863.                 if not self.anyVersionDownloadable(pkg):
  864.                     obsolete_pkgs.add(pkg.name)
  865.                 
  866.             self.anyVersionDownloadable(pkg)
  867.         
  868.         return obsolete_pkgs
  869.  
  870.     
  871.     def anyVersionDownloadable(self, pkg):
  872.         ''' helper that checks if any of the version of pkg is downloadable '''
  873.         for ver in pkg._pkg.VersionList:
  874.             if ver.Downloadable:
  875.                 return True
  876.         
  877.         return False
  878.  
  879.     
  880.     def _getUnusedDependencies(self):
  881.         ''' get all package names that are not downloadable '''
  882.         unused_dependencies = set()
  883.         for pkg in self:
  884.             if pkg.isInstalled and self._depcache.IsGarbage(pkg._pkg):
  885.                 unused_dependencies.add(pkg.name)
  886.                 continue
  887.         
  888.         return unused_dependencies
  889.  
  890.     
  891.     def _getForeignPkgs(self, allowed_origin, fromDist, toDist):
  892.         ''' get all packages that are installed from a foreign repo
  893.             (and are actually downloadable)
  894.         '''
  895.         foreign_pkgs = set()
  896.         for pkg in self:
  897.             if pkg.isInstalled and self.downloadable(pkg):
  898.                 foreign = True
  899.                 for origin in pkg.candidateOrigin:
  900.                     if fromDist in origin.archive and origin.origin == allowed_origin:
  901.                         foreign = False
  902.                     
  903.                     if toDist in origin.archive and origin.origin == allowed_origin:
  904.                         foreign = False
  905.                         continue
  906.                 
  907.                 if foreign:
  908.                     foreign_pkgs.add(pkg.name)
  909.                 
  910.             foreign
  911.         
  912.         return foreign_pkgs
  913.  
  914.     
  915.     def checkFreeSpace(self):
  916.         '''
  917.         this checks if we have enough free space on /var, /boot and /usr
  918.         with the given cache 
  919.  
  920.         Note: this can not be fully accurate if there are multiple 
  921.               mountpoints for /usr, /var, /boot
  922.         '''
  923.         
  924.         class FreeSpace(object):
  925.             ''' helper class that represents the free space on each mounted fs '''
  926.             
  927.             def __init__(self, initialFree):
  928.                 self.free = initialFree
  929.                 self.need = 0
  930.  
  931.  
  932.         
  933.         def make_fs_id(d):
  934.             """ return 'id' of a directory so that directories on the
  935.                 same filesystem get the same id (simply the mount_point)
  936.             """
  937.             for mount_point in mounted:
  938.                 if d.startswith(mount_point):
  939.                     return mount_point
  940.             
  941.             return '/'
  942.  
  943.         mounted = []
  944.         mnt_map = { }
  945.         fs_free = { }
  946.         for line in open('/proc/mounts'):
  947.             
  948.             try:
  949.                 (what, where, fs, options, a, b) = line.split()
  950.             except ValueError:
  951.                 (None,)
  952.                 e = (None,)
  953.                 logging.debug("line '%s' in /proc/mounts not understood (%s)" % (line, e))
  954.                 continue
  955.             except:
  956.                 (None,)
  957.  
  958.             if where not in mounted:
  959.                 mounted.append(where)
  960.                 continue
  961.             (None,)
  962.         
  963.         mounted.sort(cmp = (lambda a, b: cmp(len(a), len(b))), reverse = True)
  964.         archivedir = apt_pkg.Config.FindDir('Dir::Cache::archives')
  965.         aufs_rw_dir = '/tmp/'
  966.         if hasattr(self, 'config') and self.config.getWithDefault('Aufs', 'Enabled', False):
  967.             aufs_rw_dir = self.config.get('Aufs', 'RWDir')
  968.             if not os.path.exists(aufs_rw_dir):
  969.                 os.makedirs(aufs_rw_dir)
  970.             
  971.         
  972.         logging.debug('cache aufs_rw_dir: %s' % aufs_rw_dir)
  973.         for d in [
  974.             '/',
  975.             '/usr',
  976.             '/var',
  977.             '/boot',
  978.             archivedir,
  979.             aufs_rw_dir,
  980.             '/home']:
  981.             d = os.path.realpath(d)
  982.             fs_id = make_fs_id(d)
  983.             st = os.statvfs(d)
  984.             free = st[statvfs.F_BAVAIL] * st[statvfs.F_FRSIZE]
  985.             if fs_id in mnt_map:
  986.                 logging.debug('Dir %s mounted on %s' % (d, mnt_map[fs_id]))
  987.                 fs_free[d] = fs_free[mnt_map[fs_id]]
  988.                 continue
  989.             logging.debug('Free space on %s: %s' % (d, free))
  990.             mnt_map[fs_id] = d
  991.             fs_free[d] = FreeSpace(free)
  992.         
  993.         del mnt_map
  994.         logging.debug("fs_free contains: '%s'" % fs_free)
  995.         space_in_boot = 0
  996.         for pkg in self:
  997.             if re.match('^linux-(image|image-debug)-[0-9.]*-.*', pkg.name):
  998.                 if pkg.markedInstall:
  999.                     logging.debug('%s (new-install) added with %s to boot space' % (pkg.name, KERNEL_INITRD_SIZE))
  1000.                     space_in_boot += KERNEL_INITRD_SIZE
  1001.                 
  1002.             pkg.markedInstall
  1003.         
  1004.         required_for_aufs = 0
  1005.         if hasattr(self, 'config') and self.config.getWithDefault('Aufs', 'Enabled', False):
  1006.             logging.debug('taking aufs overlay into space calculation')
  1007.             aufs_rw_dir = self.config.get('Aufs', 'RWDir')
  1008.             for pkg in self:
  1009.                 if pkg.markedUpgrade or pkg.markedInstall:
  1010.                     required_for_aufs += self._depcache.GetCandidateVer(pkg._pkg).Size
  1011.                     continue
  1012.             
  1013.         
  1014.         for dir, size in [
  1015.             (archivedir, self.requiredDownload),
  1016.             ('/usr', self.additionalRequiredSpace),
  1017.             ('/usr', 52428800),
  1018.             ('/boot', space_in_boot),
  1019.             ('/', 10485760),
  1020.             (aufs_rw_dir, required_for_aufs)]:
  1021.             dir = os.path.realpath(dir)
  1022.             logging.debug("dir '%s' needs '%s' of '%s' (%f)" % (dir, size, fs_free[dir], fs_free[dir].free))
  1023.             fs_free[dir].free -= size
  1024.             fs_free[dir].need += size
  1025.         
  1026.         required_list = { }
  1027.         for dir in fs_free:
  1028.             if fs_free[dir].free < 0:
  1029.                 free_at_least = apt_pkg.SizeToStr(float(abs(fs_free[dir].free) + 1))
  1030.                 required_list[make_fs_id(dir)] = FreeSpaceRequired(apt_pkg.SizeToStr(fs_free[dir].need), make_fs_id(dir), free_at_least)
  1031.                 continue
  1032.             fs_free[dir]
  1033.         
  1034.         if len(required_list) > 0:
  1035.             []([] % [ str(i) for i in required_list ])
  1036.             raise NotEnoughFreeSpaceError(required_list.values())
  1037.         len(required_list) > 0
  1038.         return True
  1039.  
  1040.  
  1041. if __name__ == '__main__':
  1042.     import DistUpgradeConfigParser
  1043.     import DistUpgradeView
  1044.     print 'foo'
  1045.     c = MyCache(DistUpgradeConfigParser.DistUpgradeConfig('.'), DistUpgradeView.DistUpgradeView(), None)
  1046.     print c.checkFreeSpace()
  1047.     sys.exit()
  1048.     c.clear()
  1049.     c.create_snapshot()
  1050.     c.installedTasks
  1051.     c.installTasks([
  1052.         'ubuntu-desktop'])
  1053.     print c.getChanges()
  1054.     c.restore_snapshot()
  1055.  
  1056.