#!/usr/bin/python2.7 -tt
# 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 2007 Red Hat, Inc
# Written by Seth Vidal
# upgrade-helper plugin
# cleans out orphans and impossible-to-update/obsolete-away pkgs
# download list of stuff to kill from each repo, if there
# parse it and load it into memory
# - make sure that any pkgspec matching: a lot of things *? or * or . or what not
# will be ignored
#format of the file is:
#<cleanup>
# <removespec pkgmatch="zsh.i386" on_arch="x86_64"/>
# <removespec pkgmatch="zvbi"/>
#</cleanup>
# for all the ones for anything in your arch
# if something is installed matching it, then add it to the TS to be removed
# do all this only if:
# running as root
# the command being run is 'update' or 'install' (or performing those functions somehow)
from yum.plugins import TYPE_CORE
from yum.constants import *
import rpmUtils.arch
from yum.repoMDObject import ns_cleanup
import gzip
try:
from xml.etree import cElementTree
except ImportError:
import cElementTree
iterparse = cElementTree.iterparse
requires_api_version = '2.5'
plugin_type = (TYPE_CORE,)
myarch = rpmUtils.arch.getBaseArch()
def parse_xml(xmlfile):
"""parse the xml file and hand back the contents in a usable form"""
# store results in a dict of on_arch = list_of_pkgs
results = {}
results[myarch] = []
xfo = gzip.open(xmlfile, 'rt')
parser = iterparse(xfo)
for ev, elem in parser:
for child in elem:
child_name = ns_cleanup(child.tag)
thisarch = myarch
if child_name == 'removespec':
if 'on_arch' in child.attrib:
thisarch = child.attrib.get('on_arch')
if 'pkgmatch' in child.attrib:
thismatch = child.attrib.get('pkgmatch')
if thisarch in results:
if thismatch not in results[thisarch]:
results[thisarch].append(thismatch)
else:
results[thisarch] = [thismatch]
return results
def stuff_to_remove(repos):
toremove = []
# for repo in my repos
# grab the cleanup file
# parse it
# merge all the results for $myarch together
# return them as the toremove list
for repo in repos.listEnabled():
if 'cleanup' in repo.repoXML.repoData:
trf = repo.retrieveMD('cleanup')
tr_dict = parse_xml(trf)
# prune out things like *, ?, *.*, *.*.*.*.*
# etc
badmatches = ['*', '?', '*.*', 'glibc', 'kernel', 'yum', 'rpm']
for pm in tr_dict[myarch]:
if pm in badmatches:
continue
# other tests here?
toremove.append(pm)
return toremove
def preresolve_hook(conduit):
"""add all of these into the ts to be removed"""
ts = conduit.getTsInfo()
# only run it if we're installing/updating something, don't do it if
# we're removing only
runme = False
for mbr in ts.getMembers():
if mbr.output_state in TS_INSTALL_STATES:
runme = True
break
if runme:
rpmdb = conduit.getRpmDB()
# we should probably consider also allowing version-range packagespecs
# like foo < 1.1.1-1 by using rpmdb.getProvides() with some other magic
# FIXME FOR LATER
for pkgglob in stuff_to_remove(conduit.getRepos()):
ex, m, u = rpmdb.matchPackageNames([pkgglob])
for po in ex + m:
conduit.info(1, "Setting %s to be removed due to repository metadata in cleanup plugin" % po)
ts.addErase(po)
@KyuuKazami