diff options
Diffstat (limited to 'yum-presto/shared/prestoDownload.py')
-rw-r--r-- | yum-presto/shared/prestoDownload.py | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/yum-presto/shared/prestoDownload.py b/yum-presto/shared/prestoDownload.py new file mode 100644 index 0000000..340ad1c --- /dev/null +++ b/yum-presto/shared/prestoDownload.py @@ -0,0 +1,171 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright 2005 Duke University +# Copyright 2007 Jonathan Dieter + +import os +from yum import misc +from yum import Errors +from yum import types +from urlgrabber.grabber import URLGrabError +import deltarpm + +def verifyDelta(fo, po, conduit, raiseError): + """verifies the deltarpm is what we expect it to be + raiseError = defaults to 0 - if 1 then will raise + a URLGrabError if the file does not check out. + otherwise it returns false for a failure, true for success""" + + if type(fo) is types.InstanceType: + fo = fo.filename + + try: + verifyChecksum(fo, po.returnSimple('deltachecksumtype'), po.returnSimple('deltachecksum')) + except: + if raiseError: + raise URLGrabError(-1, 'Package does not match intended download') + else: + return False + + return True + + +def verifyChecksum(filename, checksumType, csum): + """Verify the checksum of the file versus the + provided checksum""" + + try: + + filesum = misc.checksum(checksumType, filename) + except Errors.MiscError, e: + raise URLGrabError(-3, 'Could not perform checksum') + + if filesum != csum: + raise URLGrabError(-1, 'Package does not match checksum') + + return 0 + + +def downloadPkgs(conduit, pkglist): + """download list of package objects handed to you, return errors""" + + opts, commands = conduit.getCmdLine() + + errors = {} + def adderror(po, msg): + errors.setdefault(po, []).append(msg) + + # Check whether drpm is already downloaded + repo_cached = False + remote_pkgs = [] + rebuild_pkgs = [] + for po in conduit.getDownloadPackages(): + if hasattr(po, 'has_drpm') and po.has_drpm: + po.to.pkgtup = po.to.realpkgtup + local = po.returnSimple('deltalocalpath') + if os.path.exists(local): + cursize = os.stat(local)[6] + totsize = long(po.returnSimple('deltasize')) + try: + verifyChecksum(local, po.returnSimple('deltachecksumtype'), po.returnSimple('deltachecksum')) + except: + if po.repo.p_repo.cache: + repo_cached = True + adderror(po, 'package fails checksum but caching is ' + 'enabled for %s' % po.repo.p_repo.id) + + if cursize >= totsize: # otherwise keep it around for regetting + os.unlink(local) + else: + # Deltarpm is local and good, let's put it in the rebuild list + conduit.info(5, "using local copy of deltarpm for %s" % po) + rebuild_pkgs.append(po) + continue + remote_pkgs.append(po) + + # Download deltarpms + i = 0 + for po in remote_pkgs: + i += 1 + checkfunc = (verifyDelta, (po, conduit, 1), {}) + cache = po.repo.p_repo.http_caching != 'none' + dirstat = os.statvfs(po.repo.deltasdir) + if (dirstat.f_bavail * dirstat.f_bsize) <= long(po.size): + adderror(po, 'Insufficient space in download directory %s ' + 'to download' % po.repo.deltasdir) + continue + po.simple['reallocalpath'] = po.localpath + po.localpath = po.returnSimple('deltalocalpath') + po.simple['realrelativepath'] = po.returnSimple('relativepath') + po.simple['relativepath'] = po.returnSimple('deltarelativepath') + try: + text = '(%s/%s): %s' % (i, len(remote_pkgs), os.path.basename(po.returnSimple('deltarelativepath'))) + deltalocal = po.repo.p_repo.getPackage(po, checkfunc=checkfunc, text=text, cache=cache) + except Errors.RepoError, e: + adderror(po, str(e)) + else: + rebuild_pkgs.append(po) + po.simple['deltalocalpath'] = deltalocal + + if errors.has_key(po): + del errors[po] + + po.simple['relativepath'] = po.returnSimple('realrelativepath') + po.localpath = po.returnSimple('reallocalpath') + if po.simple.has_key('realpackagesize'): + po.simple['packagesize'] = po.returnSimple('realpackagesize') + del po.simple['realpackagesize'] + del po.simple['realrelativepath'] + del po.simple['reallocalpath'] + + # Rebuild rpms from downloaded deltarpms + for po in rebuild_pkgs: + deltalocal = po.returnSimple('deltalocalpath') + drpm = deltarpm.DeltaRpmWrapper(conduit) + try: + conduit.info(2, "Building %s from %s" % (os.path.basename(po.localpath), os.path.basename(deltalocal))) + drpm.apply(po.localpath, deltalocal) + except: + conduit.info(2, "Error rebuilding rpm from %s! Will download full package." % os.path.basename(deltalocal)) + try: + os.unlink(po.localpath) + except: + pass + else: + # Set package type to local, so yum doesn't try to download it later + # po.pkgtype = "local" # If we set this, we can't auto-install public keys + # and yum is smart enough to detect the full rpm and + # not redownload it. + + # Check to see whether or not we should keep the drpms + # FIXME: Is there any way to see whether or not a Boolean option was not set? + if conduit.confBool('main', 'neverkeepdeltas'): + delete = True + elif conduit.confBool('main', 'keepdeltas'): + delete = False + elif conduit.getConf().keepcache != 0: + delete = False + else: + delete = True + + if delete: + try: + os.unlink(deltalocal) + except: + pass + + return errors + + |