Allow configurable stage names (#36509)

Add `config:stage_name` which is a Spec format string that can
customize the names of stages created by Spack. This was primarily
created to allow generating shorter stage names on Windows (along
with `config:build_stage`, this can be used to create stages with
short absolute paths).

By default, this is not set and the prior name stage format is used.

This also removes the username component that is always added to
Stage paths on Windows (if users want to include this, they can
add it to the `build_stage`).
This commit is contained in:
John W. Parent 2023-03-31 14:46:47 -04:00 committed by GitHub
parent a6a364d3b8
commit a8e2961010
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 6 deletions

View file

@ -3,3 +3,4 @@ config:
concretizer: clingo
build_stage::
- '$spack/.staging'
stage_name: '{name}-{version}-{hash:7}'

View file

@ -57,7 +57,7 @@
from spack.filesystem_view import YamlFilesystemView
from spack.install_test import TestFailure, TestSuite
from spack.installer import InstallError, PackageInstaller
from spack.stage import ResourceStage, Stage, StageComposite, stage_prefix
from spack.stage import ResourceStage, Stage, StageComposite, compute_stage_name
from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash
from spack.util.prefix import Prefix
@ -1022,8 +1022,7 @@ def _make_root_stage(self, fetcher):
)
# Construct a path where the stage should build..
s = self.spec
stage_name = "{0}{1}-{2}-{3}".format(stage_prefix, s.name, s.version, s.dag_hash())
stage_name = compute_stage_name(s)
stage = Stage(
fetcher,
mirror_paths=mirror_paths,

View file

@ -61,6 +61,7 @@
"build_stage": {
"oneOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]
},
"stage_name": {"type": "string"},
"test_stage": {"type": "string"},
"extensions": {"type": "array", "items": {"type": "string"}},
"template_dirs": {"type": "array", "items": {"type": "string"}},

View file

@ -35,6 +35,7 @@
import spack.fetch_strategy as fs
import spack.mirror
import spack.paths
import spack.spec
import spack.util.lock
import spack.util.path as sup
import spack.util.pattern as pattern
@ -49,6 +50,13 @@
stage_prefix = "spack-stage-"
def compute_stage_name(spec):
"""Determine stage name given a spec"""
default_stage_structure = "spack-stage-{name}-{version}-{hash}"
stage_name_structure = spack.config.get("config:stage_name", default=default_stage_structure)
return spec.format(format_string=stage_name_structure)
def create_stage_root(path: str) -> None:
"""Create the stage root directory and ensure appropriate access perms."""
assert os.path.isabs(path) and len(path.strip()) > 1
@ -150,7 +158,10 @@ def _resolve_paths(candidates):
# Ensure the path is unique per user.
can_path = sup.canonicalize_path(path)
if user not in can_path:
# When multiple users share a stage root, we can avoid conflicts between
# them by adding a per-user subdirectory.
# Avoid doing this on Windows to keep stage absolute path as short as possible.
if user not in can_path and not sys.platform == "win32":
can_path = os.path.join(can_path, user)
paths.append(can_path)

View file

@ -765,8 +765,11 @@ def test_resolve_paths(self):
# resolved path without user appends user
paths = [os.path.join(os.path.sep, "a", "b", "c")]
can_paths = [paths[0]]
user = getpass.getuser()
can_paths = [os.path.join(paths[0], user)]
if sys.platform != "win32":
can_paths = [os.path.join(paths[0], user)]
assert spack.stage._resolve_paths(paths) == can_paths
# resolved path with node including user does not append user
@ -789,7 +792,7 @@ def test_resolve_paths(self):
res_paths[1] = can_tempdir
res_paths[2] = os.path.join(can_tempdir, user)
res_paths[3] = os.path.join(can_tempdir, "stage", user)
else:
elif sys.platform != "win32":
res_paths[0] = os.path.join(res_paths[0], user)
assert spack.stage._resolve_paths(paths) == res_paths