From 03436b7f8f6dc18be74a1df98a921d011578b761 Mon Sep 17 00:00:00 2001 From: slowsage <84777606+slowsage@users.noreply.github.com> Date: Thu, 1 Jun 2023 03:15:49 -0400 Subject: [PATCH] fix: Handle '# [include]'. Update default config (#450) --- config.example.toml | 2 +- src/config.rs | 46 ++++++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/config.example.toml b/config.example.toml index 62c2744a..3919317e 100644 --- a/config.example.toml +++ b/config.example.toml @@ -1,7 +1,7 @@ # Include any additional configuration file(s) # [include] sections are processed in the order you write them # Files in $CONFIG_DIR/topgrade/topgrade.d/ are automatically included at the beginning of this file -[include] +#[include] #paths = ["/etc/topgrade.toml"] [misc] diff --git a/src/config.rs b/src/config.rs index d4ee58e2..a8d332a9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -198,8 +198,8 @@ pub enum Step { #[derive(Deserialize, Default, Debug, Merge)] #[serde(deny_unknown_fields)] pub struct Include { - #[merge(strategy = merge::vec::append)] - paths: Vec, + #[merge(strategy = crate::utils::merge_strategies::vec_prepend_opt)] + paths: Option>, } #[derive(Deserialize, Default, Debug, Merge)] @@ -611,7 +611,7 @@ impl ConfigFile { // To parse [include] sections in the order as they are written, // we split the file and parse each part as a separate file - let regex_match_include = Regex::new(r"\[include]").expect("Failed to compile regex"); + let regex_match_include = Regex::new(r"^\s*\[include]").expect("Failed to compile regex"); let contents_split = regex_match_include.split_inclusive_left(contents_non_split.as_str()); for contents in contents_split { @@ -622,25 +622,29 @@ impl ConfigFile { if let Some(includes) = &config_file_include_only.include { // Parses the [include] section present in the slice - for include in includes.paths.iter().rev() { - let include_path = shellexpand::tilde::<&str>(&include.as_ref()).into_owned(); - let include_path = PathBuf::from(include_path); - let include_contents = match fs::read_to_string(&include_path) { - Ok(c) => c, - Err(e) => { - tracing::error!("Unable to read {}: {}", include_path.display(), e); - continue; - } - }; - match toml::from_str::(&include_contents) { - Ok(include_parsed) => result.merge(include_parsed), - Err(e) => { - tracing::error!("Failed to deserialize {}: {}", include_path.display(), e); - continue; - } - }; + if let Some(ref paths) = includes.paths { + for include in paths.iter().rev() { + let include_path = shellexpand::tilde::<&str>(&include.as_ref()).into_owned(); + let include_path = PathBuf::from(include_path); + let include_contents = match fs::read_to_string(&include_path) { + Ok(c) => c, + Err(e) => { + tracing::error!("Unable to read {}: {}", include_path.display(), e); + continue; + } + }; + match toml::from_str::(&include_contents) { + Ok(include_parsed) => result.merge(include_parsed), + Err(e) => { + tracing::error!("Failed to deserialize {}: {}", include_path.display(), e); + continue; + } + }; - debug!("Configuration include found: {}", include_path.display()); + debug!("Configuration include found: {}", include_path.display()); + } + } else { + debug!("No include paths found in {}", config_path.display()); } }