Install: Add use-buildcache option to install (#32537)
Install: Add use-buildcache option to install * Allow differentiating between top level packages and dependencies when determining whether to install from the cache or not. * Add unit test for --use-buildcache * Use metavar to display use-buildcache options. * Update spack-completion
This commit is contained in:
parent
7a25f416b8
commit
a01c36da45
4 changed files with 167 additions and 9 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import textwrap
|
||||
|
@ -31,10 +32,50 @@
|
|||
level = "short"
|
||||
|
||||
|
||||
# Pass in the value string passed to use-buildcache and get back
|
||||
# the package and dependencies values.
|
||||
def parse_use_buildcache(opt):
|
||||
bc_keys = ["package:", "dependencies:", ""]
|
||||
bc_values = ["only", "never", "auto"]
|
||||
kv_list = re.findall("([a-z]+:)?([a-z]+)", opt)
|
||||
|
||||
# Verify keys and values
|
||||
bc_map = {k: v for k, v in kv_list if k in bc_keys and v in bc_values}
|
||||
if not len(kv_list) == len(bc_map):
|
||||
tty.error("Unrecognized arguments passed to use-buildcache")
|
||||
tty.error(
|
||||
"Expected: --use-buildcache "
|
||||
"[[auto|only|never],[package:[auto|only|never]],[dependencies:[auto|only|never]]]"
|
||||
)
|
||||
exit(1)
|
||||
|
||||
for _group in ["package:", "dependencies:"]:
|
||||
if _group not in bc_map:
|
||||
if "" in bc_map:
|
||||
bc_map[_group] = bc_map[""]
|
||||
else:
|
||||
bc_map[_group] = "auto"
|
||||
|
||||
return bc_map["package:"], bc_map["dependencies:"]
|
||||
|
||||
|
||||
# Determine value of cache flag
|
||||
def cache_opt(default_opt, use_buildcache):
|
||||
if use_buildcache == "auto":
|
||||
return default_opt
|
||||
elif use_buildcache == "only":
|
||||
return True
|
||||
elif use_buildcache == "never":
|
||||
return False
|
||||
|
||||
|
||||
def install_kwargs_from_args(args):
|
||||
"""Translate command line arguments into a dictionary that will be passed
|
||||
to the package installer.
|
||||
"""
|
||||
|
||||
pkg_use_bc, dep_use_bc = parse_use_buildcache(args.use_buildcache)
|
||||
|
||||
return {
|
||||
"fail_fast": args.fail_fast,
|
||||
"keep_prefix": args.keep_prefix,
|
||||
|
@ -44,8 +85,10 @@ def install_kwargs_from_args(args):
|
|||
"verbose": args.verbose or args.install_verbose,
|
||||
"fake": args.fake,
|
||||
"dirty": args.dirty,
|
||||
"use_cache": args.use_cache,
|
||||
"cache_only": args.cache_only,
|
||||
"package_use_cache": cache_opt(args.use_cache, pkg_use_bc),
|
||||
"package_cache_only": cache_opt(args.cache_only, pkg_use_bc),
|
||||
"dependencies_use_cache": cache_opt(args.use_cache, dep_use_bc),
|
||||
"dependencies_cache_only": cache_opt(args.cache_only, dep_use_bc),
|
||||
"include_build_deps": args.include_build_deps,
|
||||
"explicit": True, # Use true as a default for install command
|
||||
"stop_at": args.until,
|
||||
|
@ -123,6 +166,18 @@ def setup_parser(subparser):
|
|||
default=False,
|
||||
help="only install package from binary mirrors",
|
||||
)
|
||||
cache_group.add_argument(
|
||||
"--use-buildcache",
|
||||
dest="use_buildcache",
|
||||
default="package:auto,dependencies:auto",
|
||||
metavar="[{auto,only,never},][package:{auto,only,never},][dependencies:{auto,only,never}]",
|
||||
help="""select the mode of buildcache for the 'package' and 'dependencies'.
|
||||
Default: package:auto,dependencies:auto
|
||||
- `auto` behaves like --use-cache
|
||||
- `only` behaves like --cache-only
|
||||
- `never` behaves like --no-cache
|
||||
""",
|
||||
)
|
||||
|
||||
subparser.add_argument(
|
||||
"--include-build-deps",
|
||||
|
|
|
@ -1182,12 +1182,12 @@ def _install_task(self, task):
|
|||
Args:
|
||||
task (BuildTask): the installation build task for a package"""
|
||||
|
||||
install_args = task.request.install_args
|
||||
cache_only = install_args.get("cache_only")
|
||||
explicit = task.explicit
|
||||
install_args = task.request.install_args
|
||||
cache_only = task.cache_only
|
||||
use_cache = task.use_cache
|
||||
tests = install_args.get("tests")
|
||||
unsigned = install_args.get("unsigned")
|
||||
use_cache = install_args.get("use_cache")
|
||||
|
||||
pkg, pkg_id = task.pkg, task.pkg_id
|
||||
|
||||
|
@ -2220,7 +2220,29 @@ def flag_installed(self, installed):
|
|||
@property
|
||||
def explicit(self):
|
||||
"""The package was explicitly requested by the user."""
|
||||
return self.pkg == self.request.pkg and self.request.install_args.get("explicit", True)
|
||||
return self.is_root and self.request.install_args.get("explicit", True)
|
||||
|
||||
@property
|
||||
def is_root(self):
|
||||
"""The package was requested directly, but may or may not be explicit
|
||||
in an environment."""
|
||||
return self.pkg == self.request.pkg
|
||||
|
||||
@property
|
||||
def use_cache(self):
|
||||
_use_cache = True
|
||||
if self.is_root:
|
||||
return self.request.install_args.get("package_use_cache", _use_cache)
|
||||
else:
|
||||
return self.request.install_args.get("dependencies_use_cache", _use_cache)
|
||||
|
||||
@property
|
||||
def cache_only(self):
|
||||
_cache_only = False
|
||||
if self.is_root:
|
||||
return self.request.install_args.get("package_cache_only", _cache_only)
|
||||
else:
|
||||
return self.request.install_args.get("dependencies_cache_only", _cache_only)
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
|
@ -2302,21 +2324,23 @@ def __str__(self):
|
|||
def _add_default_args(self):
|
||||
"""Ensure standard install options are set to at least the default."""
|
||||
for arg, default in [
|
||||
("cache_only", False),
|
||||
("context", "build"), # installs *always* build
|
||||
("dependencies_cache_only", False),
|
||||
("dependencies_use_cache", True),
|
||||
("dirty", False),
|
||||
("fail_fast", False),
|
||||
("fake", False),
|
||||
("install_deps", True),
|
||||
("install_package", True),
|
||||
("install_source", False),
|
||||
("package_cache_only", False),
|
||||
("package_use_cache", True),
|
||||
("keep_prefix", False),
|
||||
("keep_stage", False),
|
||||
("restage", False),
|
||||
("skip_patch", False),
|
||||
("tests", False),
|
||||
("unsigned", False),
|
||||
("use_cache", True),
|
||||
("verbose", False),
|
||||
]:
|
||||
_ = self.install_args.setdefault(arg, default)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import argparse
|
||||
import filecmp
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
@ -14,6 +15,7 @@
|
|||
from six.moves import builtins
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.cmd.install
|
||||
import spack.compilers as compilers
|
||||
|
@ -1090,3 +1092,80 @@ def test_install_callbacks_fail(install_mockery, mock_fetch, name, method):
|
|||
assert output.count(method) == 2
|
||||
assert output.count("method not implemented") == 1
|
||||
assert output.count("TestFailure: 1 tests failed") == 1
|
||||
|
||||
|
||||
def test_install_use_buildcache(
|
||||
capsys,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mock_binary_index,
|
||||
tmpdir,
|
||||
install_mockery_mutable_config,
|
||||
):
|
||||
"""
|
||||
Make sure installing with use-buildcache behaves correctly.
|
||||
"""
|
||||
|
||||
package_name = "dependent-install"
|
||||
dependency_name = "dependency-install"
|
||||
|
||||
def validate(mode, out, pkg):
|
||||
def assert_auto(pkg, out):
|
||||
assert "==> Extracting {0}".format(pkg) in out
|
||||
|
||||
def assert_only(pkg, out):
|
||||
assert "==> Extracting {0}".format(pkg) in out
|
||||
|
||||
def assert_never(pkg, out):
|
||||
assert "==> {0}: Executing phase: 'install'".format(pkg) in out
|
||||
|
||||
if mode == "auto":
|
||||
assert_auto(pkg, out)
|
||||
elif mode == "only":
|
||||
assert_only(pkg, out)
|
||||
else:
|
||||
assert_never(pkg, out)
|
||||
|
||||
def install_use_buildcache(opt):
|
||||
out = install(
|
||||
"--no-check-signature", "--use-buildcache", opt, package_name, fail_on_error=True
|
||||
)
|
||||
|
||||
pkg_opt, dep_opt = spack.cmd.install.parse_use_buildcache(opt)
|
||||
validate(dep_opt, out, dependency_name)
|
||||
validate(pkg_opt, out, package_name)
|
||||
|
||||
# Clean up installed packages
|
||||
uninstall("-y", "-a")
|
||||
|
||||
# Setup the mirror
|
||||
# Create a temp mirror directory for buildcache usage
|
||||
mirror_dir = tmpdir.join("mirror_dir")
|
||||
mirror_url = "file://{0}".format(mirror_dir.strpath)
|
||||
|
||||
# Populate the buildcache
|
||||
install(package_name)
|
||||
buildcache("create", "-u", "-a", "-f", "-d", mirror_dir.strpath, package_name, dependency_name)
|
||||
|
||||
# Uninstall the all of the packages for clean slate
|
||||
uninstall("-y", "-a")
|
||||
|
||||
# Configure the mirror where we put that buildcache w/ the compiler
|
||||
mirror("add", "test-mirror", mirror_url)
|
||||
|
||||
with capsys.disabled():
|
||||
# Install using the matrix of possible combinations with --use-buildcache
|
||||
for pkg, deps in itertools.product(["auto", "only", "never"], repeat=2):
|
||||
tty.debug(
|
||||
"Testing `spack install --use-buildcache package:{0},dependencies:{1}`".format(
|
||||
pkg, deps
|
||||
)
|
||||
)
|
||||
install_use_buildcache("package:{0},dependencies:{1}".format(pkg, deps))
|
||||
install_use_buildcache("dependencies:{0},package:{1}".format(deps, pkg))
|
||||
|
||||
# Install using a default override option
|
||||
# Alternative to --cache-only (always) or --no-cache (never)
|
||||
for opt in ["auto", "only", "never"]:
|
||||
install_use_buildcache(opt)
|
||||
|
|
|
@ -1188,7 +1188,7 @@ _spack_info() {
|
|||
_spack_install() {
|
||||
if $list_options
|
||||
then
|
||||
SPACK_COMPREPLY="-h --help --only -u --until -j --jobs --overwrite --fail-fast --keep-prefix --keep-stage --dont-restage --use-cache --no-cache --cache-only --include-build-deps --no-check-signature --show-log-on-error --source -n --no-checksum --deprecated -v --verbose --fake --only-concrete --no-add -f --file --clean --dirty --test --log-format --log-file --help-cdash --cdash-upload-url --cdash-build --cdash-site --cdash-track --cdash-buildstamp -y --yes-to-all -U --fresh --reuse"
|
||||
SPACK_COMPREPLY="-h --help --only -u --until -j --jobs --overwrite --fail-fast --keep-prefix --keep-stage --dont-restage --use-cache --no-cache --cache-only --use-buildcache --include-build-deps --no-check-signature --show-log-on-error --source -n --no-checksum --deprecated -v --verbose --fake --only-concrete --no-add -f --file --clean --dirty --test --log-format --log-file --help-cdash --cdash-upload-url --cdash-build --cdash-site --cdash-track --cdash-buildstamp -y --yes-to-all -U --fresh --reuse"
|
||||
else
|
||||
_all_packages
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue