@@ -455,11 +455,16 @@ error(1, Msg)
455455
456456% if a package depends on a virtual, it's not external and we have a
457457% provider for that virtual then it depends on the provider
458- 1 { attr("depends_on", PackageNode, ProviderNode , Type) : provider(ProviderNode, node(VirtualID, Virtual)) } 1
458+ node_depends_on_virtual( PackageNode, Virtual , Type)
459459 :- dependency_holds(PackageNode, Virtual, Type),
460460 virtual(Virtual),
461461 not external(PackageNode).
462462
463+ node_depends_on_virtual(PackageNode, Virtual) :- node_depends_on_virtual(PackageNode, Virtual, Type).
464+
465+ 1 { attr("depends_on", PackageNode, ProviderNode, Type) : provider(ProviderNode, node(VirtualID, Virtual)) } 1
466+ :- node_depends_on_virtual(PackageNode, Virtual, Type).
467+
463468attr("virtual_on_edge", PackageNode, ProviderNode, Virtual)
464469 :- dependency_holds(PackageNode, Virtual, Type),
465470 attr("depends_on", PackageNode, ProviderNode, Type),
@@ -468,9 +473,7 @@ attr("virtual_on_edge", PackageNode, ProviderNode, Virtual)
468473
469474% dependencies on virtuals also imply that the virtual is a virtual node
4704751 { attr("virtual_node", node(0..X-1, Virtual)) : max_dupes(Virtual, X) }
471- :- dependency_holds(PackageNode, Virtual, Type),
472- virtual(Virtual),
473- not external(PackageNode).
476+ :- node_depends_on_virtual(PackageNode, Virtual).
474477
475478% If there's a virtual node, we must select one and only one provider.
476479% The provider must be selected among the possible providers.
@@ -490,13 +493,24 @@ attr("virtual_node", VirtualNode) :- attr("virtual_root", VirtualNode).
490493% then the provider is the root package.
491494attr("root", PackageNode) :- attr("virtual_root", VirtualNode), provider(PackageNode, VirtualNode).
492495
493- % If we asked for a root package and that root provides a virtual,
494- % the root is a provider for that virtual. This rule is mostly relevant
495- % for environments that are concretized together (e.g. where we
496- % asks to install "mpich" and "hdf5+mpi" and we want "mpich" to
497- % be the mpi provider)
498- 1 { provider(PackageNode, node(0..X-1, Virtual)) : max_dupes(Virtual, X) } 1 :- attr("node", PackageNode), virtual_condition_holds(PackageNode, Virtual).
499- :- 2 { provider(PackageNode, VirtualNode) }, attr("virtual_node", VirtualNode).
496+ % The provider is selected among the nodes for which the virtual condition holds
497+ 1 { provider(PackageNode, node(X, Virtual)) :
498+ attr("node", PackageNode), virtual_condition_holds(PackageNode, Virtual) } 1
499+ :- attr("virtual_node", node(X, Virtual)).
500+
501+ % If a spec is selected as a provider, it is for all the virtual it could provide
502+ :- provider(PackageNode, node(X, Virtual1)),
503+ virtual_condition_holds(PackageNode, Virtual2),
504+ Virtual2 != Virtual1,
505+ unification_set(SetID, PackageNode),
506+ unification_set(SetID, node(X, Virtual2)),
507+ not provider(PackageNode, node(X, Virtual2)).
508+
509+ % If a spec is a dependency, and could provide a needed virtual, it must be a provider
510+ :- node_depends_on_virtual(PackageNode, Virtual),
511+ depends_on(PackageNode, PossibleProviderNode),
512+ virtual_condition_holds(PossibleProviderNode, Virtual),
513+ not attr("virtual_on_edge", PackageNode, PossibleProviderNode, Virtual).
500514
501515% The provider provides the virtual if some provider condition holds.
502516virtual_condition_holds(node(ProviderID, Provider), Virtual) :- virtual_condition_holds(ID, node(ProviderID, Provider), Virtual).
0 commit comments