Spec.constrain: separate constraints from edges with different conditions

Signed-off-by: Gregory Becker <becker33@llnl.gov>
This commit is contained in:
Gregory Becker 2025-05-12 14:16:03 -07:00
parent fb6ffc45d7
commit 7472a1db8a
No known key found for this signature in database
GPG Key ID: 2362541F6D14ED84

View File

@ -3177,42 +3177,22 @@ def _constrain_dependencies(self, other: "Spec") -> bool:
if any(not d.name for d in other.traverse(root=False)): if any(not d.name for d in other.traverse(root=False)):
raise UnconstrainableDependencySpecError(other) raise UnconstrainableDependencySpecError(other)
# Handle common first-order constraints directly reference_spec = self.copy(deps=True)
# Note: This doesn't handle constraining transitive dependencies with the same name for edge in other.edges_to_dependencies():
# as direct dependencies existing = self.edges_to_dependencies(edge.spec.name, when=edge.when)
changed = False if existing:
common_dependencies = {x.name for x in self.dependencies()} existing[0].spec.constrain(edge.spec)
common_dependencies &= {x.name for x in other.dependencies()} existing[0].update_deptypes(edge.depflag)
for name in common_dependencies: existing[0].update_virtuals(edge.virtuals)
changed |= self[name].constrain(other[name], deps=True) else:
if name in self._dependencies: self.add_dependency_edge(
# WARNING: This function is an implementation detail of the edge.spec,
# WARNING: original concretizer. Since with that greedy depflag=edge.depflag,
# WARNING: algorithm we don't allow multiple nodes from virtuals=edge.virtuals,
# WARNING: the same package in a DAG, here we hard-code direct=edge.direct,
# WARNING: using index 0 i.e. we assume that we have only when=edge.when,
# WARNING: one edge from package "name"
edges_from_name = self._dependencies[name]
changed |= edges_from_name[0].update_deptypes(other._dependencies[name][0].depflag)
changed |= edges_from_name[0].update_virtuals(
other._dependencies[name][0].virtuals
) )
return self != reference_spec
# Update with additional constraints from other spec
# operate on direct dependencies only, because a concrete dep
# represented by hash may have structure that needs to be preserved
for name in other.direct_dep_difference(self):
dep_spec_copy = other._get_dependency(name)
self._add_dependency(
dep_spec_copy.spec.copy(),
depflag=dep_spec_copy.depflag,
virtuals=dep_spec_copy.virtuals,
direct=dep_spec_copy.direct,
when=dep_spec_copy.when,
)
changed = True
return changed
def common_dependencies(self, other): def common_dependencies(self, other):
"""Return names of dependencies that self and other have in common.""" """Return names of dependencies that self and other have in common."""