diff --git a/src/apply.rs b/src/apply.rs index 3d8e93a..d6e3f28 100644 --- a/src/apply.rs +++ b/src/apply.rs @@ -5,25 +5,59 @@ use tokio::fs; use crate::base64_decode; -pub async fn files(files: &[crate::File], root: &str) -> Result<()> { +pub async fn files(files: &[crate::File], root: &str, dry_run: bool) -> Result<()> { for file in files { let path = chroot(root, &file.path); let path = Path::new(&path); - if let Some(parent) = path.parent() { + if !dry_run && let Some(parent) = path.parent() { fs::create_dir_all(parent).await?; } use crate::FileKind as K; match &file.kind { - K::Content(content) => fs::write(path, content.as_bytes()).await?, + K::Content(content) => { + if dry_run { + info!( + "would create {} ({} bytes from content)", + file.path, + content.len() + ); + } else { + fs::write(path, content.as_bytes()).await?; + } + } K::Content64(content) => { let content = base64_decode(content)?; - fs::write(path, content).await? + if dry_run { + info!( + "would create {} ({} bytes from content64)", + file.path, + content.len() + ); + } else { + fs::write(path, content).await? + } + } + K::Dir(true) => { + if dry_run { + info!("would create {} (directory)", file.path); + } else { + fs::create_dir(path).await?; + } } - K::Dir(true) => fs::create_dir(path).await?, K::Dir(false) => {} // shouldn't happen, but semantic is to ignore - K::Symlink(tgt) => fs::symlink(tgt, path).await?, + K::Symlink(tgt) => { + if dry_run { + info!("would create {} (symlink to {})", file.path, tgt); + } else { + fs::symlink(tgt, path).await?; + } + } + } + + if dry_run { + continue; } match file.kind { diff --git a/src/bin/dkl.rs b/src/bin/dkl.rs index cbe4f19..e9e6de3 100644 --- a/src/bin/dkl.rs +++ b/src/bin/dkl.rs @@ -24,6 +24,9 @@ enum Command { /// path prefix (aka chroot) #[arg(short = 'P', long, default_value = "/")] prefix: String, + /// don't really write files + #[arg(long)] + dry_run: bool, }, Logger { /// Path where the logs are stored @@ -97,9 +100,10 @@ async fn main() -> Result<()> { config, filters, prefix, + dry_run, } => { let filters = parse_globs(&filters)?; - apply_config(&config, &filters, &prefix).await + apply_config(&config, &filters, &prefix, dry_run).await } C::Logger { ref log_path, @@ -156,7 +160,12 @@ async fn main() -> Result<()> { } } -async fn apply_config(config_file: &str, filters: &[glob::Pattern], chroot: &str) -> Result<()> { +async fn apply_config( + config_file: &str, + filters: &[glob::Pattern], + chroot: &str, + dry_run: bool, +) -> Result<()> { let config = fs::read_to_string(config_file).await?; let config: dkl::Config = serde_yaml::from_str(&config)?; @@ -168,7 +177,7 @@ async fn apply_config(config_file: &str, filters: &[glob::Pattern], chroot: &str .collect() }; - dkl::apply::files(&files, chroot).await + dkl::apply::files(&files, chroot, dry_run).await } #[derive(Subcommand)] diff --git a/src/dynlay.rs b/src/dynlay.rs index 7221416..cb01273 100644 --- a/src/dynlay.rs +++ b/src/dynlay.rs @@ -1,4 +1,4 @@ -use eyre::{format_err, Result}; +use eyre::{Result, format_err}; use log::{debug, error, info, warn}; use std::path::PathBuf; use tokio::{fs, io::AsyncWriteExt, process::Command}; diff --git a/src/lib.rs b/src/lib.rs index dd31d3d..78bbb7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,6 @@ impl Config { } pub fn base64_decode(s: &str) -> Result, base64::DecodeError> { - use base64::{prelude::BASE64_STANDARD_NO_PAD as B64, Engine}; + use base64::{Engine, prelude::BASE64_STANDARD_NO_PAD as B64}; B64.decode(s.trim_end_matches('=')) } diff --git a/src/logger.rs b/src/logger.rs index 9c79700..18502d0 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,6 +1,6 @@ use async_compression::tokio::write::{ZstdDecoder, ZstdEncoder}; use chrono::{DurationRound, TimeDelta, Utc}; -use eyre::{format_err, Result}; +use eyre::{Result, format_err}; use log::{debug, error, warn}; use std::path::{Path, PathBuf}; use std::process::Stdio; @@ -9,7 +9,7 @@ use tokio::{ io::{self, AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader, BufWriter}, process, sync::mpsc, - time::{sleep, Duration}, + time::{Duration, sleep}, }; pub type Timestamp = chrono::DateTime;