diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py index a02c73f7cc6..d70fb6ed98d 100644 --- a/lib/spack/spack/package_base.py +++ b/lib/spack/spack/package_base.py @@ -1012,7 +1012,7 @@ def needs_commit(cls, version) -> bool: ver_attrs = cls.versions.get(version) if ver_attrs: - return bool(ver_attrs.get("tag") or ver_attrs.get("branch")) + return bool(ver_attrs.get("commit") or ver_attrs.get("tag") or ver_attrs.get("branch")) return False diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index e9f90ed1136..25653c9f86b 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1596,9 +1596,11 @@ def key_fn(version): ), ) ) - if pkg.needs_commit(declared_version.version): - commit = pkg.version_or_package_attr("commit", declared_version.version, "") - self.git_commit_versions[pkg.name][declared_version.version] = commit + + for v in self.possible_versions[pkg.name]: + if pkg.needs_commit(v): + commit = pkg.version_or_package_attr("commit", v, "") + self.git_commit_versions[pkg.name][v] = commit # Declare deprecated versions for this package, if any deprecated = self.deprecated_versions[pkg.name] @@ -2908,10 +2910,11 @@ def define_version_constraints(self): for v in versions: if v in self.git_commit_versions[pkg_name]: sha = self.git_commit_versions[pkg_name].get(v) - self.gen.fact(fn.pkg_fact(pkg_name, fn.version_needs_commit(v))) if sha: self.gen.fact(fn.pkg_fact(pkg_name, fn.version_has_commit(v, sha))) - self.gen.newline() + else: + self.gen.fact(fn.pkg_fact(pkg_name, fn.version_needs_commit(v))) + self.gen.newline() for pkg_name, versions in sorted(self.version_constraints): # generate facts for each package constraint and the version @@ -3109,8 +3112,18 @@ def setup( commit = spec.variants.get("commit") version = spec.versions.concrete_range_as_version if not version and commit: - version = max(spack.repo.PATH.get_pkg_class(spec.fullname).versions.keys()) - spec.versions = spack.version.VersionList([version]) + # look for a matching commit in versions otherwise default to max infinity version + versions = spack.repo.PATH.get_pkg_class(spec.fullname).versions + match = None + for v, data in versions.items(): + if data.get("commit") == commit.value[0]: + match = v + break + if match: + spec.versions = spack.version.VersionList([match]) + else: + version = max(versions.keys()) + spec.versions = spack.version.VersionList([version]) self.gen = ProblemInstanceBuilder() diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index 0906a7e4cc4..0f2b7a94f16 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -333,20 +333,26 @@ attr("node_version_satisfies", node(ID, Package), Constraint) :- attr("version", node(ID, Package), Version), pkg_fact(Package, version_satisfies(Constraint, Version)). +% if a version needs a commit or has one it can use the commit variant +can_accept_commit(Package, Version) :- pkg_fact(Package, version_needs_commit(Version)). +can_accept_commit(Package, Version) :- pkg_fact(Package, version_has_commit(Version, _)). + % Specs with a commit variant can't use versions that don't need commits -error(10, "Cannot use commit variant with '{0}@{1}'", Package, Version) +error(10, "Cannot use commit variant with '{0}@={1}'", Package, Version) :- attr("version", node(ID, Package), Version), - not pkg_fact(Package, version_needs_commit(Version)), + not can_accept_commit(Package, Version), attr("variant_value", node(ID, Package), "commit", _). -% Versions with commits require a matching commit variant - :- attr("version", node(ID, Packate), Version), - pkg_fact(Package, version_has_commit(Version, Sha)), - not attr("variant_value", node(ID, Package), "commit", Sha). +error(10, "Commit '{0}' must match package.py value '{1}' for '{2}@={3}'", Vsha, Psha, Package, Version) + :- attr("version", node(ID, Package), Version), + attr("variant_value", node(ID, Package), "commit", Vsha), + pkg_fact(Package, version_has_commit(Version, Psha)), + Vsha != Psha. #defined version_satisfies/3. #defined deprecated_versions_not_allowed/0. #defined deprecated_version/2. +#defined can_accept_commit/2. %----------------------------------------------------------------------------- % Spec conditions and imposed constraints diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index fe7526ae96d..ce2542df669 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -2673,7 +2673,7 @@ def name_and_dependency_types(s: str) -> Tuple[str, dt.DepFlag]: return name, depflag def spec_and_dependency_types( - s: Union[Spec, Tuple[Spec, str]], + s: Union[Spec, Tuple[Spec, str]] ) -> Tuple[Spec, dt.DepFlag]: """Given a non-string key in the literal, extracts the spec and its dependency types.