1+ use crate :: core:: Profile ;
12use anyhow:: { Context , Result , anyhow} ;
23use camino:: Utf8PathBuf ;
3- use scarb_metadata:: { Metadata , PackageId } ;
4- use serde_json:: { Map , Number } ;
54use std:: fs:: File ;
65use std:: { env, fs} ;
7- use tempfile:: { TempDir , tempdir} ;
86use toml:: Value ;
7+
8+ pub mod core;
9+ pub mod test_utils;
10+
911pub const CONFIG_FILENAME : & str = "snfoundry.toml" ;
1012
11- /// Defined in snfoundry.toml
1213/// Configuration not associated with any specific package
1314pub trait Config {
1415 #[ must_use]
@@ -19,40 +20,6 @@ pub trait Config {
1920 Self : Sized ;
2021}
2122
22- /// Defined in scarb manifest
23- /// Configuration associated with a specific package
24- pub trait PackageConfig {
25- #[ must_use]
26- fn tool_name ( ) -> & ' static str ;
27-
28- fn from_raw ( config : & serde_json:: Value ) -> Result < Self >
29- where
30- Self : Sized ;
31- }
32-
33- fn get_with_ownership ( config : serde_json:: Value , key : & str ) -> Option < serde_json:: Value > {
34- match config {
35- serde_json:: Value :: Object ( mut map) => map. remove ( key) ,
36- _ => None ,
37- }
38- }
39-
40- pub fn get_profile (
41- raw_config : serde_json:: Value ,
42- tool : & str ,
43- profile : Option < & str > ,
44- ) -> Result < serde_json:: Value > {
45- let profile_name = profile. unwrap_or ( "default" ) ;
46- let tool_config = get_with_ownership ( raw_config, tool)
47- . unwrap_or ( serde_json:: Value :: Object ( serde_json:: Map :: new ( ) ) ) ;
48-
49- match get_with_ownership ( tool_config, profile_name) {
50- Some ( profile_value) => Ok ( profile_value) ,
51- None if profile_name == "default" => Ok ( serde_json:: Value :: Object ( Map :: default ( ) ) ) ,
52- None => Err ( anyhow ! ( "Profile [{profile_name}] not found in config" ) ) ,
53- }
54- }
55-
5623#[ must_use]
5724pub fn resolve_config_file ( ) -> Utf8PathBuf {
5825 find_config_file ( ) . unwrap_or_else ( |_| {
@@ -83,70 +50,14 @@ pub fn load_config<T: Config + Default>(
8350 let raw_config_json = serde_json:: to_value ( raw_config_toml)
8451 . context ( "Conversion from TOML value to JSON value should not fail." ) ?;
8552
86- let profile = get_profile ( raw_config_json, T :: tool_name ( ) , profile) ?;
87- T :: from_raw ( resolve_env_variables ( profile) ?)
53+ core:: load_config (
54+ raw_config_json,
55+ profile. map_or_else ( || Profile :: Default , |p| Profile :: Some ( p. to_string ( ) ) ) ,
56+ )
8857 }
8958 None => Ok ( T :: default ( ) ) ,
9059 }
9160}
92- /// Loads config for a specific package from the `Scarb.toml` file
93- /// # Arguments
94- /// * `metadata` - Scarb metadata object
95- /// * `package` - Id of the Scarb package
96- pub fn load_package_config < T : PackageConfig + Default > (
97- metadata : & Metadata ,
98- package : & PackageId ,
99- ) -> Result < T > {
100- let maybe_raw_metadata = metadata
101- . get_package ( package)
102- . ok_or_else ( || anyhow ! ( "Failed to find metadata for package = {package}" ) ) ?
103- . tool_metadata ( T :: tool_name ( ) )
104- . cloned ( ) ;
105- match maybe_raw_metadata {
106- Some ( raw_metadata) => T :: from_raw ( & resolve_env_variables ( raw_metadata) ?) ,
107- None => Ok ( T :: default ( ) ) ,
108- }
109- }
110-
111- fn resolve_env_variables ( config : serde_json:: Value ) -> Result < serde_json:: Value > {
112- match config {
113- serde_json:: Value :: Object ( map) => {
114- let val = map
115- . into_iter ( )
116- . map ( |( k, v) | -> Result < ( String , serde_json:: Value ) > {
117- Ok ( ( k, resolve_env_variables ( v) ?) )
118- } )
119- . collect :: < Result < serde_json:: Map < String , serde_json:: Value > > > ( ) ?;
120- Ok ( serde_json:: Value :: Object ( val) )
121- }
122- serde_json:: Value :: Array ( val) => {
123- let val = val
124- . into_iter ( )
125- . map ( resolve_env_variables)
126- . collect :: < Result < Vec < serde_json:: Value > > > ( ) ?;
127- Ok ( serde_json:: Value :: Array ( val) )
128- }
129- serde_json:: Value :: String ( val) if val. starts_with ( '$' ) => resolve_env_variable ( & val) ,
130- val => Ok ( val) ,
131- }
132- }
133-
134- fn resolve_env_variable ( var : & str ) -> Result < serde_json:: Value > {
135- assert ! ( var. starts_with( '$' ) ) ;
136- let mut initial_value = & var[ 1 ..] ;
137- if initial_value. starts_with ( '{' ) && initial_value. ends_with ( '}' ) {
138- initial_value = & initial_value[ 1 ..initial_value. len ( ) - 1 ] ;
139- }
140- let value = env:: var ( initial_value) ?;
141-
142- if let Ok ( value) = value. parse :: < Number > ( ) {
143- return Ok ( serde_json:: Value :: Number ( value) ) ;
144- }
145- if let Ok ( value) = value. parse :: < bool > ( ) {
146- return Ok ( serde_json:: Value :: Bool ( value) ) ;
147- }
148- Ok ( serde_json:: Value :: String ( value) )
149- }
15061
15162pub fn search_config_upwards_relative_to ( current_dir : & Utf8PathBuf ) -> Result < Utf8PathBuf > {
15263 current_dir
@@ -166,30 +77,18 @@ pub fn find_config_file() -> Result<Utf8PathBuf> {
16677 ) ?)
16778}
16879
169- pub fn copy_config_to_tempdir ( src_path : & str , additional_path : Option < & str > ) -> Result < TempDir > {
170- let temp_dir = tempdir ( ) . context ( "Failed to create a temporary directory" ) ?;
171- if let Some ( dir) = additional_path {
172- let path = temp_dir. path ( ) . join ( dir) ;
173- fs:: create_dir_all ( path) . context ( "Failed to create directories in temp dir" ) ?;
174- }
175- let temp_dir_file_path = temp_dir. path ( ) . join ( CONFIG_FILENAME ) ;
176- fs:: copy ( src_path, temp_dir_file_path) . context ( "Failed to copy config file to temp dir" ) ?;
177-
178- Ok ( temp_dir)
179- }
180-
18180#[ cfg( test) ]
18281mod tests {
18382 use std:: fs:: { self , File } ;
18483
84+ use super :: * ;
85+ use crate :: test_utils:: copy_config_to_tempdir;
18586 use serde:: { Deserialize , Serialize } ;
18687 use tempfile:: tempdir;
18788
188- use super :: * ;
189-
19089 #[ test]
19190 fn find_config_in_current_dir ( ) {
192- let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) . unwrap ( ) ;
91+ let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) ;
19392 let path = search_config_upwards_relative_to (
19493 & Utf8PathBuf :: try_from ( tempdir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ,
19594 )
@@ -200,7 +99,7 @@ mod tests {
20099 #[ test]
201100 fn find_config_in_parent_dir ( ) {
202101 let tempdir =
203- copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir" ) ) . unwrap ( ) ;
102+ copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir" ) ) ;
204103 let path = search_config_upwards_relative_to (
205104 & Utf8PathBuf :: try_from ( tempdir. path ( ) . to_path_buf ( ) . join ( "childdir" ) ) . unwrap ( ) ,
206105 )
@@ -213,8 +112,7 @@ mod tests {
213112 let tempdir = copy_config_to_tempdir (
214113 "tests/data/stubtool_snfoundry.toml" ,
215114 Some ( "childdir1/childdir2" ) ,
216- )
217- . unwrap ( ) ;
115+ ) ;
218116 let path = search_config_upwards_relative_to (
219117 & Utf8PathBuf :: try_from ( tempdir. path ( ) . to_path_buf ( ) . join ( "childdir1/childdir2" ) )
220118 . unwrap ( ) ,
@@ -226,8 +124,7 @@ mod tests {
226124 #[ test]
227125 fn find_config_in_parent_dir_available_in_multiple_parents ( ) {
228126 let tempdir =
229- copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir1" ) )
230- . unwrap ( ) ;
127+ copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir1" ) ) ;
231128 fs:: copy (
232129 "tests/data/stubtool_snfoundry.toml" ,
233130 tempdir. path ( ) . join ( "childdir1" ) . join ( CONFIG_FILENAME ) ,
@@ -270,7 +167,7 @@ mod tests {
270167 }
271168 #[ test]
272169 fn load_config_happy_case_with_profile ( ) {
273- let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) . unwrap ( ) ;
170+ let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) ;
274171 let config = load_config :: < StubConfig > (
275172 Some ( & Utf8PathBuf :: try_from ( tempdir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ) ,
276173 Some ( & String :: from ( "profile1" ) ) ,
@@ -282,7 +179,7 @@ mod tests {
282179
283180 #[ test]
284181 fn load_config_happy_case_default_profile ( ) {
285- let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) . unwrap ( ) ;
182+ let tempdir = copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , None ) ;
286183 let config = load_config :: < StubConfig > (
287184 Some ( & Utf8PathBuf :: try_from ( tempdir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ) ,
288185 None ,
@@ -354,8 +251,7 @@ mod tests {
354251 #[ expect( clippy:: float_cmp) ]
355252 fn resolve_env_vars ( ) {
356253 let tempdir =
357- copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir1" ) )
358- . unwrap ( ) ;
254+ copy_config_to_tempdir ( "tests/data/stubtool_snfoundry.toml" , Some ( "childdir1" ) ) ;
359255 fs:: copy (
360256 "tests/data/stubtool_snfoundry.toml" ,
361257 tempdir. path ( ) . join ( "childdir1" ) . join ( CONFIG_FILENAME ) ,
0 commit comments