diff --git a/src/config/file.rs b/src/config/file.rs index c4e88fec6b..2696b48af1 100644 --- a/src/config/file.rs +++ b/src/config/file.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct FileConfig { pub path: String, @@ -46,3 +48,36 @@ impl FileConfig { self } } + +impl Display for FileConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.path)?; + if self.symlink { + write!(f, " -> {}", self.data)?; + } else if self.directory { + write!(f, " type=dir")?; + if self.recursive_chown { + write!(f, " chown=yes")?; + } + } else { + write!( + f, + " size={}B", + arg_parser::to_human_readable_string(self.data.len() as u64) + )?; + if self.postinstall { + write!(f, "!")?; + } + } + if let Some(uid) = self.uid { + write!(f, " uid={}", uid)?; + } + if let Some(uid) = self.uid { + write!(f, " gid={}", uid)?; + } + if let Some(mode) = self.mode { + write!(f, " mode={:3o}", mode)?; + } + Ok(()) + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index a1fe76de78..d6a04259ca 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,9 +1,11 @@ use std::collections::BTreeMap; +use std::fmt::Display; use std::fs; use std::mem; use std::path::{Path, PathBuf}; use anyhow::bail; +use anyhow::Context; use anyhow::Result; pub mod file; @@ -35,11 +37,11 @@ impl Config { Ok(config_data) => match toml::from_str(&config_data) { Ok(config) => config, Err(err) => { - bail!("{}: failed to decode: {}", path.display(), err); + bail!("failed to decode '{}': {}", path.display(), err); } }, Err(err) => { - bail!("{}: failed to read: {}", path.display(), err); + bail!("failed to read '{}': {}", path.display(), err); } }; @@ -47,7 +49,10 @@ impl Config { let mut configs = mem::take(&mut config.include) .into_iter() - .map(|path| Config::from_file(&config_dir.join(path))) + .map(|path| { + Config::from_file(&config_dir.join(&path)) + .with_context(|| format!("Importing from {}", path.display())) + }) .collect::>>()?; configs.push(config); // Put ourself last to ensure that it overwrites anything else. @@ -90,3 +95,22 @@ impl Config { } } } + +impl Display for Config { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "files:")?; + for file in &self.files { + writeln!(f, "- {}", file)?; + } + writeln!(f, "users:")?; + for (name, user) in &self.users { + writeln!(f, "- {}:{}", name, user)?; + } + write!(f, "packages: ")?; + for name in self.packages.keys() { + write!(f, " {}", name)?; + } + writeln!(f, "")?; + Ok(()) + } +} diff --git a/src/config/user.rs b/src/config/user.rs index 9e9393de0c..862bffad0b 100644 --- a/src/config/user.rs +++ b/src/config/user.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct UserConfig { pub password: Option, @@ -14,3 +16,28 @@ pub struct GroupConfig { // FIXME move this to the UserConfig struct as extra_groups pub members: Vec, } + +impl Display for UserConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(uid) = &self.uid { + write!(f, " uid={}", uid)?; + } + if let Some(gid) = &self.gid { + write!(f, " gid={}", gid)?; + } + if let Some(name) = &self.name { + write!(f, " name={}", name)?; + } + if let Some(home) = &self.home { + write!(f, " home={}", home)?; + } + if let Some(shell) = &self.shell { + write!(f, " shell={}", shell)?; + } + if self.password.as_ref().is_some_and(|s| !s.is_empty()) { + write!(f, " password=yes")?; + } + + Ok(()) + } +} diff --git a/src/installer.rs b/src/installer.rs index 727d8862ba..1b78403f8b 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -817,7 +817,7 @@ pub fn try_fast_install( } fn install_inner(config: Config, output: &Path) -> Result<()> { - println!("Install {config:#?} to {}", output.display()); + println!("Installing to {}:\n{}", output.display(), config); let cookbook = config.general.cookbook.clone(); let cookbook = cookbook.as_ref().map(|p| p.as_str()); if output.is_dir() {