use std::fs;
use std::path::{Path, PathBuf};
use sha2::{Digest, Sha256};
fn collect_files(dir: &Path, out: &mut Vec<PathBuf>) {
let entries =
fs::read_dir(dir).unwrap_or_else(|e| panic!("build.rs: cannot read dir {dir:?}: {e}"));
for entry in entries {
let path = entry.expect("build.rs: dir entry").path();
if path.is_dir() {
collect_files(&path, out);
} else {
out.push(path);
}
}
}
fn hash_file(hasher: &mut Sha256, label: &str, path: &Path, required: bool) {
let bytes = match fs::read(path) {
Ok(b) => b,
Err(_) if !required => Vec::new(),
Err(e) => panic!("build.rs: cannot read {path:?}: {e}"),
};
hasher.update(label.as_bytes());
hasher.update((bytes.len() as u64).to_le_bytes());
hasher.update(&bytes);
}
fn main() {
let mut hasher = Sha256::new();
let mut files = Vec::new();
collect_files(Path::new("src"), &mut files);
files.sort();
for path in &files {
hash_file(&mut hasher, &path.to_string_lossy(), path, true);
}
hash_file(&mut hasher, "Cargo.toml", Path::new("Cargo.toml"), true);
hash_file(&mut hasher, "Cargo.lock", Path::new("../Cargo.lock"), false);
let digest = hasher.finalize();
println!("cargo:rustc-env=DEMYSTIFY_SRC_HASH={digest:x}");
println!("cargo:rerun-if-changed=src");
println!("cargo:rerun-if-changed=Cargo.toml");
println!("cargo:rerun-if-changed=../Cargo.lock");
println!("cargo:rerun-if-changed=build.rs");
}