I found the original code to be nearly incomprehensible. Instead of
populating a dict of potential binpkgs to remove and then removing from
the to-be-removed list, just selectively add to-be-removed packages.

Signed-off-by: Matt Turner <matts...@gentoo.org>
---
I switched from tabs to spaces in the process. I can revert back if
desired.

 pym/gentoolkit/eclean/search.py | 189 ++++++++++++++++----------------
 1 file changed, 94 insertions(+), 95 deletions(-)

diff --git a/pym/gentoolkit/eclean/search.py b/pym/gentoolkit/eclean/search.py
index 58bd97e..831ba39 100644
--- a/pym/gentoolkit/eclean/search.py
+++ b/pym/gentoolkit/eclean/search.py
@@ -489,98 +489,97 @@ class DistfilesSearch(object):
 
 
 def findPackages(
-               options,
-               exclude=None,
-               destructive=False,
-               time_limit=0,
-               package_names=False,
-               pkgdir=None,
-               port_dbapi=portage.db[portage.root]["porttree"].dbapi,
-               var_dbapi=portage.db[portage.root]["vartree"].dbapi
-       ):
-       """Find all obsolete binary packages.
-
-       XXX: packages are found only by symlinks.
-       Maybe i should also return .tbz2 files from All/ that have
-       no corresponding symlinks.
-
-       @param options: dict of options determined at runtime
-       @param exclude: an exclusion dict as defined in
-                       exclude.parseExcludeFile class.
-       @param destructive: boolean, defaults to False
-       @param time_limit: integer time value as returned by parseTime()
-       @param package_names: boolean, defaults to False.
-                       used only if destructive=True
-       @param pkgdir: path to the binary package dir being checked
-       @param port_dbapi: defaults to 
portage.db[portage.root]["porttree"].dbapi
-                                       can be overridden for tests.
-       @param var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
-                                       can be overridden for tests.
-
-       @rtype: dict
-       @return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],}
-       """
-       if exclude is None:
-               exclude = {}
-       clean_me = {}
-       # create a full package dictionary
-
-       # now do an access test, os.walk does not error for "no read permission"
-       try:
-               test = os.listdir(pkgdir)
-               del test
-       except EnvironmentError as er:
-               if options['ignore-failure']:
-                       exit(0)
-               print( pp.error("Error accessing PKGDIR." ), file=sys.stderr)
-               print( pp.error("(Check your make.conf file and 
environment)."), file=sys.stderr)
-               print( pp.error("Error: %s" %str(er)), file=sys.stderr)
-               exit(1)
-
-       # if portage supports FEATURES=binpkg-multi-instance, then
-       # cpv_all can return multiple instances per cpv, where
-       # instances are distinguishable by some extra attributes
-       # provided by portage's _pkg_str class
-       bin_dbapi = portage.binarytree(pkgdir=pkgdir, 
settings=var_dbapi.settings).dbapi
-       for cpv in bin_dbapi.cpv_all():
-               mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_'])[0])
-               if time_limit and mtime >= time_limit:
-                       # time-limit exclusion
-                       continue
-               # dict is cpv->[pkgs] (supports binpkg-multi-instance)
-               clean_me.setdefault(cpv, []).append(cpv)
-
-       # keep only obsolete ones
-       if destructive and package_names:
-               cp_all = dict.fromkeys(var_dbapi.cp_all())
-       else:
-               cp_all = {}
-       for cpv in list(clean_me):
-               if exclDictMatchCP(exclude,portage.cpv_getkey(cpv)):
-                       # exclusion because of the exclude file
-                       del clean_me[cpv]
-                       continue
-               if not destructive and port_dbapi.cpv_exists(cpv):
-                       # exclusion because pkg still exists (in porttree)
-                       del clean_me[cpv]
-                       continue
-               if destructive and var_dbapi.cpv_exists(cpv):
-                       buildtime = var_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]
-                       clean_me[cpv] = [pkg for pkg in clean_me[cpv]
-                               # only keep path if BUILD_TIME is identical 
with vartree
-                               if bin_dbapi.aux_get(pkg, ['BUILD_TIME'])[0] != 
buildtime]
-                       if not clean_me[cpv]:
-                               # nothing we can clean for this package
-                               del clean_me[cpv]
-                               continue
-               if portage.cpv_getkey(cpv) in cp_all and 
port_dbapi.cpv_exists(cpv):
-                       # exclusion because of --package-names
-                       del clean_me[cpv]
-
-       # the getname method correctly supports FEATURES=binpkg-multi-instance,
-       # allowing for multiple paths per cpv (the API used here is also 
compatible
-       # with older portage which does not support binpkg-multi-instance)
-       for cpv, pkgs in clean_me.items():
-               clean_me[cpv] = [bin_dbapi.bintree.getname(pkg) for pkg in pkgs]
-
-       return clean_me
+        options,
+        exclude=None,
+        destructive=False,
+        time_limit=0,
+        package_names=False,
+        pkgdir=None,
+        port_dbapi=portage.db[portage.root]["porttree"].dbapi,
+        var_dbapi=portage.db[portage.root]["vartree"].dbapi
+    ):
+    """Find obsolete binary packages.
+
+    @param options: dict of options determined at runtime
+    @type  options: dict
+    @param exclude: exclusion dict (as defined in the exclude.parseExcludeFile 
class)
+    @type  exclude: dict, optional
+    @param destructive: binpkg is obsolete if not installed (default: `False`)
+    @type  destructive: bool, optional
+    @param time_limit: binpkg is obsolete if older than time value as returned 
by parseTime()
+    @type  time_limit: int, optional
+    @param package_names: exclude all binpkg versions if package is installed
+                          (used with `destructive=True`) (default: `False`)
+    @type  package_names: bool, optional
+    @param pkgdir: path to the binpkg cache (PKGDIR)
+    @type  pkgdir: str
+    @param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
+                       Can be overridden for tests.
+    @param  var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
+                       Can be overridden for tests.
+
+    @return binary packages to remove. e.g. {'cat/pkg-ver': [filepath]}
+    @rtype: dict
+    """
+    if exclude is None:
+        exclude = {}
+
+    # Access test, os.walk does not error for "no read permission"
+    try:
+        test = os.listdir(pkgdir)
+        del test
+    except EnvironmentError as er:
+        if options['ignore-failure']:
+            exit(0)
+        print(pp.error("Error accessing PKGDIR."), file=sys.stderr)
+        print(pp.error("(Check your make.conf file and environment)."), 
file=sys.stderr)
+        print(pp.error("Error: %s" % str(er)), file=sys.stderr)
+        exit(1)
+
+    # Create a dictionary of all installed packages
+    if destructive and package_names:
+        installed = dict.fromkeys(var_dbapi.cp_all())
+    else:
+        installed = {}
+
+    # Dictionary of binary packages to clean. Organized as cpv->[pkgs] in order
+    # to support FEATURES=binpkg-multi-instance.
+    dead_binpkgs = {}
+
+    # Create a dictionary of all binary packages whose mtime is older than
+    # time_limit, if set. These packages will be considered for removal.
+    bin_dbapi = portage.binarytree(pkgdir=pkgdir, 
settings=var_dbapi.settings).dbapi
+    for cpv in bin_dbapi.cpv_all():
+        cp = portage.cpv_getkey(cpv)
+
+        # Exclude per --exclude-file=...
+        if exclDictMatchCP(exclude, cp):
+            continue
+
+        # Exclude if binpkg is obsolete per --time-limit=...
+        if time_limit:
+            mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_']))
+            if mtime >= time_limit:
+                continue
+
+        # Exclude if binpkg exists in the porttree and not --deep
+        if not destructive and port_dbapi.cpv_exists(cpv):
+            continue
+
+        if destructive and var_dbapi.cpv_exists(cpv):
+            # Exclude if an instance of the package is installed due to
+            # the --package-names option.
+            if cp in installed and port_dbapi.cpv_exists(cpv):
+                continue
+
+            # Exclude if BUILD_TIME of binpkg is same as vartree
+            buildtime = var_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]
+            if buildtime == bin_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]:
+                continue
+
+        binpkg_path = bin_dbapi.bintree.getname(cpv)
+        dead_binpkgs.setdefault(cpv, []).append(binpkg_path)
+
+    return dead_binpkgs
+
+# vim: set ts=4 sw=4 tw=79:
-- 
2.24.1


Reply via email to