Add diffview with confirm for applied configurations

main
trivernis 10 months ago
parent 99deb162b1
commit 458bd6476a
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

253
Cargo.lock generated

@ -160,6 +160,193 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chksum"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c56300de3d4b6e12639a862e3a9320b4ea50321689f869c7e3d7bbf2f0f5f95c"
dependencies = [
"chksum-core",
"chksum-hash",
"chksum-md5",
"chksum-sha1",
"chksum-sha2",
]
[[package]]
name = "chksum-core"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6db20071fdeca52ed6a7745519fb2d343fddcb93af81448373b851f072aaec5"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74fca0f0064c8c996eb06d803eca772b12cc8f77b53d92103fc457713fe18389"
dependencies = [
"chksum-hash-core",
"chksum-hash-md5",
"chksum-hash-sha1",
"chksum-hash-sha2",
]
[[package]]
name = "chksum-hash-core"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "221456234d441c788a2c51a27b91c4380f499de560670a67d3303e621d37b3bd"
[[package]]
name = "chksum-hash-md5"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80c33d01c33c9e193fe33e719a29a7eb900c08583375dd1d3269991aacbe434a"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash-sha1"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62ae4186244a0990f1cde56d4bb8cc32571a601b065991fd48cce32556aaa1a9"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash-sha2"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b18cf27af5d9792412533d94b6ac54b5022d5e53521832a5c5d3bdc2decdcffc"
dependencies = [
"chksum-hash-sha2-224",
"chksum-hash-sha2-256",
"chksum-hash-sha2-384",
"chksum-hash-sha2-512",
]
[[package]]
name = "chksum-hash-sha2-224"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb4a205ae2433218c6d8677a384ac0bd27a794c49d9b3febbecd1ebaa9864b44"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash-sha2-256"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b99b9b29d0cf25fbbb72ea8ff4b89492eb1a8d72a4599b64ec3699389cae81f9"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash-sha2-384"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "317fbe67e0f9fedff9994655e840e4b7495333680a5dde7c2dddb43e46bffcfa"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-hash-sha2-512"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9426c7c11aef475fddb9d1ad95539678ba882ff274e4b5d62e0c89b75b41ee5f"
dependencies = [
"chksum-hash-core",
"thiserror",
]
[[package]]
name = "chksum-md5"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95dda0f76fbb6069e042c370a928457086e1b4eabc7e75f5f49fe1b913634351"
dependencies = [
"chksum-core",
"chksum-hash-md5",
]
[[package]]
name = "chksum-sha1"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01c47aa947fb8d8649bf9e942a5ff4ec63a550df087433976e266512d2b38dc"
dependencies = [
"chksum-core",
"chksum-hash-sha1",
]
[[package]]
name = "chksum-sha2"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aac0e41b69be74dad939bb277d2b13b6bc9b1e406c62ce6e62eff8a29a106e68"
dependencies = [
"chksum-core",
"chksum-hash-sha2",
"chksum-sha2-224",
"chksum-sha2-256",
"chksum-sha2-384",
"chksum-sha2-512",
]
[[package]]
name = "chksum-sha2-224"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc70344710cfe7cc696cfbbebbc50584f76a46d7bf29737a58b48e61a15ae31f"
dependencies = [
"chksum-core",
"chksum-hash-sha2-224",
]
[[package]]
name = "chksum-sha2-256"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38ac7f7e93115d4edc71e73c83b1bd3038fdd01525f635f78815956567d0f7ab"
dependencies = [
"chksum-core",
"chksum-hash-sha2-256",
]
[[package]]
name = "chksum-sha2-384"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49ace9dacad0683db9cc7d71c270ff858c86b939729074d6ab6379e8e2c1c7fc"
dependencies = [
"chksum-core",
"chksum-hash-sha2-384",
]
[[package]]
name = "chksum-sha2-512"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5c7acaafd327334c22d591177e5eb3f36eb85a42489fa1544c1f4d867bc7899"
dependencies = [
"chksum-core",
"chksum-hash-sha2-512",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.14" version = "4.4.14"
@ -206,6 +393,19 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.12" version = "0.2.12"
@ -225,6 +425,19 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "dialoguer"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de"
dependencies = [
"console",
"shell-words",
"tempfile",
"thiserror",
"zeroize",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@ -256,6 +469,12 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.10.1" version = "0.10.1"
@ -285,6 +504,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]] [[package]]
name = "figment" name = "figment"
version = "0.10.13" version = "0.10.13"
@ -884,11 +1109,19 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]] [[package]]
name = "silo" name = "silo"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chksum",
"clap", "clap",
"dialoguer",
"dirs", "dirs",
"figment", "figment",
"git2", "git2",
@ -902,6 +1135,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sys-info", "sys-info",
"tempfile",
"toml", "toml",
] ]
@ -966,6 +1200,19 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "tempfile"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall",
"rustix",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.4.1" version = "1.4.1"
@ -1331,3 +1578,9 @@ name = "yansi"
version = "1.0.0-rc.1" version = "1.0.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377"
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"

