[Yum-devel] [PATCH] Move protect-packages plugin into core, and fix some bugs in it. Added some docs.
James Antill
james at and.org
Mon Apr 26 21:48:02 UTC 2010
Add parse_default to Option, ListOption, UrlListOption ... so we can
use the .parse() behaviour.
We also have "two" configurations still, yb.conf.protected_packages and
yb.protect_packages ... this is so we don't have to tweak mock. We can
drop the later, or default to True ... or leave it as is.
---
cli.py | 1 +
docs/yum.8 | 3 +++
docs/yum.conf.5 | 8 ++++++++
etc/Makefile | 1 +
yum.spec | 1 +
yum/__init__.py | 41 +++++++++++++++++++++++++++++++++++++++++
yum/config.py | 16 +++++++++++-----
7 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/cli.py b/cli.py
index 4479a5e..64e60e1 100644
--- a/cli.py
+++ b/cli.py
@@ -69,6 +69,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
signal.signal(signal.SIGQUIT, sigquit)
yum.YumBase.__init__(self)
output.YumOutput.__init__(self)
+ self.protect_packages = True
logging.basicConfig()
self.logger = logging.getLogger("yum.cli")
self.verbose_logger = logging.getLogger("yum.verbose.cli")
diff --git a/docs/yum.8 b/docs/yum.8
index 14622b5..f9eb7fd 100644
--- a/docs/yum.8
+++ b/docs/yum.8
@@ -138,6 +138,9 @@ Are used to remove the specified packages from the system
as well as removing any packages which depend on the package being
removed\&. remove operates on groups, files, provides and filelists just like
the "install" command\&.(See \fBSpecifying package names\fP for more information)
+
+Note that "yum" is included in the protected_packages configuration, by default.
+So you can't accidentally remove yum itself.
.IP
.IP "\fBlist\fP"
Is used to list various information about available
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
index 8200d43..5f1a5c7 100644
--- a/docs/yum.conf.5
+++ b/docs/yum.conf.5
@@ -62,6 +62,14 @@ Debug scriptlet output level. 'info' is the default, other
options are: 'critical', 'emergency', 'error', 'warn' and 'debug'.
.IP
+\fBprotected_packages\fR
+This is a list of packages that yum should never completely remove. They are
+protected via. Obsoletes as well as user/plugin removals.
+
+The default is: yum glob:/etc/yum/protected.d/*.conf
+So any packages which should be protected can do so by including a file in
+/etc/yum/protected.d with their package name in it.
+.IP
\fBlogfile\fR
Full directory and file name for where yum should write its log file.
diff --git a/etc/Makefile b/etc/Makefile
index 91b1791..a512cdf 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -8,6 +8,7 @@ clean:
install:
mkdir -p $(DESTDIR)/etc/yum/
+ mkdir -p $(DESTDIR)/etc/yum/protected.d
mkdir -p $(DESTDIR)/etc/yum/repos.d
mkdir -p $(DESTDIR)/etc/yum/vars
diff --git a/yum.spec b/yum.spec
index a559eda..909354e 100644
--- a/yum.spec
+++ b/yum.spec
@@ -87,6 +87,7 @@ exit 0
%config(noreplace) %{_sysconfdir}/yum/yum.conf
%config(noreplace) %{_sysconfdir}/yum/version-groups.conf
%dir %{_sysconfdir}/yum
+%dir %{_sysconfdir}/yum/protected.d
%dir %{_sysconfdir}/yum/repos.d
%dir %{_sysconfdir}/yum/vars
%config %{_sysconfdir}/logrotate.d/%{name}
diff --git a/yum/__init__.py b/yum/__init__.py
index dbe08ee..0488574 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -165,6 +165,8 @@ class YumBase(depsolve.Depsolve):
self.run_with_package_names = set()
+ self.protect_packages = False # Old default, needed for mock etc.
+
def __del__(self):
self.close()
self.closeRpmDB()
@@ -888,6 +890,45 @@ class YumBase(depsolve.Depsolve):
if self.tsInfo.pkgSack is not None: # rm Transactions don't have pkgSack
self.tsInfo.pkgSack.dropCachedData()
+
+ # This is a version of the old "protect-packages" plugin, it allows
+ # you to erase duplicates and do remove+install.
+ # But we don't allow you to turn it off!:)
+ protect_states = [TS_OBSOLETED, TS_ERASE]
+ txmbrs = []
+ if rescode == 2 and self.protect_packages:
+ protected = set(self.conf.protected_packages)
+ txmbrs = self.tsInfo.getMembersWithState(None, protect_states)
+ bad_togo = {}
+ for txmbr in txmbrs:
+ if txmbr.name not in protected:
+ continue
+ if txmbr.name not in bad_togo:
+ bad_togo[txmbr.name] = []
+ bad_togo[txmbr.name].append(txmbr.pkgtup)
+ for ipkg in self.rpmdb.searchNames(bad_togo.keys()):
+ if ipkg.name not in bad_togo:
+ continue
+ # If there is at least one version not being removed, allow it
+ if ipkg.pkgtup not in bad_togo[ipkg.name]:
+ del bad_togo[ipkg.name]
+ for pkgname in bad_togo.keys():
+ for txmbr in self.tsInfo.matchNaevr(name=pkgname):
+ if txmbr.name not in bad_togo:
+ continue
+ if txmbr.pkgtup in bad_togo[ipkg.name]:
+ continue
+ # If we are installing one version we aren't removing, allow it
+ if txmbr.output_state in TS_INSTALL_STATES:
+ del bad_togo[ipkg.name]
+
+ if bad_togo:
+ rescode = 1
+ restring = []
+ for pkgname in sorted(bad_togo):
+ restring.append(_('Trying to remove "%s", which is protected') %
+ pkgname)
+
self.rpmdb.dropCachedData()
self.verbose_logger.debug('Depsolve time: %0.3f' % (time.time() - ds_st))
diff --git a/yum/config.py b/yum/config.py
index 37d4d10..1b78fcd 100644
--- a/yum/config.py
+++ b/yum/config.py
@@ -55,9 +55,11 @@ class Option(object):
definition easy and consise.
'''
- def __init__(self, default=None):
+ def __init__(self, default=None, parse_default=False):
self._setattrname()
self.inherit = False
+ if parse_default:
+ default = self.parse(default)
self.default = default
def _setattrname(self):
@@ -155,10 +157,10 @@ class ListOption(Option):
An option containing a list of strings.
"""
- def __init__(self, default=None):
+ def __init__(self, default=None, parse_default=False):
if default is None:
default = []
- super(ListOption, self).__init__(default)
+ super(ListOption, self).__init__(default, parse_default)
def parse(self, s):
"""Converts a string from the config file to a workable list, parses
@@ -226,8 +228,9 @@ class UrlListOption(ListOption):
Option for handling lists of URLs with validation of the URL scheme.
'''
- def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https')):
- super(UrlListOption, self).__init__(default)
+ def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https'),
+ parse_default=False):
+ super(UrlListOption, self).__init__(default, parse_default)
# Hold a UrlOption instance to assist with parsing
self._urloption = UrlOption(schemes=schemes)
@@ -730,6 +733,9 @@ class YumConf(StartupConf):
rpmverbosity = Option('info')
+ protected_packages = ListOption("yum, glob:/etc/yum/protected.d/*.conf",
+ parse_default=True)
+
_reposlist = []
def dump(self):
--
1.7.0.1
More information about the Yum-devel
mailing list