Skip to content

Commit e46cf1d

Browse files
committed
eclean-pkg: add --changed-iuse to clean binpkgs with stale IUSE
When PYTHON_COMPAT gains a new target, ebuilds grow a new default-disabled IUSE flag (e.g. python_targets_python3_14). Existing binary packages lack that flag, so Portage refuses to install them and there is no way to make them usable again -- they are orphaned and will only ever be rebuilt from source. Add --changed-iuse to delete such binpkgs. The comparison ignores USE flag defaults and only considers whether the set of flags matches the current ebuild's IUSE. Closes: https://bugs.gentoo.org/965888 Signed-off-by: Matt Turner <mattst88@gentoo.org>
1 parent 4962c21 commit e46cf1d

3 files changed

Lines changed: 41 additions & 2 deletions

File tree

man/eclean.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ This is only useful when scripting to ignore an otherwise fatal error.
115115
\fB\-\-changed\-deps\fP delete packages for which ebuild dependencies have changed
116116
.TP
117117
\fB\-\-changed\-subslot\fP delete packages with := deps on subslots no longer in the tree
118+
.TP
119+
\fB\-\-changed\-iuse\fP delete packages whose IUSE no longer matches the ebuild
120+
This is useful when, for instance, PYTHON_COMPAT changes and adds a new
121+
python_targets_* flag: the old binary package can never be a cache hit again.
118122
.SH "EXCLUSION FILES"
119123
Exclusions files are lists of packages names or categories you want to protect
120124
in particular. This may be useful to protect more binary packages for some system

pym/gentoolkit/eclean/cli.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ def printUsage(_error=None, help=None, unresolved_invalids=None):
266266
+ " - delete packages with := deps on subslots no longer in tree",
267267
file=out,
268268
)
269+
print(
270+
yellow(" --changed-iuse")
271+
+ " - delete packages whose IUSE no longer matches the ebuild",
272+
file=out,
273+
)
269274
print(
270275
yellow(" --no-clean-invalid")
271276
+ " - Skip cleaning invalid binpkgs",
@@ -425,6 +430,8 @@ def optionSwitch(option, opts, action=None):
425430
options["changed-deps"] = True
426431
elif o in ("--changed-subslot"):
427432
options["changed-subslot"] = True
433+
elif o in ("--changed-iuse"):
434+
options["changed-iuse"] = True
428435
elif o in ("-i", "--ignore-failure"):
429436
options["ignore-failure"] = True
430437
elif o in ("-u", "--unique-use"):
@@ -480,6 +487,7 @@ def optionSwitch(option, opts, action=None):
480487
"ignore-failure",
481488
"changed-deps",
482489
"changed-subslot",
490+
"changed-iuse",
483491
"unique-use",
484492
"no-clean-invalid",
485493
]
@@ -497,6 +505,7 @@ def optionSwitch(option, opts, action=None):
497505
options["verbose"] = False
498506
options["changed-deps"] = False
499507
options["changed-subslot"] = False
508+
options["changed-iuse"] = False
500509
options["ignore-failure"] = False
501510
options["no-clean-invalid"] = False
502511
options["unique-use"] = False

pym/gentoolkit/eclean/search.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,23 @@ def _check_subslot_deps(deps, eapi, port_dbapi, uselist=None, cpv=None, verbose=
657657
return False
658658

659659

660+
def _iuse_changed(iuse_binpkg, iuse_ebuild):
661+
"""Check if the set of IUSE flags differs between binpkg and ebuild.
662+
663+
USE flag defaults (a leading + or -) are ignored; only the presence of a
664+
flag matters. Portage cannot use a binpkg whose IUSE no longer matches the
665+
ebuild's (e.g. after PYTHON_COMPAT adds a new python_targets_* flag), so
666+
such a binpkg is orphaned and can be removed.
667+
668+
Returns True if the IUSE flags differ (binpkg should be removed).
669+
"""
670+
671+
def _flags(iuse):
672+
return frozenset(flag.lstrip("+-") for flag in iuse.split())
673+
674+
return _flags(iuse_binpkg) != _flags(iuse_ebuild)
675+
676+
660677
def _find_debuginfo_tarball(cpv: portage.versions._pkg_str, cp: str):
661678
"""
662679
From a CPV, identify and check for a matching debuginfo tarball.
@@ -806,11 +823,15 @@ def mk_binpkg_key(cpv):
806823

807824
# Exclude if binpkg exists in the porttree and not --deep
808825
if not destructive and port_dbapi.cpv_exists(cpv):
809-
if not options["changed-deps"] and not options["changed-subslot"]:
826+
if (
827+
not options["changed-deps"]
828+
and not options["changed-subslot"]
829+
and not options["changed-iuse"]
830+
):
810831
continue
811832

812833
dep_keys = ("RDEPEND", "PDEPEND")
813-
keys = ("EAPI", "USE") + dep_keys
834+
keys = ("EAPI", "USE", "IUSE") + dep_keys
814835
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
815836
deps_binpkg = " ".join(binpkg_metadata[key] for key in dep_keys)
816837
uselist = frozenset(binpkg_metadata["USE"].split())
@@ -842,6 +863,11 @@ def mk_binpkg_key(cpv):
842863
):
843864
should_remove = True
844865

866+
if not should_remove and options["changed-iuse"]:
867+
ebuild_iuse = port_dbapi.aux_get(cpv, ["IUSE"])[0]
868+
if _iuse_changed(binpkg_metadata["IUSE"], ebuild_iuse):
869+
should_remove = True
870+
845871
if not should_remove:
846872
continue
847873

0 commit comments

Comments
 (0)