@ -6,7 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
chksum = "0.3.0"
clap = { version = "4.4.14", features = ["derive", "env"] } clap = { version = "4.4.14", features = ["derive", "env"] }
dialoguer = "0.11.0"
dirs = "5.0.1" dirs = "5.0.1"
figment = { version = "0.10.13", features = ["toml", "env"] } figment = { version = "0.10.13", features = ["toml", "env"] }
git2 = "0.18.1" git2 = "0.18.1"
@ -20,4 +22,5 @@ pretty_env_logger = "0.5.0"
serde = { version = "1.0.195", features = ["derive"] } serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111" serde_json = "1.0.111"
sys-info = "0.9.1" sys-info = "0.9.1"
tempfile = "3.9.0"
toml = "0.8.8" toml = "0.8.8"

@ -1,12 +1,17 @@
use chksum::sha2_256::chksum;
use dialoguer::Confirm;
use globset::{Glob, GlobSet, GlobSetBuilder}; use globset::{Glob, GlobSet, GlobSetBuilder};
use miette::{bail, Context, IntoDiagnostic, Result}; use miette::{bail, Context, IntoDiagnostic, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
env, env,
fs::{self}, fs::{self, File},
io::Write,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::Command,
rc::Rc, rc::Rc,
}; };
use tempfile::NamedTempFile;
use crate::{ use crate::{
config::{read_config, SiloConfig}, config::{read_config, SiloConfig},
@ -202,17 +207,29 @@ impl FileEntry {
let filename = new_path.file_name().unwrap(); let filename = new_path.file_name().unwrap();
let dest = cwd.join(filename); let dest = cwd.join(filename);
templating::render_to_file(&dest, &contents, &ctx.config.template_context)?; let render_contents = templating::render(&contents, &ctx.config.template_context)?;
if confirm_changes(&ctx.config.diff_tool, &render_contents, &dest)? {
log::info!("Render {path:?} -> {dest:?}"); log::info!("Render {path:?} -> {dest:?}");
fs::write(&dest, render_contents)
.into_diagnostic()
.context("writing changes")?;
} else {
log::info!("Skipping {path:?} !-> {dest:?}");
}
} }
FileEntry::Plain(path) => { FileEntry::Plain(path) => {
let filename = path.file_name().unwrap(); let filename = path.file_name().unwrap();
let dest = cwd.join(filename); let dest = cwd.join(filename);
log::info!("Copying {path:?} -> {dest:?}");
if confirm_write(&ctx.config.diff_tool, path, &dest)? {
log::info!("Copying {path:?} -> {dest:?}");
fs::copy(path, &dest) fs::copy(path, &dest)
.into_diagnostic() .into_diagnostic()
.with_context(|| format!("copy {path:?} to {dest:?}"))?; .with_context(|| format!("copy {path:?} to {dest:?}"))?;
} else {
log::info!("Skipping {path:?} !-> {dest:?}");
}
} }
} }
@ -247,3 +264,42 @@ impl RootDirData {
.with_context(|| format!("parsing metadata file {path:?}")) .with_context(|| format!("parsing metadata file {path:?}"))
} }
} }
fn confirm_changes(diff_tool: &str, changes: &str, original: &Path) -> Result<bool> {
let mut tmp = NamedTempFile::new()
.into_diagnostic()
.context("create tmp file")?;
tmp.write_all(changes.as_bytes())
.into_diagnostic()
.context("write tmp file")?;
confirm_write(diff_tool, &tmp.into_temp_path(), original)
}
fn confirm_write(diff_tool: &str, a: &Path, b: &Path) -> Result<bool> {
if !b.exists() {
return Ok(true);
}
let f1 = File::open(a)
.into_diagnostic()
.with_context(|| format!("opening file {a:?}"))?;
let f2 = File::open(b)
.into_diagnostic()
.with_context(|| format!("opening file {b:?}"))?;
if chksum(f1).into_diagnostic()?.as_bytes() == chksum(f2).into_diagnostic()?.as_bytes() {
return Ok(true);
}
Command::new(diff_tool)
.arg(b)
.arg(a)
.spawn()
.into_diagnostic()
.context("spawn diff tool")?
.wait()
.into_diagnostic()
.context("wait for diff tool to exit")?;
Confirm::new()
.with_prompt("Do you want to apply these changes?")
.interact()
.into_diagnostic()
}

@ -1,9 +1,4 @@
use std::{ use std::{env, path::PathBuf};
env,
fs::File,
io::BufWriter,
path::{Path, PathBuf},
};
use handlebars::Handlebars; use handlebars::Handlebars;
use handlebars_switch::SwitchHelper; use handlebars_switch::SwitchHelper;
@ -11,18 +6,6 @@ use lazy_static::lazy_static;
use miette::{Context, IntoDiagnostic, Result}; use miette::{Context, IntoDiagnostic, Result};
use serde::Serialize; use serde::Serialize;
pub fn render_to_file<T: Serialize>(path: &Path, template: &str, ctx: T) -> Result<()> {
let file = File::create(path)
.into_diagnostic()
.context("creating file")?;
let writer = BufWriter::new(file);
engine()
.render_template_to_write(template, &context(ctx), writer)
.into_diagnostic()
.context("rendering to path")?;
Ok(())
}
pub fn render<T: Serialize>(template: &str, ctx: T) -> Result<String> { pub fn render<T: Serialize>(template: &str, ctx: T) -> Result<String> {
engine() engine()
.render_template(template, &context(ctx)) .render_template(template, &context(ctx))

Loading…
Cancel
Save