use std::fs::{self, OpenOptions};
use std::path::{Path, PathBuf};
pub fn resolve_config_dir() -> PathBuf {
if let Ok(p) = std::env::var("AUTOCORE_CONFIG_DIR") {
let p = PathBuf::from(p);
let _ = fs::create_dir_all(&p);
return p;
}
let preferred = if cfg!(target_os = "windows") {
match std::env::var("PROGRAMDATA") {
Ok(d) => PathBuf::from(d).join("ADC").join("autocore").join("config"),
Err(_) => PathBuf::from("./target/autocore/config"),
}
} else {
PathBuf::from("/srv/autocore/config")
};
if dir_is_writable(&preferred) {
return preferred;
}
eprintln!(
"WARN: cannot write to {:?}; falling back to ./target/autocore/config",
preferred,
);
let fallback = PathBuf::from("./target/autocore/config");
let _ = fs::create_dir_all(&fallback);
fallback
}
fn dir_is_writable(dir: &Path) -> bool {
if fs::create_dir_all(dir).is_err() {
return false;
}
let probe = dir.join(".config_writable_probe");
match OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&probe)
{
Ok(_) => {
let _ = fs::remove_file(&probe);
true
}
Err(_) => false,
}
}
#[cfg(test)]
pub(crate) mod test_support {
use std::path::PathBuf;
use std::sync::{Mutex, MutexGuard};
static ENV_LOCK: Mutex<()> = Mutex::new(());
pub fn with_temp_config<F: FnOnce()>(tag: &str, f: F) {
let _guard: MutexGuard<()> = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
let dir =
std::env::temp_dir().join(format!("mechutil_cfg_{}_{}", tag, std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
unsafe { std::env::set_var("AUTOCORE_CONFIG_DIR", &dir) };
f();
unsafe { std::env::remove_var("AUTOCORE_CONFIG_DIR") };
let _ = std::fs::remove_dir_all(&dir);
}
pub fn current_dir() -> PathBuf {
PathBuf::from(std::env::var("AUTOCORE_CONFIG_DIR").expect("within with_temp_config"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn env_override_wins_and_is_created() {
test_support::with_temp_config("paths", || {
let dir = test_support::current_dir();
let resolved = resolve_config_dir();
assert_eq!(resolved, dir);
assert!(resolved.is_dir(), "resolve_config_dir should create the dir");
});
}
}