@@ -52,20 +52,23 @@ where
5252 /// Creates a new resolved runtime configuration from an optional runtime config source TOML file.
5353 pub fn from_optional_file (
5454 runtime_config_path : Option < & Path > ,
55- provided_state_dir : Option < & Path > ,
56- provided_log_dir : LogDir ,
55+ local_app_dir : Option < PathBuf > ,
56+ provided_state_dir : UserProvidedPath ,
57+ provided_log_dir : UserProvidedPath ,
5758 use_gpu : bool ,
5859 ) -> anyhow:: Result < Self > {
5960 match runtime_config_path {
6061 Some ( runtime_config_path) => Self :: from_file (
6162 runtime_config_path,
63+ local_app_dir,
6264 provided_state_dir,
6365 provided_log_dir,
6466 use_gpu,
6567 ) ,
6668 None => Self :: new (
6769 Default :: default ( ) ,
6870 None ,
71+ local_app_dir,
6972 provided_state_dir,
7073 provided_log_dir,
7174 use_gpu,
7881 /// `provided_state_dir` is the explicitly provided state directory, if any.
7982 pub fn from_file (
8083 runtime_config_path : & Path ,
81- provided_state_dir : Option < & Path > ,
82- provided_log_dir : LogDir ,
84+ local_app_dir : Option < PathBuf > ,
85+ provided_state_dir : UserProvidedPath ,
86+ provided_log_dir : UserProvidedPath ,
8387 use_gpu : bool ,
8488 ) -> anyhow:: Result < Self > {
8589 let file = std:: fs:: read_to_string ( runtime_config_path) . with_context ( || {
98102 Self :: new (
99103 toml,
100104 Some ( runtime_config_path) ,
105+ local_app_dir,
101106 provided_state_dir,
102107 provided_log_dir,
103108 use_gpu,
@@ -108,11 +113,13 @@ where
108113 pub fn new (
109114 toml : toml:: Table ,
110115 runtime_config_path : Option < & Path > ,
111- provided_state_dir : Option < & Path > ,
112- provided_log_dir : LogDir ,
116+ local_app_dir : Option < PathBuf > ,
117+ provided_state_dir : UserProvidedPath ,
118+ provided_log_dir : UserProvidedPath ,
113119 use_gpu : bool ,
114120 ) -> anyhow:: Result < Self > {
115- let toml_resolver = TomlResolver :: new ( & toml, provided_state_dir, provided_log_dir) ;
121+ let toml_resolver =
122+ TomlResolver :: new ( & toml, local_app_dir, provided_state_dir, provided_log_dir) ;
116123 let tls_resolver = runtime_config_path. map ( SpinTlsRuntimeConfig :: new) ;
117124 let key_value_config_resolver = key_value_config_resolver ( toml_resolver. state_dir ( ) ?) ;
118125 let sqlite_config_resolver = sqlite_config_resolver ( toml_resolver. state_dir ( ) ?)
@@ -178,19 +185,25 @@ where
178185/// Resolves runtime configuration from a TOML file.
179186pub struct TomlResolver < ' a > {
180187 table : TomlKeyTracker < ' a > ,
188+ /// The local app directory.
189+ local_app_dir : Option < PathBuf > ,
181190 /// Explicitly provided state directory.
182- state_dir : Option < & ' a Path > ,
191+ state_dir : UserProvidedPath ,
183192 /// Explicitly provided log directory.
184- log_dir : LogDir ,
193+ log_dir : UserProvidedPath ,
185194}
186195
187196impl < ' a > TomlResolver < ' a > {
188197 /// Create a new TOML resolver.
189- ///
190- /// The `state_dir` is the explicitly provided state directory, if any.
191- pub fn new ( table : & ' a toml:: Table , state_dir : Option < & ' a Path > , log_dir : LogDir ) -> Self {
198+ pub fn new (
199+ table : & ' a toml:: Table ,
200+ local_app_dir : Option < PathBuf > ,
201+ state_dir : UserProvidedPath ,
202+ log_dir : UserProvidedPath ,
203+ ) -> Self {
192204 Self {
193205 table : TomlKeyTracker :: new ( table) ,
206+ local_app_dir,
194207 state_dir,
195208 log_dir,
196209 }
@@ -200,28 +213,63 @@ impl<'a> TomlResolver<'a> {
200213 ///
201214 /// Errors if the path cannot be converted to an absolute path.
202215 pub fn state_dir ( & self ) -> std:: io:: Result < Option < PathBuf > > {
203- let from_toml = || {
204- self . table
205- . get ( "state_dir" )
206- . and_then ( |v| v. as_str ( ) )
207- . filter ( |v| !v. is_empty ( ) )
208- . map ( Path :: new)
209- } ;
210- // Prefer explicitly provided state directory, then take from toml.
211- self . state_dir
212- . or_else ( from_toml)
213- . map ( std:: path:: absolute)
214- . transpose ( )
216+ let mut state_dir = self . state_dir . clone ( ) ;
217+ // If the state_dir is not explicitly provided, check the toml.
218+ if matches ! ( state_dir, UserProvidedPath :: Default ) {
219+ let from_toml =
220+ self . table
221+ . get ( "state_dir" )
222+ . and_then ( |v| v. as_str ( ) )
223+ . map ( |toml_value| {
224+ if toml_value. is_empty ( ) {
225+ // If the toml value is empty, treat it as unset.
226+ UserProvidedPath :: Unset
227+ } else {
228+ // Otherwise, treat the toml value as a provided path.
229+ UserProvidedPath :: Provided ( PathBuf :: from ( toml_value) )
230+ }
231+ } ) ;
232+ // If toml value is not provided, use the original value after all.
233+ state_dir = from_toml. unwrap_or ( state_dir) ;
234+ }
235+
236+ match ( state_dir, & self . local_app_dir ) {
237+ ( UserProvidedPath :: Provided ( p) , _) => Ok ( Some ( std:: path:: absolute ( p) ?) ) ,
238+ ( UserProvidedPath :: Default , Some ( local_app_dir) ) => {
239+ Ok ( Some ( local_app_dir. join ( ".spin" ) ) )
240+ }
241+ ( UserProvidedPath :: Default | UserProvidedPath :: Unset , _) => Ok ( None ) ,
242+ }
215243 }
216244
217245 /// Get the configured log directory.
218246 ///
219247 /// Errors if the path cannot be converted to an absolute path.
220248 pub fn log_dir ( & self ) -> std:: io:: Result < Option < PathBuf > > {
221- match & self . log_dir {
222- LogDir :: Provided ( p) => Ok ( Some ( std:: path:: absolute ( p) ?) ) ,
223- LogDir :: Default => Ok ( self . state_dir ( ) ?. map ( |p| p. join ( "logs" ) ) ) ,
224- LogDir :: None => Ok ( None ) ,
249+ let mut log_dir = self . log_dir . clone ( ) ;
250+ // If the log_dir is not explicitly provided, check the toml.
251+ if matches ! ( log_dir, UserProvidedPath :: Default ) {
252+ let from_toml = self
253+ . table
254+ . get ( "log_dir" )
255+ . and_then ( |v| v. as_str ( ) )
256+ . map ( |toml_value| {
257+ if toml_value. is_empty ( ) {
258+ // If the toml value is empty, treat it as unset.
259+ UserProvidedPath :: Unset
260+ } else {
261+ // Otherwise, treat the toml value as a provided path.
262+ UserProvidedPath :: Provided ( PathBuf :: from ( toml_value) )
263+ }
264+ } ) ;
265+ // If toml value is not provided, use the original value after all.
266+ log_dir = from_toml. unwrap_or ( log_dir) ;
267+ }
268+
269+ match log_dir {
270+ UserProvidedPath :: Provided ( p) => Ok ( Some ( std:: path:: absolute ( p) ?) ) ,
271+ UserProvidedPath :: Default => Ok ( self . state_dir ( ) ?. map ( |p| p. join ( "logs" ) ) ) ,
272+ UserProvidedPath :: Unset => Ok ( None ) ,
225273 }
226274 }
227275
@@ -397,13 +445,13 @@ fn sqlite_config_resolver(
397445 ) )
398446}
399447
400- /// The log directory for the trigger .
448+ /// A user provided option which be either be provided, default, or explicitly none .
401449#[ derive( Clone , Debug ) ]
402- pub enum LogDir {
403- /// Use the explicitly provided log directory.
450+ pub enum UserProvidedPath {
451+ /// Use the explicitly provided directory.
404452 Provided ( PathBuf ) ,
405- /// Use the default log directory .
453+ /// Use the default.
406454 Default ,
407- /// Do not log .
408- None ,
455+ /// Explicitly unset .
456+ Unset ,
409457}
0 commit comments