[Yum-devel] [PATCH] Move protect-packages plugin into core, and fix some bugs in it. Added some docs. for yum.conf => protected_packages, and yum on the remove command.

James Antill james at and.org
Tue Apr 27 20:17:56 UTC 2010


 Add parse_default to Option, ListOption, UrlListOption ... so we can
use the .parse() behaviour.

 Default: yum, glob:/etc/yum/protected.d/*.conf
 Created dir. and owned it.
---
 docs/yum.8      |    3 +++
 docs/yum.conf.5 |    8 ++++++++
 etc/Makefile    |    1 +
 yum.spec        |    1 +
 yum/__init__.py |   39 +++++++++++++++++++++++++++++++++++++++
 yum/config.py   |   16 +++++++++++-----
 6 files changed, 63 insertions(+), 5 deletions(-)

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..a41079a 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -888,6 +888,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.conf.protected_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