Rename install.yaml -> config.yaml, install_area -> "store"

- Added a schema for config.yaml
- Moved install tree configuration to config.yaml
- Moved etc/spack/install.yaml to etc/spack/defaults/config.yaml
- renamed install_area to "store", to use a term in common with guix/nix.
  - in `config.yaml` file, it's called the `install_tree` to be more
    intuitive to users.
  - `install_tree` might've worked in the code, but `install_tree` is
    already a global function in the spack namespace, from
    llnl.util.filesystem.
This commit is contained in:
Todd Gamblin 2016-10-27 10:57:27 -07:00
parent 24901f7a38
commit 9347f86939
23 changed files with 266 additions and 164 deletions

View File

@ -0,0 +1,64 @@
# -------------------------------------------------------------------------
# This is the default spack configuration file.
#
# Settings here are versioned with Spack and are intended to provide
# sensible defaults out of the box. Spack maintainers should edit this
# file to keep it current.
#
# Users can override these settings by editing the following files.
#
# Per-spack-instance settings (overrides defaults):
# $SPACK_ROOT/etc/spack/config.yaml
#
# Per-user settings (overrides default and site settings):
# ~/.spack/config.yaml
# -------------------------------------------------------------------------
config:
# Precedence of configuration scopes, high to low.
# The user can override this paradoxically.
# scopes: [user, spack, default]
# This is the path to the root of the Spack install tree.
# You can use $spack here to refer to the root of the spack instance.
install_tree: $spack/opt/spack
# Temporary locations Spack can try to use for builds.
#
# Spack will use the first one it finds that exists and is writable.
# You can use $tempdir to refer to the system default temp directory
# (as returned by tempfile.gettempdir()).
#
# A value of $local indicates that Spack should run builds directly
# inside its install directory without staging them in temporary space.
build_stage:
- /usr/workspace/*/%u
- $tempdir
- /nfs/tmp2/%u
- $local
# Cache directory already downloaded source tarballs and archived
# repositories. This can be purged with spack purge
source_cache: $spack/var/spack/cache
# Cache directory for miscellaneous files, like the package index.
misc_cache: ~/.spack/cache
# If this is false, tools like curl that use SSL will not verify
# certifiates. (e.g., curl will use use the -k option)
verify_ssl: true
# If set to true, Spack will always check checksums after downloading
# archives. If false, Spack skips the checksum step.
checksum: true
# If set to true, `spack install` and friends will NOT clean
# potentially harmful variables from the build environment. Use wisely.
dirty: false

View File

@ -1,8 +0,0 @@
# -------------------------------------------------------------------------
# This is the default spack install setup configuration.
#
# Changes to this file will affect all users of this spack install
# -------------------------------------------------------------------------
install:
path: $spack/opt/spack
layout : YamlDirectoryLayout

View File

@ -10,8 +10,8 @@ Install options
---------------------------- ----------------------------
By default, Spack will install software into ``opt/spack``. By default, Spack will install software into ``opt/spack``.
To set a custom install directory, the option ``path`` in To set a custom install directory, the option ``install_tree`` in
``install.yaml`` can be used. This file can be found ``config.yaml`` can be used. This file can be found
in a Spack installation's ``etc/spack/`` or a user's ``~/.spack/`` in a Spack installation's ``etc/spack/`` or a user's ``~/.spack/``
directory. directory.

View File

@ -145,22 +145,6 @@
# for. # for.
do_checksum = True do_checksum = True
#
# SYS_TYPE to use for the spack installation.
# Value of this determines what platform spack thinks it is by
# default. You can assign three types of values:
# 1. None
# Spack will try to determine the sys_type automatically.
#
# 2. A string
# Spack will assume that the sys_type is hardcoded to the value.
#
# 3. A function that returns a string:
# Spack will use this function to determine the sys_type.
#
sys_type = None
# #
# When packages call 'from spack import *', this extra stuff is brought in. # When packages call 'from spack import *', this extra stuff is brought in.
# #

View File

@ -58,7 +58,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.install_area import spack.store
from llnl.util.filesystem import * from llnl.util.filesystem import *
from spack.environment import EnvironmentModifications, validate from spack.environment import EnvironmentModifications, validate
from spack.util.environment import * from spack.util.environment import *
@ -277,7 +277,7 @@ def set_build_environment_variables(pkg, env, dirty=False):
env.set(SPACK_PREFIX, pkg.prefix) env.set(SPACK_PREFIX, pkg.prefix)
# Install root prefix # Install root prefix
env.set(SPACK_INSTALL, spack.install_area.path) env.set(SPACK_INSTALL, spack.store.root)
# Stuff in here sanitizes the build environemnt to eliminate # Stuff in here sanitizes the build environemnt to eliminate
# anything the user has set that may interfere. # anything the user has set that may interfere.

View File

@ -34,7 +34,7 @@
import spack import spack
import spack.config import spack.config
import spack.spec import spack.spec
import spack.install_area import spack.store
# #
# Settings for commands that modify configuration # Settings for commands that modify configuration
@ -137,7 +137,7 @@ def elide_list(line_list, max_num=10):
def disambiguate_spec(spec): def disambiguate_spec(spec):
matching_specs = spack.install_area.db.query(spec) matching_specs = spack.store.db.query(spec)
if not matching_specs: if not matching_specs:
tty.die("Spec '%s' matches no installed packages." % spec) tty.die("Spec '%s' matches no installed packages." % spec)

View File

@ -25,7 +25,7 @@
import argparse import argparse
import spack.install_area import spack.store
import spack.modules import spack.modules
from spack.util.pattern import Bunch from spack.util.pattern import Bunch
__all__ = ['add_common_arguments'] __all__ = ['add_common_arguments']
@ -54,7 +54,7 @@ class ConstraintAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
# Query specs from command line # Query specs from command line
d = self.qualifiers.get(namespace.subparser_name, {}) d = self.qualifiers.get(namespace.subparser_name, {})
specs = [s for s in spack.install_area.db.query(**d)] specs = [s for s in spack.store.db.query(**d)]
values = ' '.join(values) values = ' '.join(values)
if values: if values:
specs = [x for x in specs if x.satisfies(values, strict=True)] specs = [x for x in specs if x.satisfies(values, strict=True)]

View File

@ -27,7 +27,7 @@
import spack import spack
import spack.cmd import spack.cmd
import spack.install_area import spack.store
from spack.graph import topological_sort from spack.graph import topological_sort
description = "Deactivate a package extension." description = "Deactivate a package extension."
@ -57,7 +57,7 @@ def deactivate(parser, args):
if args.all: if args.all:
if pkg.extendable: if pkg.extendable:
tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec) tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec)
ext_pkgs = spack.install_area.db.installed_extensions_for(spec) ext_pkgs = spack.store.db.installed_extensions_for(spec)
for ext_pkg in ext_pkgs: for ext_pkg in ext_pkgs:
ext_pkg.spec.normalize() ext_pkg.spec.normalize()

View File

@ -30,7 +30,7 @@
import spack import spack
import spack.cmd import spack.cmd
import spack.cmd.find import spack.cmd.find
import spack.install_area import spack.store
description = "List extensions for package." description = "List extensions for package."
@ -88,7 +88,7 @@ def extensions(parser, args):
# List specs of installed extensions. # List specs of installed extensions.
# #
installed = [s.spec installed = [s.spec
for s in spack.install_area.db.installed_extensions_for(spec)] for s in spack.store.db.installed_extensions_for(spec)]
print print
if not installed: if not installed:
@ -100,7 +100,7 @@ def extensions(parser, args):
# #
# List specs of activated extensions. # List specs of activated extensions.
# #
activated = spack.install_area.layout.extension_map(spec) activated = spack.store.layout.extension_map(spec)
print print
if not activated: if not activated:
tty.msg("None activated.") tty.msg("None activated.")

View File

@ -28,7 +28,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.spec import spack.spec
import spack.install_area import spack.store
from llnl.util.lang import * from llnl.util.lang import *
from llnl.util.tty.colify import * from llnl.util.tty.colify import *
from llnl.util.tty.color import * from llnl.util.tty.color import *
@ -146,9 +146,9 @@ def find(parser, args):
# Get all the specs the user asked for # Get all the specs the user asked for
if not query_specs: if not query_specs:
specs = set(spack.install_area.db.query(**q_args)) specs = set(spack.store.db.query(**q_args))
else: else:
results = [set(spack.install_area.db.query(qs, **q_args)) results = [set(spack.store.db.query(qs, **q_args))
for qs in query_specs] for qs in query_specs]
specs = set.union(*results) specs = set.union(*results)

View File

@ -23,9 +23,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import spack import spack
import spack.install_area import spack.store
description = "Rebuild Spack's package database." description = "Rebuild Spack's package database."
def reindex(parser, args): def reindex(parser, args):
spack.install_area.db.reindex(spack.install_area.layout) spack.store.db.reindex(spack.store.layout)

View File

@ -29,7 +29,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.cmd import spack.cmd
import spack.install_area import spack.store
import spack.repository import spack.repository
description = "Remove an installed package" description = "Remove an installed package"
@ -90,7 +90,7 @@ def concretize_specs(specs, allow_multiple_matches=False, force=False):
specs_from_cli = [] specs_from_cli = []
has_errors = False has_errors = False
for spec in specs: for spec in specs:
matching = spack.install_area.db.query(spec) matching = spack.store.db.query(spec)
# For each spec provided, make sure it refers to only one package. # For each spec provided, make sure it refers to only one package.
# Fail and ask user to be unambiguous if it doesn't # Fail and ask user to be unambiguous if it doesn't
if not allow_multiple_matches and len(matching) > 1: if not allow_multiple_matches and len(matching) > 1:

View File

@ -180,7 +180,7 @@
'repos': spack.schema.repos.schema, 'repos': spack.schema.repos.schema,
'packages': spack.schema.packages.schema, 'packages': spack.schema.packages.schema,
'modules': spack.schema.modules.schema, 'modules': spack.schema.modules.schema,
'install': spack.schema.install.schema, 'config': spack.schema.config.schema,
} }
"""OrderedDict of config scopes keyed by name. """OrderedDict of config scopes keyed by name.

View File

@ -48,7 +48,7 @@
from llnl.util.filesystem import * from llnl.util.filesystem import *
from llnl.util.lock import * from llnl.util.lock import *
import spack.install_area import spack.store
import spack.repository import spack.repository
from spack.directory_layout import DirectoryLayoutError from spack.directory_layout import DirectoryLayoutError
from spack.version import Version from spack.version import Version
@ -280,7 +280,7 @@ def check(cond, msg):
if version > _db_version: if version > _db_version:
raise InvalidDatabaseVersionError(_db_version, version) raise InvalidDatabaseVersionError(_db_version, version)
elif version < _db_version: elif version < _db_version:
self.reindex(spack.install_area.layout) self.reindex(spack.store.layout)
installs = dict((k, v.to_dict()) for k, v in self._data.items()) installs = dict((k, v.to_dict()) for k, v in self._data.items())
def invalid_record(hash_key, error): def invalid_record(hash_key, error):
@ -446,7 +446,7 @@ def _read(self):
else: else:
# The file doesn't exist, try to traverse the directory. # The file doesn't exist, try to traverse the directory.
# reindex() takes its own write lock, so no lock here. # reindex() takes its own write lock, so no lock here.
self.reindex(spack.install_area.layout) self.reindex(spack.store.layout)
def _add(self, spec, directory_layout=None, explicit=False): def _add(self, spec, directory_layout=None, explicit=False):
"""Add an install record for this spec to the database. """Add an install record for this spec to the database.

View File

@ -1,36 +0,0 @@
__author__ = "Benedikt Hegner (CERN)"
import re
import llnl.util.tty as tty
from llnl.util.filesystem import *
#
# Read in the config
#
import spack.config
config = spack.config.get_config("install")
#
# Set up the install path
#
path = re.sub(r'^\$spack', spack.prefix, config['path'])
#
# Set up the installed packages database
#
from spack.database import Database
db = Database(path)
#
# This controls how spack lays out install prefixes and
# stage directories.
#
import spack.directory_layout
try:
layout_name = config["layout"]
layout_class = getattr(spack.directory_layout,layout_name)
layout = layout_class(path)
except:
tty.die("Invalid install directory layout %s chosen." %layout_name)

View File

@ -47,7 +47,7 @@
import llnl.util.lock import llnl.util.lock
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.install_area import spack.store
import spack.compilers import spack.compilers
import spack.directives import spack.directives
import spack.error import spack.error
@ -832,7 +832,7 @@ def activated(self):
if not self.is_extension: if not self.is_extension:
raise ValueError( raise ValueError(
"is_extension called on package that is not an extension.") "is_extension called on package that is not an extension.")
exts = spack.install_area.layout.extension_map(self.extendee_spec) exts = spack.store.layout.extension_map(self.extendee_spec)
return (self.name in exts) and (exts[self.name] == self.spec) return (self.name in exts) and (exts[self.name] == self.spec)
def provides(self, vpkg_name): def provides(self, vpkg_name):
@ -853,7 +853,7 @@ def installed_dependents(self):
TODO: move this method to database.py? TODO: move this method to database.py?
""" """
dependents = [] dependents = []
for spec in spack.install_area.db.query(): for spec in spack.store.db.query():
if self.name == spec.name: if self.name == spec.name:
continue continue
# XXX(deptype): Should build dependencies not count here? # XXX(deptype): Should build dependencies not count here?
@ -867,7 +867,7 @@ def installed_dependents(self):
def prefix_lock(self): def prefix_lock(self):
"""Prefix lock is a byte range lock on the nth byte of a file. """Prefix lock is a byte range lock on the nth byte of a file.
The lock file is ``spack.install_area.db.prefix_lock`` -- the DB The lock file is ``spack.store.db.prefix_lock`` -- the DB
tells us what to call it and it lives alongside the install DB. tells us what to call it and it lives alongside the install DB.
n is the sys.maxsize-bit prefix of the DAG hash. This makes n is the sys.maxsize-bit prefix of the DAG hash. This makes
@ -879,7 +879,7 @@ def prefix_lock(self):
prefix = self.spec.prefix prefix = self.spec.prefix
if prefix not in Package.prefix_locks: if prefix not in Package.prefix_locks:
Package.prefix_locks[prefix] = llnl.util.lock.Lock( Package.prefix_locks[prefix] = llnl.util.lock.Lock(
spack.install_area.db.prefix_lock_path, spack.store.db.prefix_lock_path,
self.spec.dag_hash_bit_prefix(bit_length(sys.maxsize)), 1) self.spec.dag_hash_bit_prefix(bit_length(sys.maxsize)), 1)
self._prefix_lock = Package.prefix_locks[prefix] self._prefix_lock = Package.prefix_locks[prefix]
@ -916,7 +916,7 @@ def remove_prefix(self):
Removes the prefix for a package along with any empty parent Removes the prefix for a package along with any empty parent
directories directories
""" """
spack.install_area.layout.remove_install_directory(self.spec) spack.store.layout.remove_install_directory(self.spec)
def do_fetch(self, mirror_only=False): def do_fetch(self, mirror_only=False):
""" """
@ -1153,15 +1153,15 @@ def do_install(self,
return return
# Ensure package is not already installed # Ensure package is not already installed
layout = spack.install_area.layout layout = spack.store.layout
with self._prefix_read_lock(): with self._prefix_read_lock():
if layout.check_installed(self.spec): if layout.check_installed(self.spec):
tty.msg( tty.msg(
"%s is already installed in %s" % (self.name, self.prefix)) "%s is already installed in %s" % (self.name, self.prefix))
rec = spack.install_area.db.get_record(self.spec) rec = spack.store.db.get_record(self.spec)
if (not rec.explicit) and explicit: if (not rec.explicit) and explicit:
with spack.install_area.db.write_transaction(): with spack.store.db.write_transaction():
rec = spack.install_area.db.get_record(self.spec) rec = spack.store.db.get_record(self.spec)
rec.explicit = True rec.explicit = True
return return
@ -1266,15 +1266,15 @@ def build_process():
try: try:
# Create the install prefix and fork the build process. # Create the install prefix and fork the build process.
spack.install_area.layout.create_install_directory(self.spec) spack.store.layout.create_install_directory(self.spec)
# Fork a child to do the actual installation # Fork a child to do the actual installation
spack.build_environment.fork(self, build_process, dirty=dirty) spack.build_environment.fork(self, build_process, dirty=dirty)
# If we installed then we should keep the prefix # If we installed then we should keep the prefix
keep_prefix = True if self.last_phase is None else keep_prefix keep_prefix = True if self.last_phase is None else keep_prefix
# note: PARENT of the build process adds the new package to # note: PARENT of the build process adds the new package to
# the database, so that we don't need to re-read from file. # the database, so that we don't need to re-read from file.
spack.install_area.db.add( spack.store.db.add(
self.spec, spack.install_area.layout, explicit=explicit self.spec, spack.store.layout, explicit=explicit
) )
except directory_layout.InstallDirectoryAlreadyExistsError: except directory_layout.InstallDirectoryAlreadyExistsError:
# Abort install if install directory exists. # Abort install if install directory exists.
@ -1303,15 +1303,16 @@ def _do_install_pop_kwargs(self, kwargs):
""" """
self.last_phase = kwargs.pop('stop_at', None) self.last_phase = kwargs.pop('stop_at', None)
if self.last_phase is not None and self.last_phase not in self.phases: if self.last_phase is not None and self.last_phase not in self.phases:
tty.die('\'{0.last_phase}\' is not among the allowed phases for package {0.name}'.format(self)) # NOQA: ignore=E501 tty.die('\'{0}\' is not an allowed phase for package {1}'
.format(self.last_phase, self.name))
def log(self): def log(self):
# Copy provenance into the install directory on success # Copy provenance into the install directory on success
log_install_path = spack.install_area.layout.build_log_path( log_install_path = spack.store.layout.build_log_path(
self.spec) self.spec)
env_install_path = spack.install_area.layout.build_env_path( env_install_path = spack.store.layout.build_env_path(
self.spec) self.spec)
packages_dir = spack.install_area.layout.build_packages_path( packages_dir = spack.store.layout.build_packages_path(
self.spec) self.spec)
# Remove first if we're overwriting another build # Remove first if we're overwriting another build
@ -1345,7 +1346,8 @@ def check_paths(path_list, filetype, predicate):
check_paths(self.sanity_check_is_dir, 'directory', os.path.isdir) check_paths(self.sanity_check_is_dir, 'directory', os.path.isdir)
installed = set(os.listdir(self.prefix)) installed = set(os.listdir(self.prefix))
installed.difference_update(spack.install_area.layout.hidden_file_paths) installed.difference_update(
spack.store.layout.hidden_file_paths)
if not installed: if not installed:
raise InstallError( raise InstallError(
"Install failed for %s. Nothing was installed!" % self.name) "Install failed for %s. Nothing was installed!" % self.name)
@ -1353,7 +1355,7 @@ def check_paths(path_list, filetype, predicate):
@property @property
def build_log_path(self): def build_log_path(self):
if self.installed: if self.installed:
return spack.install_area.layout.build_log_path(self.spec) return spack.store.layout.build_log_path(self.spec)
else: else:
return join_path(self.stage.source_path, 'spack-build.out') return join_path(self.stage.source_path, 'spack-build.out')
@ -1483,9 +1485,9 @@ def do_uninstall(self, force=False):
if not self.installed: if not self.installed:
# prefix may not exist, but DB may be inconsistent. Try to fix by # prefix may not exist, but DB may be inconsistent. Try to fix by
# removing, but omit hooks. # removing, but omit hooks.
specs = spack.install_area.db.query(self.spec, installed=True) specs = spack.store.db.query(self.spec, installed=True)
if specs: if specs:
spack.install_area.db.remove(specs[0]) spack.store.db.remove(specs[0])
tty.msg("Removed stale DB entry for %s" % self.spec.short_spec) tty.msg("Removed stale DB entry for %s" % self.spec.short_spec)
return return
else: else:
@ -1502,7 +1504,7 @@ def do_uninstall(self, force=False):
# Uninstalling in Spack only requires removing the prefix. # Uninstalling in Spack only requires removing the prefix.
self.remove_prefix() self.remove_prefix()
# #
spack.install_area.db.remove(self.spec) spack.store.db.remove(self.spec)
tty.msg("Successfully uninstalled %s" % self.spec.short_spec) tty.msg("Successfully uninstalled %s" % self.spec.short_spec)
# Once everything else is done, run post install hooks # Once everything else is done, run post install hooks
@ -1536,8 +1538,8 @@ def do_activate(self, force=False):
""" """
self._sanity_check_extension() self._sanity_check_extension()
spack.install_area.layout.check_extension_conflict(self.extendee_spec, spack.store.layout.check_extension_conflict(
self.spec) self.extendee_spec, self.spec)
# Activate any package dependencies that are also extensions. # Activate any package dependencies that are also extensions.
if not force: if not force:
@ -1548,7 +1550,7 @@ def do_activate(self, force=False):
self.extendee_spec.package.activate(self, **self.extendee_args) self.extendee_spec.package.activate(self, **self.extendee_args)
spack.install_area.layout.add_extension(self.extendee_spec, self.spec) spack.store.layout.add_extension(self.extendee_spec, self.spec)
tty.msg("Activated extension %s for %s" % tty.msg("Activated extension %s for %s" %
(self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@"))) (self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@")))
@ -1563,7 +1565,7 @@ def activate(self, extension, **kwargs):
""" """
def ignore(filename): def ignore(filename):
return (filename in spack.install_area.layout.hidden_file_paths or return (filename in spack.store.layout.hidden_file_paths or
kwargs.get('ignore', lambda f: False)(filename)) kwargs.get('ignore', lambda f: False)(filename))
tree = LinkTree(extension.prefix) tree = LinkTree(extension.prefix)
@ -1581,9 +1583,11 @@ def do_deactivate(self, **kwargs):
# Allow a force deactivate to happen. This can unlink # Allow a force deactivate to happen. This can unlink
# spurious files if something was corrupted. # spurious files if something was corrupted.
if not force: if not force:
spack.install_area.layout.check_activated(self.extendee_spec, self.spec) spack.store.layout.check_activated(
self.extendee_spec, self.spec)
activated = spack.install_area.layout.extension_map(self.extendee_spec) activated = spack.store.layout.extension_map(
self.extendee_spec)
for name, aspec in activated.items(): for name, aspec in activated.items():
if aspec == self.spec: if aspec == self.spec:
continue continue
@ -1599,8 +1603,8 @@ def do_deactivate(self, **kwargs):
# redundant activation check -- makes SURE the spec is not # redundant activation check -- makes SURE the spec is not
# still activated even if something was wrong above. # still activated even if something was wrong above.
if self.activated: if self.activated:
spack.install_area.layout.remove_extension(self.extendee_spec, spack.store.layout.remove_extension(
self.spec) self.extendee_spec, self.spec)
tty.msg("Deactivated extension %s for %s" % tty.msg("Deactivated extension %s for %s" %
(self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@"))) (self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@")))
@ -1616,7 +1620,7 @@ def deactivate(self, extension, **kwargs):
""" """
def ignore(filename): def ignore(filename):
return (filename in spack.install_area.layout.hidden_file_paths or return (filename in spack.store.layout.hidden_file_paths or
kwargs.get('ignore', lambda f: False)(filename)) kwargs.get('ignore', lambda f: False)(filename))
tree = LinkTree(extension.prefix) tree = LinkTree(extension.prefix)
@ -1717,7 +1721,7 @@ def flatten_dependencies(spec, flat_dir):
for dep in spec.traverse(root=False): for dep in spec.traverse(root=False):
name = dep.name name = dep.name
dep_path = spack.install_area.layout.path_for_spec(dep) dep_path = spack.store.layout.path_for_spec(dep)
dep_files = LinkTree(dep_path) dep_files = LinkTree(dep_path)
os.mkdir(flat_dir + '/' + name) os.mkdir(flat_dir + '/' + name)
@ -1746,7 +1750,7 @@ def dump_packages(spec, path):
if node is not spec: if node is not spec:
# Locate the dependency package in the install tree and find # Locate the dependency package in the install tree and find
# its provenance information. # its provenance information.
source = spack.install_area.layout.build_packages_path(node) source = spack.store.layout.build_packages_path(node)
source_repo_root = join_path(source, node.namespace) source_repo_root = join_path(source, node.namespace)
# There's no provenance installed for the source package. Skip it. # There's no provenance installed for the source package. Skip it.

View File

@ -30,13 +30,32 @@
'type': 'object', 'type': 'object',
'additionalProperties': False, 'additionalProperties': False,
'patternProperties': { 'patternProperties': {
'install': { 'config': {
'type': 'object', 'type': 'object',
'default' : {}, 'default': {},
'additionalProperties': False, 'additionalProperties': False,
'properties': { 'properties': {
'path' : { 'type': 'string' }, 'install_tree': {'type': 'string'},
'layout' : { 'type': 'string' } 'build_stage': {
'oneOf': [
{'type': 'string'},
{'type': 'array',
'items': {'type': 'string'}}],
},
'source_cache': {'type': 'string'},
'misc_cache': {'type': 'string'},
'verify_ssl': {
'type': 'boolean',
'default': True,
},
'checksum': {
'type': 'boolean',
'default': True,
},
'dirty': {
'type': 'boolean',
'default': False,
},
} }
}, },
}, },

View File

@ -111,7 +111,7 @@
import spack import spack
import spack.architecture import spack.architecture
import spack.install_area import spack.store
import spack.compilers as compilers import spack.compilers as compilers
import spack.error import spack.error
import spack.parse import spack.parse
@ -965,7 +965,7 @@ def cshort_spec(self):
@property @property
def prefix(self): def prefix(self):
return Prefix(spack.install_area.layout.path_for_spec(self)) return Prefix(spack.store.layout.path_for_spec(self))
def dag_hash(self, length=None): def dag_hash(self, length=None):
"""Return a hash of the entire spec DAG, including connectivity.""" """Return a hash of the entire spec DAG, including connectivity."""
@ -2329,7 +2329,7 @@ def write(s, c):
elif named_str == 'SPACK_ROOT': elif named_str == 'SPACK_ROOT':
out.write(fmt % spack.prefix) out.write(fmt % spack.prefix)
elif named_str == 'SPACK_INSTALL': elif named_str == 'SPACK_INSTALL':
out.write(fmt % spack.install_area.path) out.write(fmt % spack.store.root)
elif named_str == 'PREFIX': elif named_str == 'PREFIX':
out.write(fmt % self.prefix) out.write(fmt % self.prefix)
elif named_str.startswith('HASH'): elif named_str.startswith('HASH'):
@ -2533,7 +2533,7 @@ def parse_compiler(self, text):
def spec_by_hash(self): def spec_by_hash(self):
self.expect(ID) self.expect(ID)
specs = spack.install_area.db.query() specs = spack.store.db.query()
matches = [spec for spec in specs if matches = [spec for spec in specs if
spec.dag_hash()[:len(self.token.value)] == self.token.value] spec.dag_hash()[:len(self.token.value)] == self.token.value]

75
lib/spack/spack/store.py Normal file
View File

@ -0,0 +1,75 @@
##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
"""Components that manage Spack's installation tree.
An install tree, or "build store" consists of two parts:
1. A package database that tracks what is installed.
2. A directory layout that determines how the installations
are laid out.
The store contains all the install prefixes for packages installed by
Spack. The simplest store could just contain prefixes named by DAG hash,
but we use a fancier directory layout to make browsing the store and
debugging easier.
The directory layout is currently hard-coded to be a YAMLDirectoryLayout,
so called because it stores build metadata within each prefix, in
`spec.yaml` files. In future versions of Spack we may consider allowing
install trees to define their own layouts with some per-tree
configuration.
"""
import os
import spack
import spack.config
from spack.util.path import canonicalize_path
from spack.database import Database
from spack.directory_layout import YamlDirectoryLayout
__author__ = "Benedikt Hegner (CERN)"
__all__ = ['db', 'layout', 'root']
#
# Read in the config
#
config = spack.config.get_config("config")
#
# Set up the install path
#
root = canonicalize_path(
config.get('install_tree', os.path.join(spack.opt_path, 'spack')))
#
# Set up the installed packages database
#
db = Database(root)
#
# This controls how spack lays out install prefixes and
# stage directories.
#
layout = YamlDirectoryLayout(root)

View File

@ -23,7 +23,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import spack.test.mock_database import spack.test.mock_database
import spack.install_area import spack.store
from spack.cmd.uninstall import uninstall from spack.cmd.uninstall import uninstall
@ -51,7 +51,7 @@ def test_uninstall(self):
args = MockArgs(['callpath'], all=True, dependents=True) args = MockArgs(['callpath'], all=True, dependents=True)
uninstall(parser, args) uninstall(parser, args)
all_specs = spack.install_area.layout.all_specs() all_specs = spack.store.layout.all_specs()
self.assertEqual(len(all_specs), 7) self.assertEqual(len(all_specs), 7)
# query specs with multiple configurations # query specs with multiple configurations
mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')] mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')]

View File

@ -30,7 +30,7 @@
import os.path import os.path
import spack import spack
import spack.install_area import spack.store
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
from spack.test.mock_database import MockDatabase from spack.test.mock_database import MockDatabase
@ -41,16 +41,16 @@ def _print_ref_counts():
recs = [] recs = []
def add_rec(spec): def add_rec(spec):
cspecs = spack.install_area.db.query(spec, installed=any) cspecs = spack.store.db.query(spec, installed=any)
if not cspecs: if not cspecs:
recs.append("[ %-7s ] %-20s-" % ('', spec)) recs.append("[ %-7s ] %-20s-" % ('', spec))
else: else:
key = cspecs[0].dag_hash() key = cspecs[0].dag_hash()
rec = spack.install_area.db.get_record(cspecs[0]) rec = spack.store.db.get_record(cspecs[0])
recs.append("[ %-7s ] %-20s%d" % (key[:7], spec, rec.ref_count)) recs.append("[ %-7s ] %-20s%d" % (key[:7], spec, rec.ref_count))
with spack.install_area.db.read_transaction(): with spack.store.db.read_transaction():
add_rec('mpileaks ^mpich') add_rec('mpileaks ^mpich')
add_rec('callpath ^mpich') add_rec('callpath ^mpich')
add_rec('mpich') add_rec('mpich')
@ -83,7 +83,7 @@ def test_005_db_exists(self):
def test_010_all_install_sanity(self): def test_010_all_install_sanity(self):
"""Ensure that the install layout reflects what we think it does.""" """Ensure that the install layout reflects what we think it does."""
all_specs = spack.install_area.layout.all_specs() all_specs = spack.store.layout.all_specs()
self.assertEqual(len(all_specs), 13) self.assertEqual(len(all_specs), 13)
# query specs with multiple configurations # query specs with multiple configurations
@ -114,12 +114,12 @@ def test_010_all_install_sanity(self):
def test_015_write_and_read(self): def test_015_write_and_read(self):
# write and read DB # write and read DB
with spack.install_area.db.write_transaction(): with spack.store.db.write_transaction():
specs = spack.install_area.db.query() specs = spack.store.db.query()
recs = [spack.install_area.db.get_record(s) for s in specs] recs = [spack.store.db.get_record(s) for s in specs]
for spec, rec in zip(specs, recs): for spec, rec in zip(specs, recs):
new_rec = spack.install_area.db.get_record(spec) new_rec = spack.store.db.get_record(spec)
self.assertEqual(new_rec.ref_count, rec.ref_count) self.assertEqual(new_rec.ref_count, rec.ref_count)
self.assertEqual(new_rec.spec, rec.spec) self.assertEqual(new_rec.spec, rec.spec)
self.assertEqual(new_rec.path, rec.path) self.assertEqual(new_rec.path, rec.path)
@ -127,7 +127,7 @@ def test_015_write_and_read(self):
def _check_merkleiness(self): def _check_merkleiness(self):
"""Ensure the spack database is a valid merkle graph.""" """Ensure the spack database is a valid merkle graph."""
all_specs = spack.install_area.db.query(installed=any) all_specs = spack.store.db.query(installed=any)
seen = {} seen = {}
for spec in all_specs: for spec in all_specs:
@ -140,7 +140,7 @@ def _check_merkleiness(self):
def _check_db_sanity(self): def _check_db_sanity(self):
"""Utiilty function to check db against install layout.""" """Utiilty function to check db against install layout."""
expected = sorted(spack.install_area.layout.all_specs()) expected = sorted(spack.store.layout.all_specs())
actual = sorted(self.install_db.query()) actual = sorted(self.install_db.query())
self.assertEqual(len(expected), len(actual)) self.assertEqual(len(expected), len(actual))
@ -155,7 +155,7 @@ def test_020_db_sanity(self):
def test_025_reindex(self): def test_025_reindex(self):
"""Make sure reindex works and ref counts are valid.""" """Make sure reindex works and ref counts are valid."""
spack.install_area.db.reindex(spack.install_area.layout) spack.store.db.reindex(spack.store.layout)
self._check_db_sanity() self._check_db_sanity()
def test_030_db_sanity_from_another_process(self): def test_030_db_sanity_from_another_process(self):
@ -179,7 +179,7 @@ def test_040_ref_counts(self):
def test_050_basic_query(self): def test_050_basic_query(self):
"""Ensure querying database is consistent with what is installed.""" """Ensure querying database is consistent with what is installed."""
# query everything # query everything
self.assertEqual(len(spack.install_area.db.query()), 13) self.assertEqual(len(spack.store.db.query()), 13)
# query specs with multiple configurations # query specs with multiple configurations
mpileaks_specs = self.install_db.query('mpileaks') mpileaks_specs = self.install_db.query('mpileaks')
@ -224,7 +224,7 @@ def _check_remove_and_add_package(self, spec):
self.assertTrue(concrete_spec not in remaining) self.assertTrue(concrete_spec not in remaining)
# add it back and make sure everything is ok. # add it back and make sure everything is ok.
self.install_db.add(concrete_spec, spack.install_area.layout) self.install_db.add(concrete_spec, spack.store.layout)
installed = self.install_db.query() installed = self.install_db.query()
self.assertTrue(concrete_spec in installed) self.assertTrue(concrete_spec in installed)
self.assertEqual(installed, original) self.assertEqual(installed, original)
@ -255,7 +255,7 @@ def test_080_root_ref_counts(self):
self.assertEqual(self.install_db.get_record('mpich').ref_count, 1) self.assertEqual(self.install_db.get_record('mpich').ref_count, 1)
# Put the spec back # Put the spec back
self.install_db.add(rec.spec, spack.install_area.layout) self.install_db.add(rec.spec, spack.store.layout)
# record is present again # record is present again
self.assertEqual( self.assertEqual(

View File

@ -26,7 +26,7 @@
import tempfile import tempfile
import spack import spack
import spack.install_area import spack.store
from llnl.util.filesystem import * from llnl.util.filesystem import *
from spack.directory_layout import YamlDirectoryLayout from spack.directory_layout import YamlDirectoryLayout
from spack.database import Database from spack.database import Database
@ -50,11 +50,11 @@ def setUp(self):
# Use a fake install directory to avoid conflicts bt/w # Use a fake install directory to avoid conflicts bt/w
# installed pkgs and mock packages. # installed pkgs and mock packages.
self.tmpdir = tempfile.mkdtemp() self.tmpdir = tempfile.mkdtemp()
self.orig_layout = spack.install_area.layout self.orig_layout = spack.store.layout
self.orig_db = spack.install_area.db self.orig_db = spack.store.db
spack.install_area.layout = YamlDirectoryLayout(self.tmpdir) spack.store.layout = YamlDirectoryLayout(self.tmpdir)
spack.install_area.db = Database(self.tmpdir) spack.store.db = Database(self.tmpdir)
def tearDown(self): def tearDown(self):
super(InstallTest, self).tearDown() super(InstallTest, self).tearDown()
@ -64,8 +64,8 @@ def tearDown(self):
spack.do_checksum = True spack.do_checksum = True
# restore spack's layout. # restore spack's layout.
spack.install_area.layout = self.orig_layout spack.store.layout = self.orig_layout
spack.install_area.db = self.orig_db spack.store.db = self.orig_db
shutil.rmtree(self.tmpdir, ignore_errors=True) shutil.rmtree(self.tmpdir, ignore_errors=True)
def fake_fetchify(self, pkg): def fake_fetchify(self, pkg):
@ -92,7 +92,7 @@ def test_install_and_uninstall(self):
pkg.remove_prefix() pkg.remove_prefix()
raise raise
def test_install_area(self): def test_store(self):
spec = Spec('cmake-client').concretized() spec = Spec('cmake-client').concretized()
for s in spec.traverse(): for s in spec.traverse():

View File

@ -26,7 +26,7 @@
import tempfile import tempfile
import spack import spack
import spack.install_area import spack.store
from spack.spec import Spec from spack.spec import Spec
from spack.database import Database from spack.database import Database
from spack.directory_layout import YamlDirectoryLayout from spack.directory_layout import YamlDirectoryLayout
@ -42,7 +42,7 @@ def _mock_install(self, spec):
pkg.do_install(fake=True) pkg.do_install(fake=True)
def _mock_remove(self, spec): def _mock_remove(self, spec):
specs = spack.install_area.db.query(spec) specs = spack.store.db.query(spec)
assert len(specs) == 1 assert len(specs) == 1
spec = specs[0] spec = specs[0]
spec.package.do_uninstall(spec) spec.package.do_uninstall(spec)
@ -55,17 +55,17 @@ def setUp(self):
# Make a fake install directory # Make a fake install directory
self.install_path = tempfile.mkdtemp() self.install_path = tempfile.mkdtemp()
self.spack_install_path = spack.install_area.path self.spack_install_path = spack.store.root
spack.install_area.path = self.install_path spack.store.root = self.install_path
self.install_layout = YamlDirectoryLayout(self.install_path) self.install_layout = YamlDirectoryLayout(self.install_path)
self.spack_install_layout = spack.install_area.layout self.spack_install_layout = spack.store.layout
spack.install_area.layout = self.install_layout spack.store.layout = self.install_layout
# Make fake database and fake install directory. # Make fake database and fake install directory.
self.install_db = Database(self.install_path) self.install_db = Database(self.install_path)
self.spack_install_db = spack.install_area.db self.spack_install_db = spack.store.db
spack.install_area.db = self.install_db spack.store.db = self.install_db
# make a mock database with some packages installed note that # make a mock database with some packages installed note that
# the ref count for dyninst here will be 3, as it's recycled # the ref count for dyninst here will be 3, as it's recycled
@ -91,18 +91,18 @@ def setUp(self):
# #
# Transaction used to avoid repeated writes. # Transaction used to avoid repeated writes.
with spack.install_area.db.write_transaction(): with spack.store.db.write_transaction():
self._mock_install('mpileaks ^mpich') self._mock_install('mpileaks ^mpich')
self._mock_install('mpileaks ^mpich2') self._mock_install('mpileaks ^mpich2')
self._mock_install('mpileaks ^zmpi') self._mock_install('mpileaks ^zmpi')
def tearDown(self): def tearDown(self):
with spack.install_area.db.write_transaction(): with spack.store.db.write_transaction():
for spec in spack.install_area.db.query(): for spec in spack.store.db.query():
spec.package.do_uninstall(spec) spec.package.do_uninstall(spec)
super(MockDatabase, self).tearDown() super(MockDatabase, self).tearDown()
shutil.rmtree(self.install_path) shutil.rmtree(self.install_path)
spack.install_area.path = self.spack_install_path spack.store.root = self.spack_install_path
spack.install_area.layout = self.spack_install_layout spack.store.layout = self.spack_install_layout
spack.install_area.db = self.spack_install_db spack.store.db = self.spack_install_db