Spec.satisfies: fix a bug with concrete spec from JSON (#43968)
Fix a bug triggered by missing a virtual on some transitive edge, in a subdag of a pure build dependency.
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							cc85dc05b7
						
					
				
				
					commit
					89bf1edb6e
				
			@@ -3898,9 +3898,13 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
 | 
				
			|||||||
        if not self._dependencies:
 | 
					        if not self._dependencies:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # If we arrived here, then rhs is abstract. At the moment we don't care about the edge
 | 
					        # If we arrived here, the lhs root node satisfies the rhs root node. Now we need to check
 | 
				
			||||||
        # structure of an abstract DAG, so we check if any edge could satisfy the properties
 | 
					        # all the edges that have an abstract parent, and verify that they match some edge in the
 | 
				
			||||||
        # we ask for.
 | 
					        # lhs.
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # It might happen that the rhs brings in concrete sub-DAGs. For those we don't need to
 | 
				
			||||||
 | 
					        # verify the edge properties, cause everything is encoded in the hash of the nodes that
 | 
				
			||||||
 | 
					        # will be verified later.
 | 
				
			||||||
        lhs_edges: Dict[str, Set[DependencySpec]] = collections.defaultdict(set)
 | 
					        lhs_edges: Dict[str, Set[DependencySpec]] = collections.defaultdict(set)
 | 
				
			||||||
        for rhs_edge in other.traverse_edges(root=False, cover="edges"):
 | 
					        for rhs_edge in other.traverse_edges(root=False, cover="edges"):
 | 
				
			||||||
            # If we are checking for ^mpi we need to verify if there is any edge
 | 
					            # If we are checking for ^mpi we need to verify if there is any edge
 | 
				
			||||||
@@ -3910,6 +3914,10 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
 | 
				
			|||||||
            if not rhs_edge.virtuals:
 | 
					            if not rhs_edge.virtuals:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Skip edges from a concrete sub-DAG
 | 
				
			||||||
 | 
					            if rhs_edge.parent.concrete:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not lhs_edges:
 | 
					            if not lhs_edges:
 | 
				
			||||||
                # Construct a map of the link/run subDAG + direct "build" edges,
 | 
					                # Construct a map of the link/run subDAG + direct "build" edges,
 | 
				
			||||||
                # keyed by dependency name
 | 
					                # keyed by dependency name
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2448,6 +2448,20 @@ def _default_libc(self):
 | 
				
			|||||||
        s = Spec("a %gcc@=13.2.0").concretized()
 | 
					        s = Spec("a %gcc@=13.2.0").concretized()
 | 
				
			||||||
        assert s.satisfies("%gcc@13.2.0")
 | 
					        assert s.satisfies("%gcc@13.2.0")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @pytest.mark.regression("43267")
 | 
				
			||||||
 | 
					    def test_spec_with_build_dep_from_json(self, tmp_path):
 | 
				
			||||||
 | 
					        """Tests that we can correctly concretize a spec, when we express its dependency as a
 | 
				
			||||||
 | 
					        concrete spec to be read from JSON.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The bug was triggered by missing virtuals on edges that were trimmed from pure build
 | 
				
			||||||
 | 
					        dependencies.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        build_dep = Spec("dttop").concretized()
 | 
				
			||||||
 | 
					        json_file = tmp_path / "build.json"
 | 
				
			||||||
 | 
					        json_file.write_text(build_dep.to_json())
 | 
				
			||||||
 | 
					        s = Spec(f"dtuse ^{str(json_file)}").concretized()
 | 
				
			||||||
 | 
					        assert s["dttop"].dag_hash() == build_dep.dag_hash()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture()
 | 
					@pytest.fixture()
 | 
				
			||||||
def duplicates_test_repository():
 | 
					def duplicates_test_repository():
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,6 @@ class Dtbuild1(Package):
 | 
				
			|||||||
    version("1.0", md5="0123456789abcdef0123456789abcdef")
 | 
					    version("1.0", md5="0123456789abcdef0123456789abcdef")
 | 
				
			||||||
    version("0.5", md5="fedcba9876543210fedcba9876543210")
 | 
					    version("0.5", md5="fedcba9876543210fedcba9876543210")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depends_on("dtbuild2", type="build")
 | 
					    depends_on("vdtbuild2", type="build")
 | 
				
			||||||
    depends_on("dtlink2")
 | 
					    depends_on("dtlink2")
 | 
				
			||||||
    depends_on("dtrun2", type="run")
 | 
					    depends_on("dtrun2", type="run")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,3 +13,5 @@ class Dtbuild2(Package):
 | 
				
			|||||||
    url = "http://www.example.com/dtbuild2-1.0.tar.gz"
 | 
					    url = "http://www.example.com/dtbuild2-1.0.tar.gz"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    version("1.0", md5="0123456789abcdef0123456789abcdef")
 | 
					    version("1.0", md5="0123456789abcdef0123456789abcdef")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    provides("vdtbuild2")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user