@@ -4805,6 +4805,18 @@ def merge_abstract_anonymous_specs(*abstract_specs: Spec):
48054805 return merged_spec
48064806
48074807
4808+ def _reconstruct_virtuals_on_edges (spec ):
4809+ """Reconstruct virtuals on edges. Used to read from old DB
4810+ and reindex.
4811+ """
4812+ possible_virtuals = [x for x in spec .package .dependencies if Spec (x ).virtual ]
4813+ for vspec in possible_virtuals :
4814+ if vspec in spec :
4815+ name = spec [vspec ].name
4816+ for edge in spec .edges_to_dependencies (name = name ):
4817+ edge .update_virtuals ([vspec ])
4818+
4819+
48084820class SpecfileReaderBase :
48094821 @classmethod
48104822 def from_node_dict (cls , node ):
@@ -4869,6 +4881,64 @@ def from_node_dict(cls, node):
48694881
48704882 return spec
48714883
4884+ @classmethod
4885+ def _load (cls , data ):
4886+ """Construct a spec from JSON/YAML using the format version 2.
4887+
4888+ This format is used in Spack v0.17, was introduced in
4889+ https://github.com/spack/spack/pull/22845
4890+
4891+ Args:
4892+ data: a nested dict/list data structure read from YAML or JSON.
4893+ """
4894+ # Current specfile format
4895+ nodes = data ["spec" ]["nodes" ]
4896+ hash_type = None
4897+ any_deps = False
4898+
4899+ # Pass 0: Determine hash type
4900+ for node in nodes :
4901+ for _ , _ , _ , dhash_type , _ in cls .dependencies_from_node_dict (node ):
4902+ any_deps = True
4903+ if dhash_type :
4904+ hash_type = dhash_type
4905+ break
4906+
4907+ if not any_deps : # If we never see a dependency...
4908+ hash_type = ht .dag_hash .name
4909+ elif not hash_type : # Seen a dependency, still don't know hash_type
4910+ raise spack .error .SpecError (
4911+ "Spec dictionary contains malformed dependencies. Old format?"
4912+ )
4913+
4914+ hash_dict = {}
4915+ root_spec_hash = None
4916+
4917+ # Pass 1: Create a single lookup dictionary by hash
4918+ for i , node in enumerate (nodes ):
4919+ node_hash = node [hash_type ]
4920+ node_spec = cls .from_node_dict (node )
4921+ hash_dict [node_hash ] = node
4922+ hash_dict [node_hash ]["node_spec" ] = node_spec
4923+ if i == 0 :
4924+ root_spec_hash = node_hash
4925+
4926+ if not root_spec_hash :
4927+ raise spack .error .SpecError ("Spec dictionary contains no nodes." )
4928+
4929+ # Pass 2: Finish construction of all DAG edges (including build specs)
4930+ for node_hash , node in hash_dict .items ():
4931+ node_spec = node ["node_spec" ]
4932+ for _ , dhash , dtypes , _ , virtuals in cls .dependencies_from_node_dict (node ):
4933+ node_spec ._add_dependency (
4934+ hash_dict [dhash ]["node_spec" ], deptypes = dtypes , virtuals = virtuals
4935+ )
4936+ if "build_spec" in node .keys ():
4937+ _ , bhash , _ = cls .build_spec_from_node_dict (node , hash_type = hash_type )
4938+ node_spec ._build_spec = hash_dict [bhash ]["node_spec" ]
4939+
4940+ return hash_dict [root_spec_hash ]["node_spec" ]
4941+
48724942
48734943class SpecfileV1 (SpecfileReaderBase ):
48744944 @classmethod
@@ -4899,6 +4969,7 @@ def load(cls, data):
48994969 for dname , _ , dtypes , _ , virtuals in cls .dependencies_from_node_dict (data ):
49004970 deps [name ]._add_dependency (deps [dname ], deptypes = dtypes , virtuals = virtuals )
49014971
4972+ _reconstruct_virtuals_on_edges (result )
49024973 return result
49034974
49044975 @classmethod
@@ -4939,61 +5010,9 @@ def read_specfile_dep_specs(cls, deps, hash_type=ht.dag_hash.name):
49395010class SpecfileV2 (SpecfileReaderBase ):
49405011 @classmethod
49415012 def load (cls , data ):
4942- """Construct a spec from JSON/YAML using the format version 2.
4943-
4944- This format is used in Spack v0.17, was introduced in
4945- https://github.com/spack/spack/pull/22845
4946-
4947- Args:
4948- data: a nested dict/list data structure read from YAML or JSON.
4949- """
4950- # Current specfile format
4951- nodes = data ["spec" ]["nodes" ]
4952- hash_type = None
4953- any_deps = False
4954-
4955- # Pass 0: Determine hash type
4956- for node in nodes :
4957- for _ , _ , _ , dhash_type , _ in cls .dependencies_from_node_dict (node ):
4958- any_deps = True
4959- if dhash_type :
4960- hash_type = dhash_type
4961- break
4962-
4963- if not any_deps : # If we never see a dependency...
4964- hash_type = ht .dag_hash .name
4965- elif not hash_type : # Seen a dependency, still don't know hash_type
4966- raise spack .error .SpecError (
4967- "Spec dictionary contains malformed dependencies. Old format?"
4968- )
4969-
4970- hash_dict = {}
4971- root_spec_hash = None
4972-
4973- # Pass 1: Create a single lookup dictionary by hash
4974- for i , node in enumerate (nodes ):
4975- node_hash = node [hash_type ]
4976- node_spec = cls .from_node_dict (node )
4977- hash_dict [node_hash ] = node
4978- hash_dict [node_hash ]["node_spec" ] = node_spec
4979- if i == 0 :
4980- root_spec_hash = node_hash
4981-
4982- if not root_spec_hash :
4983- raise spack .error .SpecError ("Spec dictionary contains no nodes." )
4984-
4985- # Pass 2: Finish construction of all DAG edges (including build specs)
4986- for node_hash , node in hash_dict .items ():
4987- node_spec = node ["node_spec" ]
4988- for _ , dhash , dtypes , _ , virtuals in cls .dependencies_from_node_dict (node ):
4989- node_spec ._add_dependency (
4990- hash_dict [dhash ]["node_spec" ], deptypes = dtypes , virtuals = virtuals
4991- )
4992- if "build_spec" in node .keys ():
4993- _ , bhash , _ = cls .build_spec_from_node_dict (node , hash_type = hash_type )
4994- node_spec ._build_spec = hash_dict [bhash ]["node_spec" ]
4995-
4996- return hash_dict [root_spec_hash ]["node_spec" ]
5013+ result = cls ._load (data )
5014+ _reconstruct_virtuals_on_edges (result )
5015+ return result
49975016
49985017 @classmethod
49995018 def name_and_data (cls , node ):
@@ -5055,6 +5074,10 @@ def extract_info_from_dep(cls, elt, hash):
50555074 virtuals = elt ["parameters" ]["virtuals" ]
50565075 return dep_hash , deptypes , hash_type , virtuals
50575076
5077+ @classmethod
5078+ def load (cls , data ):
5079+ return cls ._load (data )
5080+
50585081
50595082class LazySpecCache (collections .defaultdict ):
50605083 """Cache for Specs that uses a spec_like as key, and computes lazily
0 commit comments