diff --git a/Cargo.lock b/Cargo.lock index 39b5b13..d7ae3a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5046,6 +5046,7 @@ dependencies = [ "anyhow", "directories", "dotenv", + "thiserror", ] [[package]] diff --git a/crates/sesam-vitale/src/ssvlib_demo.rs b/crates/sesam-vitale/src/ssvlib_demo.rs index 2a29ce5..d5ad4a0 100644 --- a/crates/sesam-vitale/src/ssvlib_demo.rs +++ b/crates/sesam-vitale/src/ssvlib_demo.rs @@ -9,7 +9,7 @@ use thiserror::Error; use crate::cps::lire_carte; use crate::libssv::{SSV_InitLIB2, SSV_LireConfig}; -use ::utils::config::load_config; +use ::utils::config::{load_config, ConfigError}; #[derive(Error, Debug)] pub enum SSVDemoError { @@ -18,7 +18,7 @@ pub enum SSVDemoError { #[error(transparent)] SSVLibErrorCode(#[from] crate::libssv::LibSSVError), #[error(transparent)] - Anyhow(#[from] anyhow::Error), + Configuration(#[from] ConfigError), } fn ssv_init_lib_2() -> Result<(), SSVDemoError> { @@ -71,7 +71,7 @@ pub fn demo() -> Result<(), SSVDemoError> { println!("------- Demo for the SSV library --------"); - load_config()?; + load_config(None)?; ssv_init_lib_2()?; diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index fbe8c0e..d89f083 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" anyhow = "1.0" directories = "5.0" dotenv = "0.15" +thiserror = "1.0" diff --git a/crates/utils/src/config.rs b/crates/utils/src/config.rs index d4756f5..d704e7b 100644 --- a/crates/utils/src/config.rs +++ b/crates/utils/src/config.rs @@ -1,11 +1,23 @@ -use std::{env, path::PathBuf}; +use std::{env, path::PathBuf, sync::atomic::AtomicBool}; -use anyhow::{bail, Context, Result}; use directories::ProjectDirs; use dotenv::from_path; +use thiserror::Error; const CONFIG_FILE_NAME: &str = ".env"; +static CONFIG_INITIALIZED: AtomicBool = AtomicBool::new(false); + +#[derive(Debug, Error)] +pub enum ConfigError { + #[error("No config file {0} found in the following directories: {1:#?}")] + ConfigFileNotFound(String, Vec), + #[error("Failed to load config file: {0}")] + LoadConfigError(#[from] dotenv::Error), + #[error("Environment variable error: {0}")] + EnvVarError(#[from] std::env::VarError), +} + pub fn get_config_dirs() -> Vec { let mut config_dirs = vec![ PathBuf::from(""), // Current directory @@ -19,7 +31,7 @@ pub fn get_config_dirs() -> Vec { config_dirs } -pub fn get_config_files() -> Result> { +pub fn get_config_files() -> Result, ConfigError> { let config_dirs = get_config_dirs(); let mut config_files = Vec::new(); for config_dir in config_dirs.iter() { @@ -29,14 +41,20 @@ pub fn get_config_files() -> Result> { } } if config_files.is_empty() { - bail!( - "No config file {CONFIG_FILE_NAME} found in the following directories: {config_dirs:#?}" - ); + return Err(ConfigError::ConfigFileNotFound( + CONFIG_FILE_NAME.to_string(), + config_dirs, + )); } Ok(config_files) } -pub fn load_config() -> Result<()> { +pub fn load_config(force: Option) -> Result<(), ConfigError> { + let force = force.unwrap_or(false); + if CONFIG_INITIALIZED.load(std::sync::atomic::Ordering::Relaxed) && force { + println!("DEBUG: Config already initialized, skipping"); + return Ok(()); + } let config_files = get_config_files()?; // Load the first config file found // TODO: add a verbose log to list all config files found @@ -44,5 +62,7 @@ pub fn load_config() -> Result<()> { "DEBUG: Config files found (1st loaded): {:#?}", config_files ); - from_path(config_files[0].as_path()).context("Failed to load config file") + from_path(config_files[0].as_path()).map_err(ConfigError::LoadConfigError)?; + CONFIG_INITIALIZED.store(true, std::sync::atomic::Ordering::Relaxed); + Ok(()) }