@@ -872,6 +872,8 @@ def _fetch_spec_from_mirror(spec_url):
872872 return Spec .from_dict (specfile_json )
873873 if spec_url .endswith (".json" ):
874874 return Spec .from_json (spec_file_contents )
875+ if spec_url .endswith (".yaml" ):
876+ return Spec .from_yaml (spec_file_contents )
875877
876878 tp = multiprocessing .pool .ThreadPool (processes = concurrency )
877879 try :
@@ -946,6 +948,8 @@ def file_read_method(file_path):
946948 "*.spec.json.sig" ,
947949 "--include" ,
948950 "*.spec.json" ,
951+ "--include" ,
952+ "*.spec.yaml" ,
949953 cache_prefix ,
950954 tmpspecsdir ,
951955 ]
@@ -955,7 +959,7 @@ def file_read_method(file_path):
955959 "Using aws s3 sync to download specs from {0} to {1}" .format (cache_prefix , tmpspecsdir )
956960 )
957961 aws (* sync_command_args , output = os .devnull , error = os .devnull )
958- file_list = fsys .find (tmpspecsdir , ["*.spec.json.sig" , "*.spec.json" ])
962+ file_list = fsys .find (tmpspecsdir , ["*.spec.json.sig" , "*.spec.json" , "*.spec.yaml" ])
959963 read_fn = file_read_method
960964 except Exception :
961965 tty .warn ("Failed to use aws s3 sync to retrieve specs, falling back to parallel fetch" )
@@ -991,7 +995,9 @@ def url_read_method(url):
991995 file_list = [
992996 url_util .join (cache_prefix , entry )
993997 for entry in web_util .list_url (cache_prefix )
994- if entry .endswith ("spec.json" ) or entry .endswith ("spec.json.sig" )
998+ if entry .endswith (".yaml" )
999+ or entry .endswith ("spec.json" )
1000+ or entry .endswith ("spec.json.sig" )
9951001 ]
9961002 read_fn = url_read_method
9971003 except KeyError as inst :
@@ -1053,6 +1059,14 @@ def generate_package_index(cache_prefix, concurrency=32):
10531059 tty .error ("Unable to generate package index, {0}" .format (err ))
10541060 return
10551061
1062+ if any (x .endswith (".yaml" ) for x in file_list ):
1063+ msg = (
1064+ "The mirror in '{}' contains specs in the deprecated YAML format.\n \n \t Support for "
1065+ "this format will be removed in v0.20, please regenerate the build cache with a "
1066+ "recent Spack\n "
1067+ ).format (cache_prefix )
1068+ warnings .warn (msg )
1069+
10561070 tty .debug ("Retrieving spec descriptor files from {0} to build index" .format (cache_prefix ))
10571071
10581072 tmpdir = tempfile .mkdtemp ()
@@ -1179,20 +1193,28 @@ def _build_tarball(
11791193 specfile_name = tarball_name (spec , ".spec.json" )
11801194 specfile_path = os .path .realpath (os .path .join (cache_prefix , specfile_name ))
11811195 signed_specfile_path = "{0}.sig" .format (specfile_path )
1196+ deprecated_specfile_path = specfile_path .replace (".spec.json" , ".spec.yaml" )
11821197
11831198 remote_specfile_path = url_util .join (
11841199 out_url , os .path .relpath (specfile_path , os .path .realpath (tmpdir ))
11851200 )
11861201 remote_signed_specfile_path = "{0}.sig" .format (remote_specfile_path )
1202+ remote_specfile_path_deprecated = url_util .join (
1203+ outdir , os .path .relpath (deprecated_specfile_path , os .path .realpath (tmpdir ))
1204+ )
11871205
11881206 # If force and exists, overwrite. Otherwise raise exception on collision.
11891207 if force :
11901208 if web_util .url_exists (remote_specfile_path ):
11911209 web_util .remove_url (remote_specfile_path )
11921210 if web_util .url_exists (remote_signed_specfile_path ):
11931211 web_util .remove_url (remote_signed_specfile_path )
1194- elif web_util .url_exists (remote_specfile_path ) or web_util .url_exists (
1195- remote_signed_specfile_path
1212+ if web_util .url_exists (remote_specfile_path_deprecated ):
1213+ web_util .remove_url (remote_specfile_path_deprecated )
1214+ elif (
1215+ web_util .url_exists (remote_specfile_path )
1216+ or web_util .url_exists (remote_signed_specfile_path )
1217+ or web_util .url_exists (remote_specfile_path_deprecated )
11961218 ):
11971219 raise NoOverwriteException (url_util .format (remote_specfile_path ))
11981220
@@ -1248,10 +1270,12 @@ def _build_tarball(
12481270
12491271 with open (spec_file , "r" ) as inputfile :
12501272 content = inputfile .read ()
1251- if spec_file .endswith (".json" ):
1273+ if spec_file .endswith (".yaml" ):
1274+ spec_dict = yaml .load (content )
1275+ elif spec_file .endswith (".json" ):
12521276 spec_dict = sjson .load (content )
12531277 else :
1254- raise ValueError ("{0} not a valid spec file type" .format (spec_file ))
1278+ raise ValueError ("{0} not a valid spec file type (json or yaml) " .format (spec_file ))
12551279 spec_dict ["buildcache_layout_version" ] = 1
12561280 bchecksum = {}
12571281 bchecksum ["hash_algorithm" ] = "sha256"
@@ -1472,7 +1496,7 @@ def download_tarball(spec, unsigned=False, mirrors_for_spec=None):
14721496 # Assumes we care more about finding a spec file by preferred ext
14731497 # than by mirrory priority. This can be made less complicated as
14741498 # we remove support for deprecated spec formats and buildcache layouts.
1475- for ext in ["json.sig" , "json" ]:
1499+ for ext in ["json.sig" , "json" , "yaml" ]:
14761500 for mirror_to_try in mirrors_to_try :
14771501 specfile_url = "{0}.{1}" .format (mirror_to_try ["specfile" ], ext )
14781502 spackfile_url = mirror_to_try ["spackfile" ]
@@ -1509,6 +1533,13 @@ def download_tarball(spec, unsigned=False, mirrors_for_spec=None):
15091533 # the remaining mirrors, looking for one we can use.
15101534 tarball_stage = try_fetch (spackfile_url )
15111535 if tarball_stage :
1536+ if ext == "yaml" :
1537+ msg = (
1538+ "Reading {} from mirror.\n \n \t The YAML format for buildcaches is "
1539+ "deprecated and will be removed in v0.20\n "
1540+ ).format (spackfile_url )
1541+ warnings .warn (msg )
1542+
15121543 return {
15131544 "tarball_stage" : tarball_stage ,
15141545 "specfile_stage" : local_specfile_stage ,
@@ -1748,6 +1779,8 @@ def _extract_inner_tarball(spec, filename, extract_to, unsigned, remote_checksum
17481779 spackfile_path = os .path .join (stagepath , spackfile_name )
17491780 tarfile_name = tarball_name (spec , ".tar.gz" )
17501781 tarfile_path = os .path .join (extract_to , tarfile_name )
1782+ deprecated_yaml_name = tarball_name (spec , ".spec.yaml" )
1783+ deprecated_yaml_path = os .path .join (extract_to , deprecated_yaml_name )
17511784 json_name = tarball_name (spec , ".spec.json" )
17521785 json_path = os .path .join (extract_to , json_name )
17531786 with closing (tarfile .open (spackfile_path , "r" )) as tar :
@@ -1759,6 +1792,8 @@ def _extract_inner_tarball(spec, filename, extract_to, unsigned, remote_checksum
17591792
17601793 if os .path .exists (json_path ):
17611794 specfile_path = json_path
1795+ elif os .path .exists (deprecated_yaml_path ):
1796+ specfile_path = deprecated_yaml_path
17621797 else :
17631798 raise ValueError ("Cannot find spec file for {0}." .format (extract_to ))
17641799
@@ -1805,8 +1840,10 @@ def extract_tarball(spec, download_result, allow_root=False, unsigned=False, for
18051840 content = inputfile .read ()
18061841 if specfile_path .endswith (".json.sig" ):
18071842 spec_dict = Spec .extract_json_from_clearsig (content )
1808- else :
1843+ elif specfile_path . endswith ( ".json" ) :
18091844 spec_dict = sjson .load (content )
1845+ else :
1846+ spec_dict = syaml .load (content )
18101847
18111848 bchecksum = spec_dict ["binary_cache_checksum" ]
18121849 filename = download_result ["tarball_stage" ].save_filename
@@ -1818,7 +1855,7 @@ def extract_tarball(spec, download_result, allow_root=False, unsigned=False, for
18181855 or int (spec_dict ["buildcache_layout_version" ]) < 1
18191856 ):
18201857 # Handle the older buildcache layout where the .spack file
1821- # contains a spec json, maybe an .asc file (signature),
1858+ # contains a spec json/yaml , maybe an .asc file (signature),
18221859 # and another tarball containing the actual install tree.
18231860 tmpdir = tempfile .mkdtemp ()
18241861 try :
@@ -1969,12 +2006,17 @@ def try_direct_fetch(spec, mirrors=None):
19692006 """
19702007 Try to find the spec directly on the configured mirrors
19712008 """
2009+ deprecated_specfile_name = tarball_name (spec , ".spec.yaml" )
19722010 specfile_name = tarball_name (spec , ".spec.json" )
19732011 signed_specfile_name = tarball_name (spec , ".spec.json.sig" )
19742012 specfile_is_signed = False
2013+ specfile_is_json = True
19752014 found_specs = []
19762015
19772016 for mirror in spack .mirror .MirrorCollection (mirrors = mirrors ).values ():
2017+ buildcache_fetch_url_yaml = url_util .join (
2018+ mirror .fetch_url , _build_cache_relative_path , deprecated_specfile_name
2019+ )
19782020 buildcache_fetch_url_json = url_util .join (
19792021 mirror .fetch_url , _build_cache_relative_path , specfile_name
19802022 )
@@ -1988,19 +2030,28 @@ def try_direct_fetch(spec, mirrors=None):
19882030 try :
19892031 _ , _ , fs = web_util .read_from_url (buildcache_fetch_url_json )
19902032 except (URLError , web_util .SpackWebError , HTTPError ) as url_err_x :
1991- tty .debug (
1992- "Did not find {0} on {1}" .format (
1993- specfile_name , buildcache_fetch_url_signed_json
1994- ),
1995- url_err ,
1996- level = 2 ,
1997- )
1998- tty .debug (
1999- "Did not find {0} on {1}" .format (specfile_name , buildcache_fetch_url_json ),
2000- url_err_x ,
2001- level = 2 ,
2002- )
2003- continue
2033+ try :
2034+ _ , _ , fs = web_util .read_from_url (buildcache_fetch_url_yaml )
2035+ specfile_is_json = False
2036+ except (URLError , web_util .SpackWebError , HTTPError ) as url_err_y :
2037+ tty .debug (
2038+ "Did not find {0} on {1}" .format (
2039+ specfile_name , buildcache_fetch_url_signed_json
2040+ ),
2041+ url_err ,
2042+ level = 2 ,
2043+ )
2044+ tty .debug (
2045+ "Did not find {0} on {1}" .format (specfile_name , buildcache_fetch_url_json ),
2046+ url_err_x ,
2047+ level = 2 ,
2048+ )
2049+ tty .debug (
2050+ "Did not find {0} on {1}" .format (specfile_name , buildcache_fetch_url_yaml ),
2051+ url_err_y ,
2052+ level = 2 ,
2053+ )
2054+ continue
20042055 specfile_contents = codecs .getreader ("utf-8" )(fs ).read ()
20052056
20062057 # read the spec from the build cache file. All specs in build caches
@@ -2009,8 +2060,10 @@ def try_direct_fetch(spec, mirrors=None):
20092060 if specfile_is_signed :
20102061 specfile_json = Spec .extract_json_from_clearsig (specfile_contents )
20112062 fetched_spec = Spec .from_dict (specfile_json )
2012- else :
2063+ elif specfile_is_json :
20132064 fetched_spec = Spec .from_json (specfile_contents )
2065+ else :
2066+ fetched_spec = Spec .from_yaml (specfile_contents )
20142067 fetched_spec ._mark_concrete ()
20152068
20162069 found_specs .append (
@@ -2221,7 +2274,7 @@ def needs_rebuild(spec, mirror_url):
22212274 specfile_path = os .path .join (cache_prefix , specfile_name )
22222275
22232276 # Only check for the presence of the json version of the spec. If the
2224- # mirror only has the json version, or doesn't have the spec at all, we
2277+ # mirror only has the yaml version, or doesn't have the spec at all, we
22252278 # need to rebuild.
22262279 return not web_util .url_exists (specfile_path )
22272280
@@ -2329,6 +2382,7 @@ def download_single_spec(concrete_spec, destination, mirror_url=None):
23292382 "url" : [
23302383 tarball_name (concrete_spec , ".spec.json.sig" ),
23312384 tarball_name (concrete_spec , ".spec.json" ),
2385+ tarball_name (concrete_spec , ".spec.yaml" ),
23322386 ],
23332387 "path" : destination ,
23342388 "required" : True ,
0 commit comments