Blame SOURCES/BZ-1455318-package-cleanup-dont-remove-required.patch

5b4f08
commit f84a2dbcc28312105246fac51771481640759da5
5b4f08
Author: Phil Dibowitz <phil@ipom.com>
5b4f08
Date:   Thu Jul 2 11:40:55 2015 -0700
5b4f08
5b4f08
    Add option to remove newest dupes instead of oldest dupes
5b4f08
    
5b4f08
    Sometimes in a failed transaction you need to remove the newest of the dupes and
5b4f08
    not the oldest. This provides that option.
5b4f08
5b4f08
diff --git a/package-cleanup.py b/package-cleanup.py
5b4f08
index acad9f2..13cfb89 100755
5b4f08
--- a/package-cleanup.py
5b4f08
+++ b/package-cleanup.py
5b4f08
@@ -79,6 +79,9 @@ class PackageCleanup(YumUtilBase):
5b4f08
         dupegrp.add_option("--cleandupes", default=False, 
5b4f08
                     dest="cleandupes", action="store_true",
5b4f08
                     help='Scan for duplicates in your rpmdb and remove older ')
5b4f08
+        dupegrp.add_option("--removenewestdupes", default=False, 
5b4f08
+                    dest="removenewestdupes", action="store_true",
5b4f08
+                    help='Remove the newest dupes instead of the oldest dupes.')
5b4f08
         dupegrp.add_option("--noscripts", default=False,
5b4f08
                     dest="noscripts", action="store_true",
5b4f08
                     help="disable rpm scriptlets from running when cleaning duplicates")
5b4f08
@@ -172,7 +175,7 @@ class PackageCleanup(YumUtilBase):
5b4f08
             
5b4f08
         return results
5b4f08
 
5b4f08
-    def _remove_old_dupes(self):
5b4f08
+    def _remove_dupes(self, newest=False):
5b4f08
         """add older duplicate pkgs to be removed in the transaction"""
5b4f08
         dupedict = self._find_installed_duplicates()
5b4f08
 
5b4f08
@@ -180,7 +183,11 @@ class PackageCleanup(YumUtilBase):
5b4f08
         for (name,dupelists) in dupedict.items():
5b4f08
             for dupelist in dupelists:
5b4f08
                 dupelist.sort()
5b4f08
-                for lowpo in dupelist[0:-1]:
5b4f08
+                if newest:
5b4f08
+                    plist = dupelist[1:]
5b4f08
+                else:
5b4f08
+                    plist = dupelist[0:-1]
5b4f08
+                for lowpo in plist:
5b4f08
                     removedupes.append(lowpo)
5b4f08
 
5b4f08
         for po in removedupes:
5b4f08
@@ -373,7 +380,7 @@ class PackageCleanup(YumUtilBase):
5b4f08
                 sys.exit(1)
5b4f08
             if opts.noscripts:
5b4f08
                 self.conf.tsflags.append('noscripts')
5b4f08
-            self._remove_old_dupes()
5b4f08
+            self._remove_dupes(opts.removenewestdupes)
5b4f08
             self.run_with_package_names.add('yum-utils')
5b4f08
 
5b4f08
             if hasattr(self, 'doUtilBuildTransaction'):
5b4f08
commit 27784822a342debd3ecfa04686a35f2e7e576023
5b4f08
Author: Michal Domonkos <mdomonko@redhat.com>
5b4f08
Date:   Wed Oct 11 19:26:38 2017 +0200
5b4f08
5b4f08
    package-cleanup: don't remove required dupes. BZ 1455318
5b4f08
    
5b4f08
    Note: Turning removedupes into a set for O(1) complexity on
5b4f08
    removedupes.remove().
5b4f08
5b4f08
diff --git a/package-cleanup.py b/package-cleanup.py
5b4f08
index 13cfb89..9f74609 100755
5b4f08
--- a/package-cleanup.py
5b4f08
+++ b/package-cleanup.py
5b4f08
@@ -176,10 +176,12 @@ class PackageCleanup(YumUtilBase):
5b4f08
         return results
5b4f08
 
5b4f08
     def _remove_dupes(self, newest=False):
5b4f08
-        """add older duplicate pkgs to be removed in the transaction"""
5b4f08
-        dupedict = self._find_installed_duplicates()
5b4f08
+        """add duplicate pkgs to be removed in the transaction,
5b4f08
+           return a dict of excluded dupes and their requiring packages"""
5b4f08
 
5b4f08
-        removedupes = []
5b4f08
+        # Find dupes
5b4f08
+        dupedict = self._find_installed_duplicates()
5b4f08
+        removedupes = set()
5b4f08
         for (name,dupelists) in dupedict.items():
5b4f08
             for dupelist in dupelists:
5b4f08
                 dupelist.sort()
5b4f08
@@ -188,11 +190,37 @@ class PackageCleanup(YumUtilBase):
5b4f08
                 else:
5b4f08
                     plist = dupelist[0:-1]
5b4f08
                 for lowpo in plist:
