From 4acdfeae61d278ecf682adee1b9842d58ce3035a Mon Sep 17 00:00:00 2001 From: Tom Scogland Date: Fri, 29 Apr 2016 10:21:55 -0700 Subject: track whether a package was installed "explicitly" Adds a new attribute in the database to track whether a package was installed explicitly or not, where explicitly is the user running `spack install ` and implicitly is it being installed as a dependency. It also adds arguments to `spack find` to find these packages such that it should be possible to query the packages that were installed implicitly and are not currently depended upon any longer. --- lib/spack/spack/cmd/find.py | 15 ++++++++++++++- lib/spack/spack/cmd/install.py | 3 ++- lib/spack/spack/database.py | 20 ++++++++++++-------- lib/spack/spack/package.py | 5 +++-- 4 files changed, 31 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index a99012a275..6896e92ef5 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -57,6 +57,12 @@ def setup_parser(subparser): '-L', '--very-long', action='store_true', help='Show dependency hashes as well as versions.') + subparser.add_argument( + '-e', '--explicit', action='store_true', + help='Show only specs that were installed explicitly') + subparser.add_argument( + '-E', '--implicit', action='store_true', + help='Show only specs that were installed as dependencies') subparser.add_argument( '-u', '--unknown', action='store_true', help='Show only specs Spack does not have a package for.') @@ -163,7 +169,14 @@ def find(parser, args): installed = any if args.unknown: known = False - q_args = { 'installed' : installed, 'known' : known } + + explicit = None + if args.explicit: + explicit = False + if args.implicit: + explicit = True + + q_args = { 'installed' : installed, 'known' : known, "explicit" : explicit } # Get all the specs the user asked for if not query_specs: diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py index fef21f15ba..9d3175786b 100644 --- a/lib/spack/spack/cmd/install.py +++ b/lib/spack/spack/cmd/install.py @@ -78,4 +78,5 @@ def install(parser, args): ignore_deps=args.ignore_deps, make_jobs=args.jobs, verbose=args.verbose, - fake=args.fake) + fake=args.fake, + explicit=True) diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py index ee4473e079..73bc8143c8 100644 --- a/lib/spack/spack/database.py +++ b/lib/spack/spack/database.py @@ -92,22 +92,24 @@ class InstallRecord(object): dependents left. """ - def __init__(self, spec, path, installed, ref_count=0): + def __init__(self, spec, path, installed, ref_count=0, explicit=False): self.spec = spec self.path = str(path) self.installed = bool(installed) self.ref_count = ref_count + self.explicit = explicit def to_dict(self): return { 'spec' : self.spec.to_node_dict(), 'path' : self.path, 'installed' : self.installed, - 'ref_count' : self.ref_count } + 'ref_count' : self.ref_count, + 'explicit' : self.explicit } @classmethod def from_dict(cls, spec, dictionary): d = dictionary - return InstallRecord(spec, d['path'], d['installed'], d['ref_count']) + return InstallRecord(spec, d['path'], d['installed'], d['ref_count'], d.get('explicit', False)) class Database(object): @@ -370,7 +372,7 @@ class Database(object): self.reindex(spack.install_layout) - def _add(self, spec, path, directory_layout=None): + def _add(self, spec, path, directory_layout=None, explicit=False): """Add an install record for spec at path to the database. This assumes that the spec is not already installed. It @@ -392,7 +394,7 @@ class Database(object): rec.path = path else: - self._data[key] = InstallRecord(spec, path, True) + self._data[key] = InstallRecord(spec, path, True, explicit=explicit) for dep in spec.dependencies.values(): self._increment_ref_count(dep, directory_layout) @@ -415,7 +417,7 @@ class Database(object): self._data[key].ref_count += 1 @_autospec - def add(self, spec, path): + def add(self, spec, path, explicit=False): """Add spec at path to database, locking and reading DB to sync. ``add()`` will lock and read from the DB on disk. @@ -424,7 +426,7 @@ class Database(object): # TODO: ensure that spec is concrete? # Entire add is transactional. with self.write_transaction(): - self._add(spec, path) + self._add(spec, path, explicit=explicit) def _get_matching_spec_key(self, spec, **kwargs): @@ -513,7 +515,7 @@ class Database(object): # TODO: conditional way to do this instead of catching exceptions - def query(self, query_spec=any, known=any, installed=True): + def query(self, query_spec=any, known=any, installed=True, explicit=any): """Run a query on the database. ``query_spec`` @@ -553,6 +555,8 @@ class Database(object): for key, rec in self._data.items(): if installed is not any and rec.installed != installed: continue + if explicit is not any and rec.explicit != explicit: + continue if known is not any and spack.repo.exists(rec.spec.name) != known: continue if query_spec is any or rec.spec.satisfies(query_spec): diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 8167341127..d1c36d0670 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -857,7 +857,8 @@ class Package(object): skip_patch=False, verbose=False, make_jobs=None, - fake=False): + fake=False, + explicit=False): """Called by commands to install a package and its dependencies. Package implementations should override install() to describe @@ -995,7 +996,7 @@ class Package(object): # note: PARENT of the build process adds the new package to # the database, so that we don't need to re-read from file. - spack.installed_db.add(self.spec, self.prefix) + spack.installed_db.add(self.spec, self.prefix, explicit=explicit) def sanity_check_prefix(self): """This function checks whether install succeeded.""" -- cgit v1.2.3-60-g2f50