diff --git a/src/config.rs b/src/config.rs index f3bb122..89d876b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,7 +3,11 @@ use std::{ path::{ PathBuf, }, + error, + fmt, + io }; +use tokio::fs; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Config @@ -17,8 +21,55 @@ impl Default for Config fn default() -> Self { Self { - base_dir: PathBuf::default(), + base_dir: PathBuf::from("/tmp/videl"), } } } +impl Config +{ + /// Validate this config + pub async fn validate(&self) -> Result<(), Error> + { + let exists = self.base_dir.exists(); + if exists && !self.base_dir.is_dir() { + return Err(Error::InvalidDestination); + } else if !exists { + fs::create_dir_all(&self.base_dir).await?; + } + Ok(()) + } +} + +#[derive(Debug)] +pub enum Error { + IO(io::Error), + InvalidDestination, +} +impl error::Error for Error +{ + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match &self { + Self::IO(io) => Some(io), + _ => None, + } + } +} +impl fmt::Display for Error +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + match self { + Self::IO(_) => write!(f, "i/o error"), + Self::InvalidDestination => write!(f, "invalid base destination for videl databases"), + } + } +} + +impl From for Error +{ + #[inline] fn from(from: io::Error) -> Self + { + Self::IO(from) + } +} diff --git a/src/main.rs b/src/main.rs index b87897c..ed942bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,10 +64,22 @@ async fn process(config: Arc, file: String) .with_suggestion(|| "Are you sure this database location is correct")); } +async fn validate_config(config: config::Config) -> eyre::Result +{ + config.validate().await + .with_section(|| format!("{:#?}", config).header("Config was")) + .with_suggestion(|| "Are you sure the base directory is a valid pathspec?") + .with_suggestion(|| "Are you sure the base directory is not already occupied by a non-directory?") + .with_suggestion(|| format!("Are you sure we have read-write access to {:?}?", config.base_dir))?; + Ok(config) +} + async fn begin() -> eyre::Result { install()?; - let config = Arc::new(config::Config::default()); + let config = Arc::new(validate_config(config::Config::default()).await + .wrap_err(eyre!("Failed to validate config"))?); + println!("Validated config OK"); if args::process(|file| { let config = Arc::clone(&config); process(config, file)