use super::hash::Sha256;
pub fn collect_relevant_env_vars() -> Vec<(String, String)> {
let mut relevant_env_keys: Vec<String> = std::env::vars()
.filter_map(|(k, _)| {
if k == "CARGO_MANIFEST_DIR"
|| k == "CARGO_TARGET_DIR"
|| k == "CARGO_MAKEFLAGS"
|| k == "MAKEFLAGS"
|| k == "CARGO_HOME"
|| k == "CARGO"
{
None
} else if k.starts_with("CARGO_")
|| k.starts_with("RUST_")
|| k.starts_with("CLIPPY_")
|| k == "RUSTFLAGS"
|| k == "CARGO_ENCODED_RUSTFLAGS"
|| k == "RUSTC_WRAPPER"
|| k == "RUSTC_WORKSPACE_WRAPPER"
|| k == "RUSTDOCFLAGS"
|| k == "TARGET"
|| k == "HOST"
|| k == "PROFILE"
{
Some(k)
} else {
None
}
})
.collect();
relevant_env_keys.sort();
relevant_env_keys
.into_iter()
.filter_map(|k| std::env::var(&k).ok().map(|v| (k, v)))
.collect()
}
pub fn compute_effective_env_hash() -> String {
let vars = collect_relevant_env_vars();
let mut payload = String::new();
for (k, v) in vars {
payload.push_str(&format!("{}={}\n", k, v));
}
Sha256::digest(payload.as_bytes())
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex;
static ENV_MUTEX: Mutex<()> = Mutex::new(());
#[test]
fn test_collect_relevant_env_vars_filtering() {
let _lock = ENV_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
std::env::set_var("CARGO_PKG_NAME", "test-pkg");
std::env::set_var("RUSTFLAGS", "--cfg foo");
std::env::set_var("MAKEFLAGS", "ignore_me");
let vars = collect_relevant_env_vars();
let keys: Vec<&str> = vars.iter().map(|(k, _)| k.as_str()).collect();
assert!(keys.contains(&"CARGO_PKG_NAME"));
assert!(keys.contains(&"RUSTFLAGS"));
assert!(!keys.contains(&"MAKEFLAGS"));
}
#[test]
fn test_compute_effective_env_hash_deterministic() {
let _lock = ENV_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
let h1 = compute_effective_env_hash();
let h2 = compute_effective_env_hash();
assert_eq!(h1, h2);
assert_eq!(h1.len(), 64);
}
}