use std::{
collections::BTreeMap,
path::{Path, PathBuf},
};
pub const CACHE_ENV_PREFIX: &str = "HCI_CACHE_";
#[derive(Debug, Clone, Default)]
pub struct PreparedCaches {
pub env: BTreeMap<String, String>,
pub dirs: Vec<PathBuf>,
}
#[must_use]
pub fn prepare_caches(paths: &[String], cache_root: &Path) -> PreparedCaches {
let mut prepared = PreparedCaches::default();
let mut used = BTreeMap::<String, u32>::new();
for path in paths {
let base = slot_name(path);
let slot = match used.get_mut(&base) {
Some(count) => {
*count += 1;
format!("{base}_{count}")
}
None => {
used.insert(base.clone(), 0);
base
}
};
let directory = cache_root.join(&slot);
if std::fs::create_dir_all(&directory).is_err() {
continue;
}
prepared.env.insert(
format!("{CACHE_ENV_PREFIX}{slot}"),
directory.display().to_string(),
);
prepared.dirs.push(directory);
}
prepared
}
fn slot_name(path: &str) -> String {
let mut output = String::with_capacity(path.len());
let mut separated = true;
for character in path.chars() {
if character.is_ascii_alphanumeric() {
output.push(character.to_ascii_uppercase());
separated = false;
} else if !separated {
output.push('_');
separated = true;
}
}
while output.ends_with('_') {
output.pop();
}
if output.is_empty() {
"CACHE".to_string()
} else {
output
}
}