summaryrefslogtreecommitdiffstats
path: root/yum-presto-legacy/shared/prestoDownload.py
diff options
context:
space:
mode:
Diffstat (limited to 'yum-presto-legacy/shared/prestoDownload.py')
-rw-r--r--yum-presto-legacy/shared/prestoDownload.py188
1 files changed, 188 insertions, 0 deletions
diff --git a/yum-presto-legacy/shared/prestoDownload.py b/yum-presto-legacy/shared/prestoDownload.py
new file mode 100644
index 0000000..1c29608
--- /dev/null
+++ b/yum-presto-legacy/shared/prestoDownload.py
@@ -0,0 +1,188 @@
+# 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
+import prestoThread
+import Queue
+import thread
+
+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.deltachecksumtype, po.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 reconstruct(conduit, po, log):
+ deltalocal = po.deltalocalpath
+ retlist = ""
+
+ drpm = deltarpm.DeltaRpmWrapper(conduit)
+
+ try:
+ drpm.apply(po.arch, po.localpath, deltalocal)
+ except:
+ retlist += "Error rebuilding rpm from %s! Will download full package.\n" % os.path.basename(deltalocal)
+ try:
+ os.unlink(po.localpath)
+ except:
+ pass
+ else:
+ # log success
+ log.log(po.oldpkg_string, po.newpkg_string, os.stat(po.localpath)[6], os.stat(deltalocal)[6])
+
+ #retlist += "Built %s from deltarpm\n" % os.path.basename(po.localpath)
+ # 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 retlist
+
+
+
+def downloadPkgs(conduit, pkglist, log):
+ """download list of package objects handed to you, return errors"""
+
+ opts, commands = conduit.getCmdLine()
+
+ errors = {}
+ def adderror(po, msg):
+ errors.setdefault(po, []).append(msg)
+
+ # Set up thread for applying drpms
+ queue = Queue.Queue(0)
+ lock = thread.allocate_lock()
+ curthread = prestoThread.ReconstructionThread(queue, lock, reconstruct)
+ curthread.start()
+
+ # Check whether drpm is already downloaded
+ repo_cached = False
+ remote_pkgs = []
+ for po in conduit.getDownloadPackages():
+ if hasattr(po, 'has_drpm') and po.has_drpm:
+ local = po.deltalocalpath
+ if os.path.exists(local):
+ cursize = os.stat(local)[6]
+ totsize = long(po.deltasize)
+ try:
+ verifyChecksum(local, po.deltachecksumtype, po.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 thread.
+ conduit.info(5, "using local copy of deltarpm for %s" % po)
+ queue.put((conduit, po, log))
+ continue
+ remote_pkgs.append(po)
+
+ # Download deltarpms and send them to another thread to be rebuilt
+ 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
+ try:
+ text = '(%s/%s): %s' % (i, len(remote_pkgs), os.path.basename(po.deltarelativepath))
+ deltalocal = po.repo.p_repo.getPackage(po, checkfunc=checkfunc, text=text, cache=cache)
+ except Errors.RepoError, e:
+ adderror(po, str(e))
+ else:
+ queue.put((conduit, po, log))
+
+ if errors.has_key(po):
+ del errors[po]
+
+ if hasattr(po, 'realpackagesize'):
+ po.packagesize = po.realpackagesize
+ del po.realpackagesize
+
+ # Check for waiting messages from building thread
+ lock.acquire()
+ if curthread.messages != "":
+ conduit.info(2, curthread.messages[:-1])
+ curthread.messages = ""
+ lock.release()
+
+ conduit.info(2, "Rebuilding rpms from deltarpms")
+
+ # Tell build thread that there are no more drpms and wait for it to exit
+ curthread.can_exit = True
+ queue.put(None)
+ curthread.join()
+
+ if curthread.messages != "":
+ conduit.info(2, curthread.messages[:-1])
+ curthread.messages = ""
+
+ return errors
+