1+ use std:: path:: Path ;
2+
13use anyhow:: Context ;
4+ use spin_common:: ui:: quoted_path;
5+ use spin_manifest:: schema:: v2:: TargetEnvironmentRef ;
6+
7+ const DEFAULT_REGISTRY : & str = "fermyon.com" ;
28
39/// Loads the given `TargetEnvironment` from a registry.
4- pub async fn load_environment ( env_id : impl AsRef < str > ) -> anyhow:: Result < TargetEnvironment > {
5- use futures_util:: TryStreamExt ;
10+ pub async fn load_environment ( env_id : & TargetEnvironmentRef ) -> anyhow:: Result < TargetEnvironment > {
11+ match env_id {
12+ TargetEnvironmentRef :: DefaultRegistry ( package) => {
13+ load_environment_from_registry ( DEFAULT_REGISTRY , package) . await
14+ }
15+ TargetEnvironmentRef :: Registry { registry, package } => {
16+ load_environment_from_registry ( registry, package) . await
17+ }
18+ TargetEnvironmentRef :: WitDirectory { path } => load_environment_from_dir ( path) ,
19+ }
20+ }
621
7- let env_id = env_id. as_ref ( ) ;
22+ async fn load_environment_from_registry (
23+ registry : & str ,
24+ env_id : & str ,
25+ ) -> anyhow:: Result < TargetEnvironment > {
26+ use futures_util:: TryStreamExt ;
827
928 let ( pkg_name, pkg_ver) = env_id. split_once ( '@' ) . with_context ( || format ! ( "Failed to parse target environment {env_id} as package reference - is the target correct?" ) ) ?;
29+ let env_pkg_ref: wasm_pkg_loader:: PackageRef = pkg_name
30+ . parse ( )
31+ . with_context ( || format ! ( "Environment {pkg_name} is not a valid package name" ) ) ?;
32+
33+ let registry: wasm_pkg_loader:: Registry = registry
34+ . parse ( )
35+ . with_context ( || format ! ( "Registry {registry} is not a valid registry name" ) ) ?;
1036
1137 // TODO: this requires wkg configuration which shouldn't be on users:
1238 // is there a better way to handle it?
13- let mut client = wasm_pkg_loader:: Client :: with_global_defaults ( )
14- . context ( "Failed to create a package loader from your global settings" ) ?;
39+ let mut wkg_config = wasm_pkg_loader:: Config :: global_defaults ( )
40+ . unwrap_or_else ( |_| wasm_pkg_loader:: Config :: empty ( ) ) ;
41+ wkg_config. set_package_registry_override ( env_pkg_ref, registry) ;
42+
43+ let mut client = wasm_pkg_loader:: Client :: new ( wkg_config) ;
1544
1645 let package = pkg_name
1746 . to_owned ( )
@@ -35,7 +64,14 @@ pub async fn load_environment(env_id: impl AsRef<str>) -> anyhow::Result<TargetE
3564 . with_context ( || format ! ( "Failed to get {env_id} package data from registry" ) ) ?
3665 . to_vec ( ) ;
3766
38- TargetEnvironment :: new ( env_id. to_owned ( ) , bytes)
67+ TargetEnvironment :: from_package_bytes ( env_id. to_owned ( ) , bytes)
68+ }
69+
70+ fn load_environment_from_dir ( path : & Path ) -> anyhow:: Result < TargetEnvironment > {
71+ let mut resolve = wit_parser:: Resolve :: default ( ) ;
72+ let ( pkg_id, _) = resolve. push_dir ( path) ?;
73+ let decoded = wit_parser:: decoding:: DecodedWasm :: WitPackage ( resolve, pkg_id) ;
74+ TargetEnvironment :: from_decoded_wasm ( path, decoded)
3975}
4076
4177/// A parsed document representing a deployment environment, e.g. Spin 2.7,
@@ -57,7 +93,7 @@ pub struct TargetEnvironment {
5793}
5894
5995impl TargetEnvironment {
60- fn new ( name : String , bytes : Vec < u8 > ) -> anyhow:: Result < Self > {
96+ fn from_package_bytes ( name : String , bytes : Vec < u8 > ) -> anyhow:: Result < Self > {
6197 let decoded = wit_component:: decode ( & bytes)
6298 . with_context ( || format ! ( "Failed to decode package for environment {name}" ) ) ?;
6399 let package_id = decoded. package ( ) ;
@@ -79,6 +115,38 @@ impl TargetEnvironment {
79115 } )
80116 }
81117
118+ fn from_decoded_wasm (
119+ source : & Path ,
120+ decoded : wit_parser:: decoding:: DecodedWasm ,
121+ ) -> anyhow:: Result < Self > {
122+ let package_id = decoded. package ( ) ;
123+ let package = decoded
124+ . resolve ( )
125+ . packages
126+ . get ( package_id)
127+ . with_context ( || {
128+ format ! (
129+ "The {} environment is invalid (no package for decoded package ID)" ,
130+ quoted_path( source)
131+ )
132+ } ) ?
133+ . clone ( ) ;
134+ let name = package. name . to_string ( ) ;
135+
136+ // This versionm of wit_component requires a flag for v2 encoding.
137+ // v1 encoding is retired in wit_component main. You can remove the
138+ // flag when this breaks next time we upgrade the crate!
139+ let bytes = wit_component:: encode ( Some ( true ) , decoded. resolve ( ) , package_id) ?;
140+
141+ Ok ( Self {
142+ name,
143+ decoded,
144+ package,
145+ package_id,
146+ package_bytes : bytes,
147+ } )
148+ }
149+
82150 /// Returns true if the given trigger type provides the world identified by
83151 /// `world` in this environment.
84152 pub fn is_world_for ( & self , trigger_type : & TriggerType , world : & wit_parser:: World ) -> bool {
0 commit comments