From e2744fafa16749a1b2c9d8cb5bf5e1c885ba841b Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 3 Nov 2021 16:07:20 +0100 Subject: spack concretize: add --reuse argument --- lib/spack/spack/cmd/concretize.py | 6 +++++- lib/spack/spack/concretize.py | 13 +++++++++++-- lib/spack/spack/environment/environment.py | 26 +++++++++++++++----------- lib/spack/spack/spec.py | 6 ++++-- share/spack/spack-completion.bash | 2 +- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/spack/spack/cmd/concretize.py b/lib/spack/spack/cmd/concretize.py index 433236b238..be966d84a8 100644 --- a/lib/spack/spack/cmd/concretize.py +++ b/lib/spack/spack/cmd/concretize.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import spack.cmd +import spack.cmd.common.arguments import spack.environment as ev description = 'concretize an environment and write a lockfile' @@ -12,6 +13,7 @@ level = "long" def setup_parser(subparser): + spack.cmd.common.arguments.add_common_arguments(subparser, ['reuse']) subparser.add_argument( '-f', '--force', action='store_true', help="Re-concretize even if already concretized.") @@ -34,6 +36,8 @@ def concretize(parser, args): tests = False with env.write_transaction(): - concretized_specs = env.concretize(force=args.force, tests=tests) + concretized_specs = env.concretize( + force=args.force, tests=tests, reuse=args.reuse + ) ev.display_specs(concretized_specs) env.write() diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py index aed8fe7713..f3572cfdcf 100644 --- a/lib/spack/spack/concretize.py +++ b/lib/spack/spack/concretize.py @@ -732,7 +732,11 @@ def concretize_specs_together(*abstract_specs, **kwargs): def _concretize_specs_together_new(*abstract_specs, **kwargs): import spack.solver.asp - result = spack.solver.asp.solve(abstract_specs) + concretization_kwargs = { + 'tests': kwargs.get('tests', False), + 'reuse': kwargs.get('reuse', False) + } + result = spack.solver.asp.solve(abstract_specs, **concretization_kwargs) result.raise_if_unsat() return [s.copy() for s in result.specs] @@ -768,10 +772,15 @@ def _concretize_specs_together_original(*abstract_specs, **kwargs): abstract_specs = [spack.spec.Spec(s) for s in abstract_specs] concretization_repository = make_concretization_repository(abstract_specs) + concretization_kwargs = { + 'tests': kwargs.get('tests', False), + 'reuse': kwargs.get('reuse', False) + } + with spack.repo.additional_repository(concretization_repository): # Spec from a helper package that depends on all the abstract_specs concretization_root = spack.spec.Spec('concretizationroot') - concretization_root.concretize(tests=kwargs.get('tests', False)) + concretization_root.concretize(**concretization_kwargs) # Retrieve the direct dependencies concrete_specs = [ concretization_root[spec.name].copy() for spec in abstract_specs diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py index 4ed3d2508e..a6be5d1c50 100644 --- a/lib/spack/spack/environment/environment.py +++ b/lib/spack/spack/environment/environment.py @@ -1035,7 +1035,7 @@ class Environment(object): """Returns true when the spec is built from local sources""" return spec.name in self.dev_specs - def concretize(self, force=False, tests=False): + def concretize(self, force=False, tests=False, reuse=False): """Concretize user_specs in this environment. Only concretizes specs that haven't been concretized yet unless @@ -1049,6 +1049,8 @@ class Environment(object): already concretized tests (bool or list or set): False to run no tests, True to test all packages, or a list of package names to run tests for some + reuse (bool): if True try to maximize reuse of already installed + specs, if False don't account for installation status. Returns: List of specs that have been concretized. Each entry is a tuple of @@ -1062,14 +1064,15 @@ class Environment(object): # Pick the right concretization strategy if self.concretization == 'together': - return self._concretize_together(tests=tests) + return self._concretize_together(tests=tests, reuse=reuse) + if self.concretization == 'separately': - return self._concretize_separately(tests=tests) + return self._concretize_separately(tests=tests, reuse=reuse) msg = 'concretization strategy not implemented [{0}]' raise SpackEnvironmentError(msg.format(self.concretization)) - def _concretize_together(self, tests=False): + def _concretize_together(self, tests=False, reuse=False): """Concretization strategy that concretizes all the specs in the same DAG. """ @@ -1102,13 +1105,14 @@ class Environment(object): self.specs_by_hash = {} concrete_specs = spack.concretize.concretize_specs_together( - *self.user_specs, tests=tests) + *self.user_specs, tests=tests, reuse=reuse + ) concretized_specs = [x for x in zip(self.user_specs, concrete_specs)] for abstract, concrete in concretized_specs: self._add_concrete_spec(abstract, concrete) return concretized_specs - def _concretize_separately(self, tests=False): + def _concretize_separately(self, tests=False, reuse=False): """Concretization strategy that concretizes separately one user spec after the other. """ @@ -1133,7 +1137,7 @@ class Environment(object): ): if uspec not in old_concretized_user_specs: root_specs.append(uspec) - arguments.append((uspec_constraints, tests)) + arguments.append((uspec_constraints, tests, reuse)) # Ensure we don't try to bootstrap clingo in parallel if spack.config.get('config:concretizer') == 'clingo': @@ -1988,7 +1992,7 @@ def display_specs(concretized_specs): print('') -def _concretize_from_constraints(spec_constraints, tests=False): +def _concretize_from_constraints(spec_constraints, tests=False, reuse=False): # Accept only valid constraints from list and concretize spec # Get the named spec even if out of order root_spec = [s for s in spec_constraints if s.name] @@ -2007,7 +2011,7 @@ def _concretize_from_constraints(spec_constraints, tests=False): if c not in invalid_constraints: s.constrain(c) try: - return s.concretized(tests=tests) + return s.concretized(tests=tests, reuse=reuse) except spack.spec.InvalidDependencyError as e: invalid_deps_string = ['^' + d for d in e.invalid_deps] invalid_deps = [c for c in spec_constraints @@ -2027,9 +2031,9 @@ def _concretize_from_constraints(spec_constraints, tests=False): def _concretize_task(packed_arguments): - spec_constraints, tests = packed_arguments + spec_constraints, tests, reuse = packed_arguments with tty.SuppressOutput(msg_enabled=False): - return _concretize_from_constraints(spec_constraints, tests) + return _concretize_from_constraints(spec_constraints, tests, reuse) def make_repo_path(root): diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 7268142537..eaf7544e83 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -2666,7 +2666,7 @@ class Spec(object): s.clear_cached_hashes() s._mark_root_concrete(value) - def concretized(self, tests=False): + def concretized(self, tests=False, reuse=False): """This is a non-destructive version of concretize(). First clones, then returns a concrete version of this package @@ -2676,9 +2676,11 @@ class Spec(object): tests (bool or list): if False disregard 'test' dependencies, if a list of names activate them for the packages in the list, if True activate 'test' dependencies for all packages. + reuse (bool): if True try to maximize reuse of already installed + specs, if False don't account for installation status. """ clone = self.copy(caches=True) - clone.concretize(tests=tests) + clone.concretize(tests=tests, reuse=reuse) return clone def flat_dependencies(self, **kwargs): diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index 38589ed3ea..231187213c 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -705,7 +705,7 @@ _spack_compilers() { } _spack_concretize() { - SPACK_COMPREPLY="-h --help -f --force --test" + SPACK_COMPREPLY="-h --help --reuse -f --force --test" } _spack_config() { -- cgit v1.2.3-70-g09d2