From c93e465134b06b8f18717fc664ac328858bad95c Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 8 May 2022 01:19:44 -0700 Subject: full hash: fix uninstall and gc with full hash DB The database now stores full hashes, so we need to adjust the criteria we use to determine if something can be uninstalled. Specifically, it's ok to uninstall thing that have remaining build-only dependents. --- lib/spack/spack/cmd/uninstall.py | 18 ++++++++++++++---- lib/spack/spack/database.py | 7 +++++++ lib/spack/spack/package.py | 6 +++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py index ce3d6f7dab..f7fbd67754 100644 --- a/lib/spack/spack/cmd/uninstall.py +++ b/lib/spack/spack/cmd/uninstall.py @@ -225,15 +225,25 @@ def do_uninstall(env, specs, force): # A package is ready to be uninstalled when nothing else references it, # unless we are requested to force uninstall it. - is_ready = lambda x: not spack.store.db.query_by_spec_hash(x)[1].ref_count - if force: - is_ready = lambda x: True + def is_ready(dag_hash): + if force: + return True + + _, record = spack.store.db.query_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",) + 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 dependents {0}]' + ' remaining link or run dependents {0}]' msg = msg.format(', '.join(x.name for x in packages)) raise spack.error.SpackError(msg) diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py index 06389cad78..1b10965a42 100644 --- a/lib/spack/spack/database.py +++ b/lib/spack/spack/database.py @@ -691,6 +691,13 @@ class Database(object): return db def query_by_spec_hash(self, hash_key, data=None): + """Get a spec for hash, and whether it's installed upstream. + + Return: + (tuple): (bool, optional InstallRecord): bool tells us whether + the spec is installed upstream. Its InstallRecord is also + returned if it's installed at all; otherwise None. + """ if data and hash_key in data: return False, data[hash_key] if not data: diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 9fc227baec..ce8f2add09 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -2371,7 +2371,11 @@ class PackageBase(six.with_metaclass(PackageMeta, PackageViewMixin, object)): if not force: dependents = spack.store.db.installed_relatives( - spec, 'parents', True) + spec, + direction='parents', + transitive=True, + deptype=("link", "run"), + ) if dependents: raise PackageStillNeededError(spec, dependents) -- cgit v1.2.3-70-g09d2