repo compat: initial draft

This commit is contained in:
Gregory Becker 2025-02-10 15:08:51 -08:00
parent 2c3f2c5733
commit d8baa193b3
4 changed files with 39 additions and 1 deletions

View File

@ -31,6 +31,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import classproperty, memoized from llnl.util.lang import classproperty, memoized
import spack
import spack.compilers import spack.compilers
import spack.config import spack.config
import spack.dependency import spack.dependency
@ -60,6 +61,7 @@
from spack.util.package_hash import package_hash from spack.util.package_hash import package_hash
from spack.util.typing import SupportsRichComparison from spack.util.typing import SupportsRichComparison
from spack.version import GitVersion, StandardVersion from spack.version import GitVersion, StandardVersion
from spack.version import ver as version_from_str
FLAG_HANDLER_RETURN_TYPE = Tuple[ FLAG_HANDLER_RETURN_TYPE = Tuple[
Optional[Iterable[str]], Optional[Iterable[str]], Optional[Iterable[str]] 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. #: TestSuite instance used to manage stand-alone tests for 1+ specs.
test_suite: Optional[Any] = None 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): def __init__(self, spec):
# this determines how the package should be built. # this determines how the package should be built.
self.spec: spack.spec.Spec = spec 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 # Allow custom staging paths for packages
self.path = None self.path = None

View File

@ -32,6 +32,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack
import spack.caches import spack.caches
import spack.config import spack.config
import spack.error import spack.error
@ -40,6 +41,7 @@
import spack.spec import spack.spec
import spack.tag import spack.tag
import spack.tengine import spack.tengine
import spack.version
import spack.util.file_cache import spack.util.file_cache
import spack.util.git import spack.util.git
import spack.util.naming as nm import spack.util.naming as nm
@ -49,6 +51,11 @@
#: Package modules are imported as spack.pkg.<repo-namespace>.<pkg-name> #: Package modules are imported as spack.pkg.<repo-namespace>.<pkg-name>
ROOT_PYTHON_NAMESPACE = "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): def python_package_for_repo(namespace):
"""Returns the full namespace of a repository, given its relative one """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) 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}'") 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() config = self._read_config()
check( check(
"namespace" in config, "namespace" in config,
@ -965,6 +972,19 @@ def check(condition, msg):
"Namespaces must be valid python identifiers separated by '.'", "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 # Set up 'full_namespace' to include the super-namespace
self.full_namespace = python_package_for_repo(self.namespace) self.full_namespace = python_package_for_repo(self.namespace)

View File

@ -1,2 +1,4 @@
repo: repo:
namespace: builtin.mock namespace: builtin.mock
version: 0
required_spack_version: '0.23:1.0.0.dev0'

View File

@ -1,2 +1,4 @@
repo: repo:
namespace: builtin namespace: builtin
version: 0
required_spack_version: '0.23:1.0.0.dev0'