# author: Jonathan Dieter # # heavily modified from yum-deltarpm.py created by # Lars Herrmann # # 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 from yum.plugins import TYPE_INTERACTIVE, PluginYumExit from yum import config import os import sys sys.path.append("/usr/share/presto") import deltarpm from prestoRepo import PrestoRepository from prestomdparser import PrestoMDParser import prestoTransaction import prestoLog requires_api_version = '2.1' LOG_FILE = "/var/log/presto.log" plugin_type = (TYPE_INTERACTIVE,) rpm_size = 0 drpm_size = 0 was_drpm = False # Configuration stuff def config_hook(conduit): # Set up repository specific deltarpm url and mirrorlist config.RepoConf.deltaurl = config.UrlListOption() config.RepoConf.deltamirrorlist = config.UrlOption() # Add --disable-presto option parser = conduit.getOptParser() parser.add_option('', '--disablepresto', dest='disablepresto', action='store_true', default=False, help="disable Presto plugin and don't download any deltarpms") # Set up Presto repositories def postreposetup_hook(conduit): opts, commands = conduit.getCmdLine() if not opts.disablepresto: conduit.info(2, 'Setting up Presto') for active_repo in conduit.getRepos().listEnabled(): p_repo = PrestoRepository(active_repo, conduit) p_repo.setup(conduit.getConf().cache) conduit.info(2, 'Reading Presto metadata in from local files') for active_repo in conduit.getRepos().listEnabled(): xml = active_repo.p_repo.getPrestoXML() if active_repo.p_repo.enabled: xmldata = active_repo.p_repo.repoXML.getData('deltas') (ctype, csum) = xmldata.checksum parser = PrestoMDParser(xml) active_repo.p_repo.deltalist = parser.getDeltaList() else: conduit.info(5, '--disablepresto specified - Presto disabled') def postresolve_hook(conduit): global rpm_size global drpm_size global was_drpm opts, commands = conduit.getCmdLine() if not opts.disablepresto: # Cycle through packages to see if there's a deltarpm available for newpkg in conduit.getTsInfo(): if newpkg.ts_state != "e": (chosen_drpm, installed, local, drpm_enabled) = prestoTransaction.find_available_drpms(conduit, newpkg) # If a drpm was found, change certain package information so it reflects # the drpm, not the rpm. if chosen_drpm != None: was_drpm = True rpm_size += int(newpkg.po.simple['packagesize']) drpm_size += int(chosen_drpm['size']) newpkg.po.hasdrpm = True newpkg.po.simple['basepath'] = chosen_drpm['baseurl'] newpkg.po.simple['realpackagesize'] = newpkg.po.simple['packagesize'] newpkg.po.simple['packagesize'] = chosen_drpm['size'] newpkg.po.simple['realrelativepath'] = newpkg.po.simple['relativepath'] newpkg.po.simple['relativepath'] = chosen_drpm['drpm_filename'] newpkg.po.reallocalpath = newpkg.po.localpath newpkg.po.localpath = newpkg.po.repo.deltasdir + "/" + os.path.basename(chosen_drpm['drpm_filename']) newpkg.po.to = newpkg newpkg.realpkgtup = newpkg.pkgtup newpkg.pkgtup = (newpkg.name + " *", newpkg.arch, newpkg.epoch, newpkg.version, newpkg.release) for (csum_type, csum, csumid) in newpkg.po._checksums: if csumid: newpkg.po._realchecksum = (csum_type, csum, csumid) newpkg.po._checksums.remove((csum_type, csum, csumid)) csum_type = chosen_drpm['checksum_type'] csum = chosen_drpm['checksum'] newpkg.po._checksums.append((csum_type, csum, csumid)) conduit.info(2, "Found deltarpm update for %s.%s %s:%s.%s" % (newpkg.name, newpkg.arch, newpkg.epoch, newpkg.version, newpkg.release)) else: newpkg.po.hasdrpm = False if installed and drpm_enabled and not local: try: rpm_size += int(newpkg.po.simple['packagesize']) drpm_size += int(newpkg.po.simple['packagesize']) except: pass return # Free up memory used by deleting Presto repositories for active_repo in conduit.getRepos().listEnabled(): if active_repo.p_repo.enabled: del active_repo.p_repo def postdownload_hook(conduit): global was_drpm opts, commands = conduit.getCmdLine() if not opts.disablepresto and was_drpm: failure = False # Cycle through packages to see if we've downloaded a deltarpm conduit.info(2, "Rebuilding full packages from deltas") for pkg in conduit.getDownloadPackages(): if pkg.hasdrpm and pkg.verifyLocalPkg(): # Apply deltarpm and save where rpm would have been saved drpm = deltarpm.DeltaRpmWrapper(conduit) this_failure = False try: drpm.apply(pkg.reallocalpath, pkg.localpath) except: failure = True this_failure = True if not this_failure: drpm_path = pkg.localpath # Change package information to reflect original rpm information pkg.to.pkgtup = pkg.to.realpkgtup pkg.localpath = pkg.reallocalpath pkg.simple['packagesize'] = pkg.simple['realpackagesize'] del pkg.simple['basepath'] for (csum_type, csum, csumid) in pkg._checksums: if csumid: pkg._checksums.remove((csum_type, csum, csumid)) pkg._checksums.append(pkg._realchecksum) # 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: os.unlink(drpm_path) if failure: raise PluginYumExit("Error rebuilding at least one deltarpm. Please run report this error to\nhttps://hosted.fedoraproject.org/projects/presto/newticket. To bypass this problem, run yum \nwith the --disablepresto option") def posttrans_hook(conduit): global rpm_size global drpm_size global LOG_FILE if rpm_size > 0: prestoLog.log(conduit, LOG_FILE, rpm_size, drpm_size) conduit.info(2, "Size of all updates downloaded from Presto-enabled repositories: %i bytes" % drpm_size) conduit.info(2, "Size updates would have been downloaded if Presto wasn't enabled: %i bytes" % rpm_size) conduit.info(2, "This is a savings of %i percent" % (100 - ((drpm_size * 100) / rpm_size)))