1
+ use std:: path:: Path ;
2
+
1
3
use anyhow:: Context ;
4
+ use spin_common:: ui:: quoted_path;
5
+ use spin_manifest:: schema:: v2:: TargetEnvironmentRef ;
6
+
7
+ const DEFAULT_REGISTRY : & str = "fermyon.com" ;
2
8
3
9
/// 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
+ }
6
21
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 ;
8
27
9
28
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" ) ) ?;
10
36
11
37
// TODO: this requires wkg configuration which shouldn't be on users:
12
38
// 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) ;
15
44
16
45
let package = pkg_name
17
46
. to_owned ( )
@@ -35,7 +64,14 @@ pub async fn load_environment(env_id: impl AsRef<str>) -> anyhow::Result<TargetE
35
64
. with_context ( || format ! ( "Failed to get {env_id} package data from registry" ) ) ?
36
65
. to_vec ( ) ;
37
66
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)
39
75
}
40
76
41
77
/// A parsed document representing a deployment environment, e.g. Spin 2.7,
@@ -57,7 +93,7 @@ pub struct TargetEnvironment {
57
93
}
58
94
59
95
impl 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 > {
61
97
let decoded = wit_component:: decode ( & bytes)
62
98
. with_context ( || format ! ( "Failed to decode package for environment {name}" ) ) ?;
63
99
let package_id = decoded. package ( ) ;
@@ -79,6 +115,38 @@ impl TargetEnvironment {
79
115
} )
80
116
}
81
117
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
+
82
150
/// Returns true if the given trigger type provides the world identified by
83
151
/// `world` in this environment.
84
152
pub fn is_world_for ( & self , trigger_type : & TriggerType , world : & wit_parser:: World ) -> bool {
0 commit comments