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>
---
 pym/gentoolkit/eclean/search.py | 113 ++++++++++++++++----------------
 1 file changed, 55 insertions(+), 58 deletions(-)

diff --git a/pym/gentoolkit/eclean/search.py b/pym/gentoolkit/eclean/search.py
index 58bd97e..0efefdb 100644
--- a/pym/gentoolkit/eclean/search.py
+++ b/pym/gentoolkit/eclean/search.py
@@ -498,89 +498,86 @@ def findPackages(
                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.
+       """Find obsolete binary packages.
 
        @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
+       @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: exclude binpkg if newer 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.
+                                          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
-       @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"
+       # 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)
+               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
+       # 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 = {}
+
        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)
+               cp = portage.cpv_getkey(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]
+               # Exclude per --exclude-file=...
+               if exclDictMatchCP(exclude, cp):
                        continue
+
+               # Exclude if binpkg is newer than --time-limit=...
+               if time_limit:
+                       mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_'])[0])
+                       if mtime >= time_limit:
+                               continue
+
+               # Exclude if binpkg exists in the porttree and not --deep
                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):
+                       # 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]
-                       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]
+                       if buildtime == bin_dbapi.aux_get(cpv, 
['BUILD_TIME'])[0]:
                                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]
+               binpkg_path = bin_dbapi.bintree.getname(cpv)
+               dead_binpkgs.setdefault(cpv, []).append(binpkg_path)
+
+       return dead_binpkgs
 
-       return clean_me
+# vim: set ts=4 sw=4 tw=79:
-- 
2.24.1


Reply via email to