5b4f08
-                    removedupes.append(lowpo)
5b4f08
-
5b4f08
+                    removedupes.add(lowpo)
5b4f08
+
5b4f08
+        # Exclude any such dupes that would pull other installed packages into
5b4f08
+        # the removal transaction (to prevent us from accidentally removing a
5b4f08
+        # huge part of a working system) by performing a dry transaction(s)
5b4f08
+        # first.
5b4f08
+        excluded = {}
5b4f08
+        while True:
5b4f08
+            for po in removedupes:
5b4f08
+                self.remove(po)
5b4f08
+            changed = False
5b4f08
+            for txmbr in self.tsInfo.getMembers():
5b4f08
+                requiredby = self._checkRemove(txmbr)
5b4f08
+                if requiredby:
5b4f08
+                    removedupes.remove(txmbr.po)
5b4f08
+                    excluded[txmbr.po] = requiredby
5b4f08
+                    # Do another round, to cover any transitive deps within
5b4f08
+                    # removedupes, for example: if foo requires bar requires
5b4f08
+                    # baz and removedupes contains bar and baz, then
5b4f08
+                    # _checkRemove(baz) won't return bar.
5b4f08
+                    changed = True
5b4f08
+            del self.tsInfo
5b4f08
+            if not changed:
5b4f08
+                break
5b4f08
+
5b4f08
+        # Mark the dupes for removal
5b4f08
         for po in removedupes:
5b4f08
             self.remove(po)
5b4f08
 
5b4f08
+        return excluded
5b4f08
+
5b4f08
 
5b4f08
     def _should_show_leaf(self, po, leaf_regex, exclude_devel, exclude_bin):
5b4f08
         """
5b4f08
@@ -380,7 +408,13 @@ class PackageCleanup(YumUtilBase):
5b4f08
                 sys.exit(1)
5b4f08
             if opts.noscripts:
5b4f08
                 self.conf.tsflags.append('noscripts')
5b4f08
-            self._remove_dupes(opts.removenewestdupes)
5b4f08
+            excluded = self._remove_dupes(opts.removenewestdupes)
5b4f08
+            for po, requiredby in excluded.iteritems():
5b4f08
+                count = len(requiredby)
5b4f08
+                print ('Not removing %s because it is required by %s '
5b4f08
+                       'installed package%s' %
5b4f08
+                       (po.hdr.sprintf(opts.qf), count,
5b4f08
+                        's' if count > 1 else ''))
5b4f08
             self.run_with_package_names.add('yum-utils')
5b4f08
 
5b4f08
             if hasattr(self, 'doUtilBuildTransaction'):
5b4f08
@@ -397,9 +431,20 @@ class PackageCleanup(YumUtilBase):
5b4f08
 
5b4f08
             if len(self.tsInfo) < 1:
5b4f08
                 print 'No duplicates to remove'
5b4f08
-                sys.exit(0)
5b4f08
-                
5b4f08
-            sys.exit(self.doUtilTransaction())
5b4f08
+                errc = 0
5b4f08
+            else:
5b4f08
+                errc = self.doUtilTransaction()
5b4f08
+
5b4f08
+            if excluded:
5b4f08
+                self.logger.warn(
5b4f08
+                    'Warning: Some duplicates were not removed because they '
5b4f08
+                    'are required by installed packages.\n'
5b4f08
+                    'You can try --cleandupes with%s --removenewestdupes, '
5b4f08
+                    'or review them with --dupes and remove manually.' %
5b4f08
+                    ('out' if opts.removenewestdupes else '')
5b4f08
+                )
5b4f08
+
5b4f08
+            sys.exit(errc)
5b4f08
 
5b4f08
     
5b4f08
 if __name__ == '__main__':
5b4f08
commit 4594bbc623b68bea6522047fb6267069c8ad94c8
5b4f08
Author: Michal Domonkos <mdomonko@redhat.com>
5b4f08
Date:   Wed Oct 11 20:23:06 2017 +0200
5b4f08
5b4f08
    package-cleanup: update man page
5b4f08
    
5b4f08
    Add missing options from --help and also clear up the wording of
5b4f08
    --removenewestdupes.
5b4f08
5b4f08
diff --git a/docs/package-cleanup.1 b/docs/package-cleanup.1
5b4f08
index 61959ac..5b7e1c0 100644
5b4f08
--- a/docs/package-cleanup.1
5b4f08
+++ b/docs/package-cleanup.1
5b4f08
@@ -36,6 +36,10 @@ Scan for duplicates in the local RPM database.
5b4f08
 .IP "\fB\-\-cleandupes\fP"
5b4f08
 Scan for duplicates in the local RPM database and clean out the
5b4f08
 older versions.
5b4f08
+.IP "\fB\-\-removenewestdupes\fP"
5b4f08
+Remove the newest dupes instead of the oldest dupes when cleaning duplicates.
5b4f08
+.IP "\fB\-\-noscripts\fP"
5b4f08
+Disable rpm scriptlets from running when cleaning duplicates.
5b4f08
 .IP "\fB\-\-count <COUNT>\fP"
5b4f08
 Number of duplicate/kernel packages to keep on the system (default 2)
5b4f08
 .PP 
5b4f08
diff --git a/package-cleanup.py b/package-cleanup.py
5b4f08
index 9f74609..4a44326 100755
5b4f08
--- a/package-cleanup.py
5b4f08
+++ b/package-cleanup.py
5b4f08
@@ -81,7 +81,7 @@ class PackageCleanup(YumUtilBase):
5b4f08
                     help='Scan for duplicates in your rpmdb and remove older ')
5b4f08
         dupegrp.add_option("--removenewestdupes", default=False, 
5b4f08
                     dest="removenewestdupes", action="store_true",
5b4f08
-                    help='Remove the newest dupes instead of the oldest dupes.')
5b4f08
+                    help='Remove the newest dupes instead of the oldest dupes when cleaning duplicates.')
5b4f08
         dupegrp.add_option("--noscripts", default=False,
5b4f08
                     dest="noscripts", action="store_true",
5b4f08
                     help="disable rpm scriptlets from running when cleaning duplicates")