Allows binpkgs to be deleted if they are not usable due to IUSE changes. --- Just kind of spitballing. I'm not sure about what USE flags we should ignore or whether it should be configurable, etc. On one hand, deleting binpkgs that don't have a newly added PYTHON_TARGET option might make sense if your binhost is configured to rebuild the package. On the other, you probably don't want to throw out amd64 binpkgs because abi_riscv_* was added.
pym/gentoolkit/eclean/cli.py | 8 ++++- pym/gentoolkit/eclean/search.py | 62 +++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/pym/gentoolkit/eclean/cli.py b/pym/gentoolkit/eclean/cli.py index e31fde9..910296b 100644 --- a/pym/gentoolkit/eclean/cli.py +++ b/pym/gentoolkit/eclean/cli.py @@ -146,6 +146,8 @@ def printUsage(_error=None, help=None): green("packages"),"action:", file=out) print( yellow(" --changed-deps")+ " - delete packages for which ebuild dependencies have changed", file=out) + print( yellow(" --changed-iuse")+ + " - delete packages for which IUSE have changed", file=out) print( yellow(" -i, --ignore-failure")+ " - ignore failure to locate PKGDIR", file=out) print( file=out) @@ -264,6 +266,8 @@ def parseArgs(options={}): options['verbose'] = True elif o in ("--changed-deps"): options['changed-deps'] = True + elif o in ("--changed-iuse"): + options['changed-iuse'] = True elif o in ("-i", "--ignore-failure"): options['ignore-failure'] = True else: @@ -291,7 +295,8 @@ def parseArgs(options={}): getopt_options['short']['distfiles'] = "fs:" getopt_options['long']['distfiles'] = ["fetch-restricted", "size-limit="] getopt_options['short']['packages'] = "i" - getopt_options['long']['packages'] = ["ignore-failure", "changed-deps"] + getopt_options['long']['packages'] = ["ignore-failure", "changed-deps", + "changed-iuse"] # set default options, except 'nocolor', which is set in main() options['interactive'] = False options['pretend'] = False @@ -305,6 +310,7 @@ def parseArgs(options={}): options['size-limit'] = 0 options['verbose'] = False options['changed-deps'] = False + options['changed-iuse'] = False options['ignore-failure'] = False # if called by a well-named symlink, set the action accordingly: action = None diff --git a/pym/gentoolkit/eclean/search.py b/pym/gentoolkit/eclean/search.py index 8f6e52f..8344e15 100644 --- a/pym/gentoolkit/eclean/search.py +++ b/pym/gentoolkit/eclean/search.py @@ -498,6 +498,47 @@ def _deps_equal(deps_a, eapi_a, deps_b, eapi_b, uselist=None): return deps_a == deps_b +def _changed_deps(cpv, options, port_dbapi, bin_dbapi): + if not options['changed-deps']: + return False + + dep_keys = ('RDEPEND', 'PDEPEND') + keys = ('EAPI', 'USE') + dep_keys + binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys))) + ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys))) + + return _deps_equal(' '.join(binpkg_metadata[key] for key in dep_keys), + binpkg_metadata['EAPI'], ' '.join(ebuild_metadata[key] for key in dep_keys), + ebuild_metadata['EAPI'], + frozenset(binpkg_metadata['USE'].split())) + + +# IUSE flags to be ignored for purposes of invalidating binpkgs +def ignore(iuse): + return iuse.startswith('abi_') + + +# Prune the + characters from USE flags (e.g. '+cxx' -> 'cxx') +def prune_plus(iuse): + if iuse.startswith('+'): + return iuse[1:] + return iuse + + +def _changed_iuse(cpv, options, port_dbapi, bin_dbapi): + if not options['changed-iuse']: + return False + + keys = ('IUSE',) + binpkg_metadata = [prune_plus(x) for x in bin_dbapi.aux_get(cpv, keys)[0].split(' ') if not ignore(x)] + ebuild_metadata = [prune_plus(x) for x in port_dbapi.aux_get(cpv, keys)[0].split(' ') if not ignore(x)] + + if binpkg_metadata == ['']: binpkg_metadata = [] + if ebuild_metadata == ['']: ebuild_metadata = [] + + return binpkg_metadata != ebuild_metadata + + def findPackages( options, exclude=None, @@ -570,21 +611,6 @@ def findPackages( if mtime >= time_limit: continue - # Exclude if binpkg exists in the porttree and not --deep - if not destructive and port_dbapi.cpv_exists(cpv): - if not options['changed-deps']: - continue - - dep_keys = ('RDEPEND', 'PDEPEND') - keys = ('EAPI', 'USE') + dep_keys - binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys))) - ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys))) - - if _deps_equal(' '.join(binpkg_metadata[key] for key in dep_keys), binpkg_metadata['EAPI'], - ' '.join(ebuild_metadata[key] for key in dep_keys), ebuild_metadata['EAPI'], - frozenset(binpkg_metadata['USE'].split())): - continue - if destructive and var_dbapi.cpv_exists(cpv): # Exclude if an instance of the package is installed due to # the --package-names option. @@ -596,6 +622,12 @@ def findPackages( if buildtime == bin_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]: continue + # Exclude if binpkg exists in the porttree and not --deep + if not destructive and port_dbapi.cpv_exists(cpv): + if not _changed_deps(cpv, options, port_dbapi, bin_dbapi) and \ + not _changed_iuse(cpv, options, port_dbapi, bin_dbapi): + continue + binpkg_path = bin_dbapi.bintree.getname(cpv) dead_binpkgs.setdefault(cpv, []).append(binpkg_path) -- 2.26.2