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:
parent
a6a364d3b8
commit
a8e2961010
5 changed files with 21 additions and 6 deletions
|
@ -3,3 +3,4 @@ config:
|
||||||
concretizer: clingo
|
concretizer: clingo
|
||||||
build_stage::
|
build_stage::
|
||||||
- '$spack/.staging'
|
- '$spack/.staging'
|
||||||
|
stage_name: '{name}-{version}-{hash:7}'
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
from spack.filesystem_view import YamlFilesystemView
|
from spack.filesystem_view import YamlFilesystemView
|
||||||
from spack.install_test import TestFailure, TestSuite
|
from spack.install_test import TestFailure, TestSuite
|
||||||
from spack.installer import InstallError, PackageInstaller
|
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.executable import ProcessError, which
|
||||||
from spack.util.package_hash import package_hash
|
from spack.util.package_hash import package_hash
|
||||||
from spack.util.prefix import Prefix
|
from spack.util.prefix import Prefix
|
||||||
|
@ -1022,8 +1022,7 @@ def _make_root_stage(self, fetcher):
|
||||||
)
|
)
|
||||||
# Construct a path where the stage should build..
|
# Construct a path where the stage should build..
|
||||||
s = self.spec
|
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(
|
stage = Stage(
|
||||||
fetcher,
|
fetcher,
|
||||||
mirror_paths=mirror_paths,
|
mirror_paths=mirror_paths,
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
"build_stage": {
|
"build_stage": {
|
||||||
"oneOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]
|
"oneOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]
|
||||||
},
|
},
|
||||||
|
"stage_name": {"type": "string"},
|
||||||
"test_stage": {"type": "string"},
|
"test_stage": {"type": "string"},
|
||||||
"extensions": {"type": "array", "items": {"type": "string"}},
|
"extensions": {"type": "array", "items": {"type": "string"}},
|
||||||
"template_dirs": {"type": "array", "items": {"type": "string"}},
|
"template_dirs": {"type": "array", "items": {"type": "string"}},
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
import spack.fetch_strategy as fs
|
import spack.fetch_strategy as fs
|
||||||
import spack.mirror
|
import spack.mirror
|
||||||
import spack.paths
|
import spack.paths
|
||||||
|
import spack.spec
|
||||||
import spack.util.lock
|
import spack.util.lock
|
||||||
import spack.util.path as sup
|
import spack.util.path as sup
|
||||||
import spack.util.pattern as pattern
|
import spack.util.pattern as pattern
|
||||||
|
@ -49,6 +50,13 @@
|
||||||
stage_prefix = "spack-stage-"
|
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:
|
def create_stage_root(path: str) -> None:
|
||||||
"""Create the stage root directory and ensure appropriate access perms."""
|
"""Create the stage root directory and ensure appropriate access perms."""
|
||||||
assert os.path.isabs(path) and len(path.strip()) > 1
|
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.
|
# Ensure the path is unique per user.
|
||||||
can_path = sup.canonicalize_path(path)
|
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)
|
can_path = os.path.join(can_path, user)
|
||||||
|
|
||||||
paths.append(can_path)
|
paths.append(can_path)
|
||||||
|
|
|
@ -765,8 +765,11 @@ def test_resolve_paths(self):
|
||||||
|
|
||||||
# resolved path without user appends user
|
# resolved path without user appends user
|
||||||
paths = [os.path.join(os.path.sep, "a", "b", "c")]
|
paths = [os.path.join(os.path.sep, "a", "b", "c")]
|
||||||
|
can_paths = [paths[0]]
|
||||||
user = getpass.getuser()
|
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
|
assert spack.stage._resolve_paths(paths) == can_paths
|
||||||
|
|
||||||
# resolved path with node including user does not append user
|
# 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[1] = can_tempdir
|
||||||
res_paths[2] = os.path.join(can_tempdir, user)
|
res_paths[2] = os.path.join(can_tempdir, user)
|
||||||
res_paths[3] = os.path.join(can_tempdir, "stage", 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)
|
res_paths[0] = os.path.join(res_paths[0], user)
|
||||||
|
|
||||||
assert spack.stage._resolve_paths(paths) == res_paths
|
assert spack.stage._resolve_paths(paths) == res_paths
|
||||||
|
|
Loading…
Reference in a new issue