fuel-main/mirror/centos/yum-priorities-plugin.py

227 lines
7.7 KiB
Python

#!/usr/bin/python
#
# yum-plugin-priorities 0.0.7
#
# Copyright (c) 2006-2007 Daniel de Kok
#
# 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 General Public License for more details.
#
# This plugins is inspired by the protectbase plugin, and enables/disables
# packages based on a repository priority.
#
# You can install this plugin by copying it to /usr/lib/yum-plugins. To
# enable this plugin, make sure that you have 'plugins=1' in /etc/yum.conf,
# and create the file /etc/yum/pluginconf.d/priorities.conf with the
# following content:
#
# [main]
# enabled=1
#
# If you also want the plugin to protect high-priority repositories against
# obsoletes in low-priority repositories, enable the 'check_obsoletes' bool:
#
# check_obsoletes=1
#
# By default, this plugin excludes packages from lower priority repositories
# based on the package name. If you want to exclude packages based only the
# package name and architecture, enable the 'only_samearch' bool:
#
# only_samearch=1
#
# If you want to be able to set package as the fully qualified package name
# including architecture and package version, enable 'full_match' bool:
#
# full_match=1
#
# If full_match is enabled then check_obsoletes will be forced to disable
#
# You can add priorities to repositories, by adding the line:
#
# priority=N
#
# to the repository entry, where N is an integer number. The default
# priority for repositories is 99. The repositories with the lowest
# number have the highest priority.
#
# Please report errors to Daniel de Kok <danieldk@pobox.com>
from yum.constants import *
from yum.plugins import TYPE_CORE
from yum import config
import yum
check_obsoletes = False
only_samearch = False
full_match = False
requires_api_version = '2.1'
plugin_type = (TYPE_CORE,)
def config_hook(conduit):
global check_obsoletes
global only_samearch
global full_match
# Plugin configuration
check_obsoletes = conduit.confBool('main', 'check_obsoletes',
default=False)
only_samearch = conduit.confBool('main', 'only_samearch', default=False)
full_match = conduit.confBool('main', 'full_match', default=False)
if full_match:
check_obsoletes = False
# Repo priorities
if yum.__version__ >= '2.5.0':
# New style : yum >= 2.5
config.RepoConf.priority = config.IntOption(99)
else:
# Old add extra options style
conduit.registerOpt('priority', PLUG_OPT_INT, PLUG_OPT_WHERE_REPO, 99)
# Command-line options.
parser = conduit.getOptParser()
if parser:
if hasattr(parser, 'plugin_option_group'):
parser = parser.plugin_option_group
parser.add_option(
'', '--samearch-priorities', dest='samearch', action='store_true',
default=False,
help="Priority-exclude packages based on name + arch")
def _all_repo_priorities_same(allrepos):
""" Are all repos at the same priority """
first = None
for repo in allrepos:
if first is None:
first = repo.priority
elif first != repo.priority:
return False
return True
def exclude_hook(conduit):
global only_samearch
global check_obsoletes
global full_match
allrepos = conduit.getRepos().listEnabled()
# If they haven't done anything, don't do any work
if _all_repo_priorities_same(allrepos):
return
# Check whether the user specified the --samearch option.
opts, commands = conduit.getCmdLine()
if opts and opts.samearch:
only_samearch = True
cnt = 0
if check_obsoletes and not conduit._base.conf.obsoletes:
check_obsoletes = False
if check_obsoletes:
obsoletes = conduit._base.up.rawobsoletes
# Build a dictionary with package priorities. Either with arch or
# archless, based on the user's settings.
if only_samearch:
pkg_priorities = dict()
if check_obsoletes or not only_samearch:
pkg_priorities_archless = dict()
for repo in allrepos:
if repo.enabled:
if only_samearch:
repopkgs = _pkglist_to_dict(conduit.getPackages(repo),
repo.priority, True)
_mergeprioritydicts(pkg_priorities, repopkgs)
if check_obsoletes or not only_samearch:
repopkgs_archless = _pkglist_to_dict(
conduit.getPackages(repo), repo.priority)
_mergeprioritydicts(pkg_priorities_archless, repopkgs_archless)
# Eliminate packages that have a low priority
for repo in allrepos:
if repo.enabled:
for po in conduit.getPackages(repo):
delPackage = False
if full_match:
pname = str(po)
else:
pname = po.name
if only_samearch:
key = "%s.%s" % (pname, po.arch)
if (key in pkg_priorities and
pkg_priorities[key] < repo.priority):
delPackage = True
else:
key = "%s" % pname
if (key in pkg_priorities_archless and
pkg_priorities_archless[key] < repo.priority):
delPackage = True
if delPackage:
conduit.delPackage(po)
cnt += 1
conduit.info(3, " --> %s from %s excluded "
"(priority)" % (po, po.repoid))
# If this packages obsoletes other packages, check whether
# one of the obsoleted packages is not available through
# a repo with a higher priority. If so, remove this package.
if check_obsoletes:
if po.pkgtup in obsoletes:
obsolete_pkgs = obsoletes[po.pkgtup]
for obsolete_pkg in obsolete_pkgs:
pkg_name = obsolete_pkg[0]
if (pkg_name in pkg_priorities_archless
and pkg_priorities_archless[pkg_name] <
repo.priority):
conduit.delPackage(po)
cnt += 1
conduit.info(
3, " --> %s from %s excluded "
"(priority)" % (po, po.repoid))
break
if cnt:
conduit.info(2, '%d packages excluded due to repository '
'priority protections' % cnt)
if check_obsoletes:
# Atm. the update object doesn't get updated when we manually exclude
# things ... so delete it. This needs to be re-written.
conduit._base.up = None
def _pkglist_to_dict(pl, priority, addArch=False):
global full_match
out = dict()
for p in pl:
if full_match:
pname = str(p)
else:
pname = p.name
if addArch:
key = "%s.%s" % (pname, p.arch)
out[key] = priority
else:
out[pname] = priority
return out
def _mergeprioritydicts(dict1, dict2):
for package in dict2.keys():
if package not in dict1 or dict2[package] < dict1[package]:
dict1[package] = dict2[package]