use crate::{Error, Result};
use std::path::PathBuf;
pub fn state_dir() -> Result<PathBuf> {
if let Ok(dir) = std::env::var("CUENV_STATE_DIR")
&& !dir.is_empty()
{
return Ok(PathBuf::from(dir));
}
let base = dirs::state_dir()
.or_else(dirs::data_dir)
.ok_or_else(|| Error::configuration("Could not determine state directory"))?;
Ok(base.join("cuenv"))
}
pub fn cache_dir() -> Result<PathBuf> {
if let Ok(dir) = std::env::var("CUENV_CACHE_DIR")
&& !dir.is_empty()
{
return Ok(PathBuf::from(dir));
}
let base = dirs::cache_dir()
.ok_or_else(|| Error::configuration("Could not determine cache directory"))?;
Ok(base.join("cuenv"))
}
pub fn runtime_dir() -> Result<PathBuf> {
if let Ok(dir) = std::env::var("CUENV_RUNTIME_DIR")
&& !dir.is_empty()
{
return Ok(PathBuf::from(dir));
}
let base = dirs::runtime_dir().unwrap_or_else(std::env::temp_dir);
Ok(base.join("cuenv"))
}
pub fn hook_state_dir() -> Result<PathBuf> {
Ok(state_dir()?.join("state"))
}
pub fn approvals_file() -> Result<PathBuf> {
Ok(state_dir()?.join("approved.json"))
}
pub fn task_cache_dir() -> Result<PathBuf> {
Ok(cache_dir()?.join("tasks"))
}
pub fn coordinator_socket() -> Result<PathBuf> {
Ok(runtime_dir()?.join("coordinator.sock"))
}
pub fn coordinator_pid() -> Result<PathBuf> {
Ok(runtime_dir()?.join("coordinator.pid"))
}
pub fn coordinator_lock() -> Result<PathBuf> {
Ok(runtime_dir()?.join("coordinator.lock"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_dir_default() {
temp_env::with_var_unset("CUENV_STATE_DIR", || {
let dir = state_dir().expect("state_dir should succeed");
assert!(dir.ends_with("cuenv"), "Should end with cuenv: {:?}", dir);
});
}
#[test]
fn test_state_dir_override() {
let test_dir = "/tmp/cuenv-test-state";
temp_env::with_var("CUENV_STATE_DIR", Some(test_dir), || {
let dir = state_dir().expect("state_dir should succeed");
assert_eq!(dir, PathBuf::from(test_dir));
});
}
#[test]
fn test_cache_dir_default() {
temp_env::with_var_unset("CUENV_CACHE_DIR", || {
let dir = cache_dir().expect("cache_dir should succeed");
assert!(dir.ends_with("cuenv"), "Should end with cuenv: {:?}", dir);
});
}
#[test]
fn test_cache_dir_override() {
let test_dir = "/tmp/cuenv-test-cache";
temp_env::with_var("CUENV_CACHE_DIR", Some(test_dir), || {
let dir = cache_dir().expect("cache_dir should succeed");
assert_eq!(dir, PathBuf::from(test_dir));
});
}
#[test]
fn test_runtime_dir_default() {
temp_env::with_var_unset("CUENV_RUNTIME_DIR", || {
let dir = runtime_dir().expect("runtime_dir should succeed");
assert!(dir.ends_with("cuenv"), "Should end with cuenv: {:?}", dir);
});
}
#[test]
fn test_runtime_dir_override() {
let test_dir = "/tmp/cuenv-test-runtime";
temp_env::with_var("CUENV_RUNTIME_DIR", Some(test_dir), || {
let dir = runtime_dir().expect("runtime_dir should succeed");
assert_eq!(dir, PathBuf::from(test_dir));
});
}
#[test]
fn test_hook_state_dir() {
temp_env::with_var_unset("CUENV_STATE_DIR", || {
let dir = hook_state_dir().expect("hook_state_dir should succeed");
assert!(dir.ends_with("state"), "Should end with state: {:?}", dir);
});
}
#[test]
fn test_approvals_file() {
temp_env::with_var_unset("CUENV_STATE_DIR", || {
let file = approvals_file().expect("approvals_file should succeed");
assert!(
file.ends_with("approved.json"),
"Should end with approved.json: {:?}",
file
);
});
}
#[test]
fn test_task_cache_dir() {
temp_env::with_var_unset("CUENV_CACHE_DIR", || {
let dir = task_cache_dir().expect("task_cache_dir should succeed");
assert!(dir.ends_with("tasks"), "Should end with tasks: {:?}", dir);
});
}
#[test]
fn test_coordinator_paths() {
temp_env::with_var_unset("CUENV_RUNTIME_DIR", || {
let socket = coordinator_socket().expect("coordinator_socket should succeed");
let pid = coordinator_pid().expect("coordinator_pid should succeed");
let lock = coordinator_lock().expect("coordinator_lock should succeed");
assert!(
socket.ends_with("coordinator.sock"),
"Socket should end with coordinator.sock: {:?}",
socket
);
assert!(
pid.ends_with("coordinator.pid"),
"PID should end with coordinator.pid: {:?}",
pid
);
assert!(
lock.ends_with("coordinator.lock"),
"Lock should end with coordinator.lock: {:?}",
lock
);
});
}
}