Compare commits
3 Commits
e5403dbc66
...
554c1e9cf4
Author | SHA1 | Date |
---|---|---|
|
554c1e9cf4 | |
|
09bd82d1df | |
|
1099fa40c7 |
|
@ -300,6 +300,12 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humansize"
|
name = "humansize"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
|
@ -923,6 +929,7 @@ dependencies = [
|
||||||
"argparse",
|
"argparse",
|
||||||
"blake2",
|
"blake2",
|
||||||
"file-mode",
|
"file-mode",
|
||||||
|
"hex",
|
||||||
"pwd-grp",
|
"pwd-grp",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
|
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||||
argparse = "0.2.2"
|
argparse = "0.2.2"
|
||||||
blake2 = "0.10.6"
|
blake2 = "0.10.6"
|
||||||
file-mode = { version = "0.1.2", features = ["serde"] }
|
file-mode = { version = "0.1.2", features = ["serde"] }
|
||||||
|
hex = "0.4.3"
|
||||||
pwd-grp = "0.1.1"
|
pwd-grp = "0.1.1"
|
||||||
serde = { version = "1.0.195", features = ["derive"] }
|
serde = { version = "1.0.195", features = ["derive"] }
|
||||||
serde_yaml = "0.9.30"
|
serde_yaml = "0.9.30"
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
FROM registry.fedoraproject.org/fedora-minimal:39 AS build
|
FROM docker.io/library/rust:1.73-alpine AS build
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/var/cache \
|
RUN --mount=type=cache,target=/var/cache \
|
||||||
microdnf install -y \
|
apk add \
|
||||||
--setopt install_weak_deps=0 \
|
musl-dev \
|
||||||
cargo\
|
|
||||||
&& :
|
&& :
|
||||||
|
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
RUN cargo build --release --locked
|
RUN cargo build --release --locked \
|
||||||
|
&& strip target/release/tmpl
|
||||||
|
|
||||||
|
|
||||||
FROM registry.fedoraproject.org/fedora-minimal:39
|
FROM scratch
|
||||||
|
|
||||||
COPY --from=build /src/target/release/tmpl /usr/local/bin
|
COPY --from=build /src/target/release/tmpl /tmpl
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/tmpl"]
|
ENTRYPOINT ["/tmpl"]
|
||||||
|
|
||||||
LABEL name='tmpl' \
|
LABEL name='tmpl' \
|
||||||
vendor='Dustin C. Hatch' \
|
vendor='Dustin C. Hatch' \
|
||||||
|
|
43
src/main.rs
43
src/main.rs
|
@ -1,7 +1,7 @@
|
||||||
mod model;
|
mod model;
|
||||||
mod templating;
|
mod templating;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::BTreeSet;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -12,7 +12,7 @@ use serde::de::DeserializeOwned;
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
use shlex::Shlex;
|
use shlex::Shlex;
|
||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
use model::Instructions;
|
use model::Instructions;
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ fn process_instructions(
|
||||||
);
|
);
|
||||||
|
|
||||||
let ctx = Context::from_serialize(&values)?;
|
let ctx = Context::from_serialize(&values)?;
|
||||||
let mut post_hooks = HashSet::new();
|
let mut post_hooks = BTreeSet::new();
|
||||||
for i in instructions.render {
|
for i in instructions.render {
|
||||||
let out = match tera.render(&i.template, &ctx) {
|
let out = match tera.render(&i.template, &ctx) {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -161,13 +161,18 @@ fn process_instructions(
|
||||||
};
|
};
|
||||||
let mut dest = PathBuf::from(destdir.as_ref());
|
let mut dest = PathBuf::from(destdir.as_ref());
|
||||||
dest.push(i.dest.strip_prefix("/").unwrap_or(i.dest.as_path()));
|
dest.push(i.dest.strip_prefix("/").unwrap_or(i.dest.as_path()));
|
||||||
let orig_cksm = checksum(&dest).ok();
|
let changed = match write_file(&dest, out.as_bytes()) {
|
||||||
if let Err(e) = write_file(&dest, out.as_bytes()) {
|
Ok(c) => c,
|
||||||
error!("Failed to write output file {}: {}", dest.display(), e);
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"Failed to write output file {}: {}",
|
||||||
|
dest.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let new_cksm = checksum(&dest).ok();
|
};
|
||||||
if orig_cksm != new_cksm {
|
if changed {
|
||||||
info!("File {} was changed", dest.display());
|
info!("File {} was changed", dest.display());
|
||||||
if let Some(hooks) = i.hooks {
|
if let Some(hooks) = i.hooks {
|
||||||
if let Some(changed) = hooks.changed {
|
if let Some(changed) = hooks.changed {
|
||||||
|
@ -219,19 +224,37 @@ fn process_instructions(
|
||||||
fn write_file(
|
fn write_file(
|
||||||
dest: impl AsRef<Path>,
|
dest: impl AsRef<Path>,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<bool, std::io::Error> {
|
||||||
if let Some(p) = dest.as_ref().parent() {
|
if let Some(p) = dest.as_ref().parent() {
|
||||||
if !p.exists() {
|
if !p.exists() {
|
||||||
info!("Creating directory {}", p.display());
|
info!("Creating directory {}", p.display());
|
||||||
std::fs::create_dir_all(p)?;
|
std::fs::create_dir_all(p)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Ok(orig_cksm) = checksum(&dest) {
|
||||||
|
trace!(
|
||||||
|
"Original checksum: {}: {}",
|
||||||
|
dest.as_ref().display(),
|
||||||
|
hex::encode(&orig_cksm)
|
||||||
|
);
|
||||||
|
let mut blake = Blake2b512::new();
|
||||||
|
blake.update(data);
|
||||||
|
let new_cksm = blake.finalize().to_vec();
|
||||||
|
trace!(
|
||||||
|
"New checksum: {}: {}",
|
||||||
|
dest.as_ref().display(),
|
||||||
|
hex::encode(&new_cksm)
|
||||||
|
);
|
||||||
|
if orig_cksm == new_cksm {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
debug!("Writing output: {}", dest.as_ref().display());
|
debug!("Writing output: {}", dest.as_ref().display());
|
||||||
let mut f = std::fs::File::create(&dest)?;
|
let mut f = std::fs::File::create(&dest)?;
|
||||||
f.write_all(data)?;
|
f.write_all(data)?;
|
||||||
let size = f.stream_position()?;
|
let size = f.stream_position()?;
|
||||||
debug!("Wrote output: {} ({} bytes)", dest.as_ref().display(), size);
|
debug!("Wrote output: {} ({} bytes)", dest.as_ref().display(), size);
|
||||||
Ok(())
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chown(
|
fn chown(
|
||||||
|
|
Loading…
Reference in New Issue