From 4aa06868699e63b39927079720dff30c3ee43f48 Mon Sep 17 00:00:00 2001 From: Aphek Date: Sun, 11 Jun 2023 23:50:42 -0300 Subject: [PATCH] Use global config files when user-specific file doesn't exist --- changelog/new.txt | 1 + src/config.rs | 61 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/changelog/new.txt b/changelog/new.txt index f2f6a60..f16a2f6 100644 --- a/changelog/new.txt +++ b/changelog/new.txt @@ -5,3 +5,4 @@ Breaking changes: Bugs fixed: New features: +- new global configuration paths are available, located at /etc/rustic/*.toml or %PROGRAMDATA%/rustic/config/*.toml, depending on your platform diff --git a/src/config.rs b/src/config.rs index 3baf275..162c987 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,7 @@ pub(crate) mod progress_options; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use directories::ProjectDirs; @@ -16,6 +16,7 @@ use abscissa_core::config::Config; use abscissa_core::path::AbsPathBuf; use abscissa_core::FrameworkError; use clap::Parser; +use itertools::Itertools; use rustic_core::RepositoryOptions; use serde::{Deserialize, Serialize}; @@ -50,29 +51,27 @@ pub struct RusticConfig { impl RusticConfig { pub fn merge_profile(&mut self, profile: &str) -> Result<(), FrameworkError> { - let mut path = ProjectDirs::from("", "", "rustic").map_or_else( - || Path::new(".").to_path_buf(), - |path| path.config_dir().to_path_buf(), - ); - if !path.exists() { - path = Path::new(".").to_path_buf(); - }; - let path = path.join(profile.to_string() + ".toml"); + let profile_filename = profile.to_string() + ".toml"; + let paths = get_config_paths(&profile_filename); - if path.exists() { + if let Some(path) = paths.iter().find(|path| path.exists()) { // TODO: This should be log::info! - however, the logging config // can be stored in the config file and is needed to initialize the logger eprintln!("using config {}", path.display()); - let mut config = Self::load_toml_file(AbsPathBuf::new(&path)?)?; + let mut config = Self::load_toml_file(AbsPathBuf::canonicalize(path)?)?; // if "use_profile" is defined in config file, merge the referenced profiles first for profile in &config.global.use_profile.clone() { config.merge_profile(profile)?; } self.merge(config); } else { + let paths_string = paths.iter().map(|path| path.display()).join(", "); // TODO: This should be log::warn! - however, the logging config // can be stored in the config file and is needed to initialize the logger - eprintln!("using no config file ({} doesn't exist)", path.display()); + eprintln!( + "using no config file, none of these exist: {}", + &paths_string + ); }; Ok(()) } @@ -112,3 +111,41 @@ pub struct GlobalOptions { #[serde(flatten)] pub progress_options: ProgressOptions, } + +fn get_config_paths(filename: &str) -> Vec { + [ + ProjectDirs::from("", "", "rustic") + .map(|project_dirs| project_dirs.config_dir().to_path_buf()), + get_global_config_path(), + Some(PathBuf::from(".")), + ] + .into_iter() + .filter_map(|path| { + path.map(|mut p| { + p.push(filename); + p + }) + }) + .collect() +} + +#[cfg(target_os = "windows")] +fn get_global_config_path() -> Option { + if let Some(program_data) = std::env::var_os("PROGRAMDATA") { + let mut path = PathBuf::from(program_data); + path.push(r"rustic\config"); + Some(path) + } else { + None + } +} + +#[cfg(any(target_os = "ios", target_arch = "wasm32"))] +fn get_global_config_path() -> Option { + None +} + +#[cfg(not(any(target_os = "windows", target_os = "ios", target_arch = "wasm32")))] +fn get_global_config_path() -> Option { + Some(PathBuf::from("/etc/rustic")) +}