spack uninstall: use topo order (#34053)

This commit is contained in:
Harmen Stoppels 2022-11-22 15:22:07 +01:00 committed by GitHub
parent bcc0fda4e2
commit 4bf964e6b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 49 deletions

View File

@ -43,4 +43,4 @@ def gc(parser, args):
if not args.yes_to_all: if not args.yes_to_all:
spack.cmd.uninstall.confirm_removal(specs) spack.cmd.uninstall.confirm_removal(specs)
spack.cmd.uninstall.do_uninstall(None, specs, force=False) spack.cmd.uninstall.do_uninstall(specs, force=False)

View File

@ -230,54 +230,21 @@ def _remove_from_env(spec, env):
pass # ignore non-root specs pass # ignore non-root specs
def do_uninstall(env, specs, force): def do_uninstall(specs, force=False):
"""Uninstalls all the specs in a list. # TODO: get rid of the call-sites that use this function,
# so that we don't have to do a dance of list -> set -> list -> set
hashes_to_remove = set(s.dag_hash() for s in specs)
Args: for s in traverse.traverse_nodes(
env (spack.environment.Environment or None): active environment, or ``None`` specs,
if there is not one order="topo",
specs (list): list of specs to be uninstalled direction="children",
force (bool): force uninstallation (boolean) root=True,
""" cover="nodes",
packages = [] deptype="all",
for item in specs: ):
try: if s.dag_hash() in hashes_to_remove:
# should work if package is known to spack spack.package_base.PackageBase.uninstall_by_spec(s, force=force)
packages.append(item.package)
except spack.repo.UnknownEntityError:
# The package.py file has gone away -- but still
# want to uninstall.
spack.package_base.PackageBase.uninstall_by_spec(item, force=True)
# A package is ready to be uninstalled when nothing else references it,
# unless we are requested to force uninstall it.
def is_ready(dag_hash):
if force:
return True
record = spack.store.db.query_local_by_spec_hash(dag_hash)
if not record.ref_count:
return True
# If this spec is only used as a build dependency, we can uninstall
return all(
dspec.deptypes == ("build",) or not dspec.parent.installed
for dspec in record.spec.edges_from_dependents()
)
while packages:
ready = [x for x in packages if is_ready(x.spec.dag_hash())]
if not ready:
msg = (
"unexpected error [cannot proceed uninstalling specs with"
" remaining link or run dependents {0}]"
)
msg = msg.format(", ".join(x.name for x in packages))
raise spack.error.SpackError(msg)
packages = [x for x in packages if x not in ready]
for item in ready:
item.do_uninstall(force=force)
def get_uninstall_list(args, specs, env): def get_uninstall_list(args, specs, env):
@ -419,7 +386,7 @@ def uninstall_specs(args, specs):
confirm_removal(uninstall_list) confirm_removal(uninstall_list)
# Uninstall everything on the list # Uninstall everything on the list
do_uninstall(env, uninstall_list, args.force) do_uninstall(uninstall_list, args.force)
if env: if env:
with env.write_transaction(): with env.write_transaction():