From 00c777812569f2fc0d1e285289106ebb1b3da5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Kafka?= <6414091+MatejKafka@users.noreply.github.com> Date: Sun, 5 Jan 2025 00:17:44 +0100 Subject: [PATCH] Resolve paths in config [directories] relative to the config directory (#395) --- src/config.rs | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/config.rs b/src/config.rs index 454fbf5..254b56d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -295,7 +295,7 @@ impl Config { /// /// For this, some values need to be converted to other types and some /// defaults need to be set (sometimes based on env variables). - fn from_raw(raw_config: RawConfig) -> Result { + fn from_raw(raw_config: RawConfig, relative_path_root: &Path) -> Result { let style = raw_config.style.into(); let display = raw_config.display.into(); let updates = raw_config.updates.into(); @@ -316,7 +316,9 @@ impl Config { } else if let Some(config_value) = raw_config.directories.cache_dir { // If the user explicitly configured a cache directory, use that. PathWithSource { - path: config_value, + // Resolve possible relative path. It would be nicer to clean up the path, but Rust stdlib + // does not give any method for that that does not need the paths to exist. + path: relative_path_root.join(config_value), source: PathSource::ConfigFile, } } else if let Ok(default_dir) = get_app_root(AppDataType::UserCache, &crate::APP_INFO) { @@ -333,7 +335,8 @@ impl Config { .directories .custom_pages_dir .map(|path| PathWithSource { - path, + // Resolve possible relative path. + path: relative_path_root.join(path), source: PathSource::ConfigFile, }) .or_else(|| { @@ -382,8 +385,12 @@ impl Config { RawConfig::new() }; - // Convert to config - let mut config = Self::from_raw(raw_config).context("Could not process raw config")?; + // Safe to unwrap, it's a file path, so it should have a directory component + let config_file_dir = config_file_path.parent().unwrap(); + + // Convert to config, resolve relative paths from the config file dir + let mut config = + Self::from_raw(raw_config, config_file_dir).context("Could not process raw config")?; // Potentially override styles if !enable_styles { @@ -474,3 +481,21 @@ fn test_serialize_deserialize() { let deserialized: RawConfig = toml::from_str(&serialized).unwrap(); assert_eq!(raw_config, deserialized); } + +#[test] +fn test_relative_path_resolution() { + let mut raw_config = RawConfig::new(); + raw_config.directories.cache_dir = Some("../cache".into()); + raw_config.directories.custom_pages_dir = Some("../custom_pages".into()); + + let config = Config::from_raw(raw_config, Path::new("/path/to/config")).unwrap(); + + assert_eq!( + config.directories.cache_dir.path(), + Path::new("/path/to/config/../cache") + ); + assert_eq!( + config.directories.custom_pages_dir.unwrap().path(), + Path::new("/path/to/config/../custom_pages") + ); +}