diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py index d5b9320c8bd..14d7ddf7f08 100644 --- a/lib/spack/spack/package_base.py +++ b/lib/spack/spack/package_base.py @@ -31,6 +31,7 @@ import llnl.util.tty as tty from llnl.util.lang import classproperty, memoized +import spack import spack.compilers import spack.config import spack.dependency @@ -60,6 +61,7 @@ from spack.util.package_hash import package_hash from spack.util.typing import SupportsRichComparison from spack.version import GitVersion, StandardVersion +from spack.version import ver as version_from_str FLAG_HANDLER_RETURN_TYPE = Tuple[ Optional[Iterable[str]], Optional[Iterable[str]], Optional[Iterable[str]] @@ -731,10 +733,22 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta): #: TestSuite instance used to manage stand-alone tests for 1+ specs. test_suite: Optional[Any] = None + #: compatibility requirements with Spack + #: if value is ``None``, requirements from repo are still applied + required_spack_version = None + def __init__(self, spec): # this determines how the package should be built. self.spec: spack.spec.Spec = spec + # is this package more restrictive in compatibility than the repo is + if self.required_spack_version: + spack_version = version_from_str(spack.spack_version) + required_version = version_from_str(self.required_spack_version) + if not spack_version.satisfies(required_version): + msg = f"Package {self.name} requires Spack version {self.required_spack_version}." + raise PackageError(msg) + # Allow custom staging paths for packages self.path = None diff --git a/lib/spack/spack/repo.py b/lib/spack/spack/repo.py index e4a945f0bfe..c7feade124f 100644 --- a/lib/spack/spack/repo.py +++ b/lib/spack/spack/repo.py @@ -32,6 +32,7 @@ import llnl.util.tty as tty from llnl.util.filesystem import working_dir +import spack import spack.caches import spack.config import spack.error @@ -40,6 +41,7 @@ import spack.spec import spack.tag import spack.tengine +import spack.version import spack.util.file_cache import spack.util.git import spack.util.naming as nm @@ -49,6 +51,11 @@ #: Package modules are imported as spack.pkg.. ROOT_PYTHON_NAMESPACE = "spack.pkg" +_required_repo_version = "0:" + +#: Version of the repo interface that this version of Spack is compatible with +required_repo_version = spack.version.ver(_required_repo_version) + def python_package_for_repo(namespace): """Returns the full namespace of a repository, given its relative one @@ -951,7 +958,7 @@ def check(condition, msg): self.config_file = os.path.join(self.root, repo_config_name) check(os.path.isfile(self.config_file), f"No {repo_config_name} found in '{root}'") - # Read configuration and validate namespace + # Read configuration and validate config = self._read_config() check( "namespace" in config, @@ -965,6 +972,19 @@ def check(condition, msg): "Namespaces must be valid python identifiers separated by '.'", ) + required_version = spack.version.ver(config.get("required_spack_version", ":")) + spack_version = spack.version.ver(spack.spack_version) + check( + spack_version.satisfies(required_version), + f"Repo {self.namespace} requires Spack version {required_version}", + ) + + repo_version = spack.version.ver(config.get("version", "0")) + check( + repo_version.satisfies(required_repo_version), + f"Spack requires repo version {required_repo_version}", + ) + # Set up 'full_namespace' to include the super-namespace self.full_namespace = python_package_for_repo(self.namespace) diff --git a/var/spack/repos/builtin.mock/repo.yaml b/var/spack/repos/builtin.mock/repo.yaml index 30b068da13d..9382e74ce0e 100644 --- a/var/spack/repos/builtin.mock/repo.yaml +++ b/var/spack/repos/builtin.mock/repo.yaml @@ -1,2 +1,4 @@ repo: namespace: builtin.mock + version: 0 + required_spack_version: '0.23:1.0.0.dev0' diff --git a/var/spack/repos/builtin/repo.yaml b/var/spack/repos/builtin/repo.yaml index 54b282db6be..103f646f2da 100644 --- a/var/spack/repos/builtin/repo.yaml +++ b/var/spack/repos/builtin/repo.yaml @@ -1,2 +1,4 @@ repo: namespace: builtin + version: 0 + required_spack_version: '0.23:1.0.0.dev0'