diff --git a/src/config.rs b/src/config.rs index 51b7bda..a78c5fd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,7 @@ use dirs; use log::{debug, error}; use serde::{Deserialize, Serialize}; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "lowercase")] @@ -542,6 +542,25 @@ impl Settings { settings.export_filename_format = args.item.export_filename_format.clone(); settings.import_data_file = args.item.import_data_file.clone(); + // Expand ~ in all path fields + settings.dir = Settings::expand_tilde(&settings.dir); + settings.import_data_file = settings + .import_data_file + .as_ref() + .map(|p| Settings::expand_tilde(p)); + if let Some(ref mut server) = settings.server { + server.password_file = server + .password_file + .as_ref() + .map(|p| Settings::expand_tilde(p)); + server.jwt_secret_file = server + .jwt_secret_file + .as_ref() + .map(|p| Settings::expand_tilde(p)); + server.cert_file = server.cert_file.as_ref().map(|p| Settings::expand_tilde(p)); + server.key_file = server.key_file.as_ref().map(|p| Settings::expand_tilde(p)); + } + debug!("CONFIG: Final settings: {settings:?}"); Ok(settings) } @@ -562,6 +581,24 @@ impl Settings { Ok(path) } + /// Expand a leading `~` in a path to the user's home directory. + /// + /// Returns the path unchanged if it doesn't start with `~` or if the + /// home directory cannot be determined. + fn expand_tilde(path: &Path) -> PathBuf { + let path_str = path.to_string_lossy(); + if let Some(rest) = path_str.strip_prefix("~/") { + if let Some(home) = dirs::home_dir() { + return home.join(rest); + } + } else if path_str == "~" { + if let Some(home) = dirs::home_dir() { + return home; + } + } + path.to_path_buf() + } + /// Get server password from password_file or directly from config if configured pub fn get_server_password(&self) -> Result> { if let Some(server) = &self.server { @@ -753,3 +790,35 @@ impl Settings { .collect() } } + +#[cfg(test)] +mod tests { + use super::*; + use std::path::Path; + + #[test] + fn test_expand_tilde_with_slash() { + let home = dirs::home_dir().unwrap(); + let result = Settings::expand_tilde(Path::new("~/foo/bar")); + assert_eq!(result, home.join("foo/bar")); + } + + #[test] + fn test_expand_tilde_bare() { + let home = dirs::home_dir().unwrap(); + let result = Settings::expand_tilde(Path::new("~")); + assert_eq!(result, home); + } + + #[test] + fn test_expand_tilde_absolute() { + let result = Settings::expand_tilde(Path::new("/etc/keep")); + assert_eq!(result, PathBuf::from("/etc/keep")); + } + + #[test] + fn test_expand_tilde_relative() { + let result = Settings::expand_tilde(Path::new("foo/bar")); + assert_eq!(result, PathBuf::from("foo/bar")); + } +}