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
9 changes: 9 additions & 0 deletions pym/gentoolkit/eclean/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ def printUsage(_error=None, help=None, unresolved_invalids=None):
+ " - delete packages for which ebuild dependencies have changed",
file=out,
)
print(
yellow(" --changed-subslot")
+ " - delete packages with := deps on subslots no longer in tree",
file=out,
)
print(
yellow(" --no-clean-invalid")
+ " - Skip cleaning invalid binpkgs",
Expand Down Expand Up @@ -418,6 +423,8 @@ def optionSwitch(option, opts, action=None):
options["verbose"] = True
elif o in ("--changed-deps"):
options["changed-deps"] = True
elif o in ("--changed-subslot"):
options["changed-subslot"] = True
elif o in ("-i", "--ignore-failure"):
options["ignore-failure"] = True
elif o in ("-u", "--unique-use"):
Expand Down Expand Up @@ -472,6 +479,7 @@ def optionSwitch(option, opts, action=None):
getopt_options["long"]["packages"] = [
"ignore-failure",
"changed-deps",
"changed-subslot",
"unique-use",
"no-clean-invalid",
]
Expand All @@ -488,6 +496,7 @@ def optionSwitch(option, opts, action=None):
options["size-limit"] = 0
options["verbose"] = False
options["changed-deps"] = False
options["changed-subslot"] = False
options["ignore-failure"] = False
options["no-clean-invalid"] = False
options["unique-use"] = False
Expand Down
113 changes: 100 additions & 13 deletions pym/gentoolkit/eclean/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,75 @@ def _deps_equal(deps_a, eapi_a, deps_b, eapi_b, libc_deps, uselist=None, cpv=Non
return deps_a == deps_b


def _check_subslot_deps(deps, eapi, port_dbapi, uselist=None, cpv=None, verbose=False):
"""Check if any := dep has a subslot no longer available in the tree.

Returns True if a stale subslot dep is found (binpkg should be removed).
"""
try:
dep_list = use_reduce(deps, uselist=uselist, eapi=eapi, token_class=Atom)
except InvalidDependString:
print(
pp.warn(
"Warning: Invalid binpkg DEPEND string found for: %s"
" | tagging for removal" % cpv
),
file=sys.stderr,
)
return True

queue = list(dep_list)
while queue:
token = queue.pop()
if isinstance(token, list):
queue.extend(token)
continue
if not isinstance(token, Atom):
continue
if not token.slot_operator_built:
continue
matches = port_dbapi.cp_list(token.cp)
if not matches:
continue
found = False
available_subslots = set()
for match_cpv in matches:
try:
slot_str = port_dbapi.aux_get(match_cpv, ["SLOT"])[0]
except KeyError:
continue
slot_parts = slot_str.split("/")
match_slot = slot_parts[0]
match_subslot = slot_parts[1] if len(slot_parts) > 1 else slot_parts[0]
if match_slot == token.slot:
if match_subslot == token.sub_slot:
found = True
break
available_subslots.add(match_subslot)
if not found:
if verbose:
print(
pp.warn(
" %s: stale subslot dep on %s:%s/%s=,"
" available subslot(s): %s"
% (
cpv,
token.cp,
token.slot,
token.sub_slot,
(
", ".join(sorted(available_subslots))
if available_subslots
else "(none)"
),
)
),
file=sys.stderr,
)
return True
return False


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 @@ -737,25 +806,43 @@ 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"]:
if not options["changed-deps"] and not options["changed-subslot"]:
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)))

deps_binpkg = " ".join(binpkg_metadata[key] for key in dep_keys)
deps_ebuild = " ".join(ebuild_metadata[key] for key in dep_keys)
if _deps_equal(
deps_binpkg,
binpkg_metadata["EAPI"],
deps_ebuild,
ebuild_metadata["EAPI"],
libc_deps,
frozenset(binpkg_metadata["USE"].split()),
cpv,
):
uselist = frozenset(binpkg_metadata["USE"].split())

should_remove = False

if options["changed-deps"]:
ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys)))
deps_ebuild = " ".join(ebuild_metadata[key] for key in dep_keys)
if not _deps_equal(
deps_binpkg,
binpkg_metadata["EAPI"],
deps_ebuild,
ebuild_metadata["EAPI"],
libc_deps,
uselist,
cpv,
):
should_remove = True

if not should_remove and options["changed-subslot"]:
if _check_subslot_deps(
deps_binpkg,
binpkg_metadata["EAPI"],
port_dbapi,
uselist,
cpv,
verbose=options["verbose"],
):
should_remove = True

if not should_remove:
continue

if destructive and var_dbapi.cpv_exists(cpv):
Expand Down
Loading