Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions man/eclean.1
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ Only effective with \-\-deep. Without \-\-deep, no VCS cleaning is done.
.TP
\fB\-i, \-\-ignore\-failure\fP ignore the failure to locate PKGDIR
This is only useful when scripting to ignore an otherwise fatal error.
.TP
\fB\-\-changed\-deps\fP delete packages for which ebuild dependencies have changed
.TP
\fB\-\-changed\-subslot\fP delete packages with := deps on subslots no longer in the tree
.TP
\fB\-\-changed\-iuse\fP delete packages whose IUSE no longer matches the ebuild

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These retroactively added descriptions were probably supposed to be a third commit?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They certainly can be, if you prefer.

This is useful when, for instance, PYTHON_COMPAT changes and adds a new
python_targets_* flag: the old binary package can never be a cache hit again.
.TP
\fB\-\-unreachable\fP delete packages that can no longer be a Portage cache hit
This enables all of the \-\-changed\-* options at once, so any binary package
that Portage can no longer reuse is removed regardless of why.
.SH "EXCLUSION FILES"
Exclusions files are lists of packages names or categories you want to protect
in particular. This may be useful to protect more binary packages for some system
Expand Down
20 changes: 20 additions & 0 deletions pym/gentoolkit/eclean/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,17 @@ def printUsage(_error=None, help=None, unresolved_invalids=None):
+ " - delete packages with := deps on subslots no longer in tree",
file=out,
)
print(
yellow(" --changed-iuse")
+ " - delete packages whose IUSE no longer matches the ebuild",
file=out,
)
print(
yellow(" --unreachable")
+ " - delete packages that can no longer be a cache hit"
+ " (enables all --changed-* options)",
file=out,
)
print(
yellow(" --no-clean-invalid")
+ " - Skip cleaning invalid binpkgs",
Expand Down Expand Up @@ -425,6 +436,12 @@ def optionSwitch(option, opts, action=None):
options["changed-deps"] = True
elif o in ("--changed-subslot"):
options["changed-subslot"] = True
elif o in ("--changed-iuse"):
options["changed-iuse"] = True
elif o in ("--unreachable"):
options["changed-deps"] = True
options["changed-subslot"] = True
options["changed-iuse"] = True
elif o in ("-i", "--ignore-failure"):
options["ignore-failure"] = True
elif o in ("-u", "--unique-use"):
Expand Down Expand Up @@ -480,6 +497,8 @@ def optionSwitch(option, opts, action=None):
"ignore-failure",
"changed-deps",
"changed-subslot",
"changed-iuse",
"unreachable",
"unique-use",
"no-clean-invalid",
]
Expand All @@ -497,6 +516,7 @@ def optionSwitch(option, opts, action=None):
options["verbose"] = False
options["changed-deps"] = False
options["changed-subslot"] = False
options["changed-iuse"] = False
options["ignore-failure"] = False
options["no-clean-invalid"] = False
options["unique-use"] = False
Expand Down
30 changes: 28 additions & 2 deletions pym/gentoolkit/eclean/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,23 @@ def _check_subslot_deps(deps, eapi, port_dbapi, uselist=None, cpv=None, verbose=
return False


def _iuse_changed(iuse_binpkg, iuse_ebuild):
"""Check if the set of IUSE flags differs between binpkg and ebuild.

USE flag defaults (a leading + or -) are ignored; only the presence of a
flag matters. Portage cannot use a binpkg whose IUSE no longer matches the
ebuild's (e.g. after PYTHON_COMPAT adds a new python_targets_* flag), so
such a binpkg is orphaned and can be removed.

Returns True if the IUSE flags differ (binpkg should be removed).
"""

def _flags(iuse):
return frozenset(flag.lstrip("+-") for flag in iuse.split())

return _flags(iuse_binpkg) != _flags(iuse_ebuild)


def _find_debuginfo_tarball(cpv: portage.versions._pkg_str, cp: str):
"""
From a CPV, identify and check for a matching debuginfo tarball.
Expand Down Expand Up @@ -806,11 +823,15 @@ def mk_binpkg_key(cpv):

# Exclude if binpkg exists in the porttree and not --deep
if not destructive and port_dbapi.cpv_exists(cpv):
if not options["changed-deps"] and not options["changed-subslot"]:
if (
not options["changed-deps"]
and not options["changed-subslot"]
and not options["changed-iuse"]
):
continue

dep_keys = ("RDEPEND", "PDEPEND")
keys = ("EAPI", "USE") + dep_keys
keys = ("EAPI", "USE", "IUSE") + dep_keys
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
deps_binpkg = " ".join(binpkg_metadata[key] for key in dep_keys)
uselist = frozenset(binpkg_metadata["USE"].split())
Expand Down Expand Up @@ -842,6 +863,11 @@ def mk_binpkg_key(cpv):
):
should_remove = True

if not should_remove and options["changed-iuse"]:
ebuild_iuse = port_dbapi.aux_get(cpv, ["IUSE"])[0]
if _iuse_changed(binpkg_metadata["IUSE"], ebuild_iuse):
should_remove = True

if not should_remove:
continue

Expand Down
Loading