1use std::env;
8use std::path::PathBuf;
9
10pub fn agent_dir() -> PathBuf {
17 agent_dir_with(|name| env::var(name).ok())
18}
19
20pub fn agent_dir_with<F>(lookup: F) -> PathBuf
23where
24 F: Fn(&str) -> Option<String>,
25{
26 if let Some(raw) = lookup("CAPO_AGENT_DIR") {
27 return expand_tilde(&raw, &lookup);
28 }
29 if let Some(home) = lookup("HOME") {
30 return PathBuf::from(home).join(".capo").join("agent");
31 }
32 PathBuf::from(".capo").join("agent")
33}
34
35fn expand_tilde<F>(raw: &str, lookup: &F) -> PathBuf
36where
37 F: Fn(&str) -> Option<String>,
38{
39 let trimmed = raw.trim();
40 if trimmed == "~" {
41 return lookup("HOME")
42 .map(PathBuf::from)
43 .unwrap_or_else(|| PathBuf::from("~"));
44 }
45 if let Some(rest) = trimmed.strip_prefix("~/") {
46 if let Some(home) = lookup("HOME") {
47 return PathBuf::from(home).join(rest);
48 }
49 }
50 PathBuf::from(trimmed)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use std::collections::HashMap;
57
58 fn lookup(map: HashMap<&'static str, &'static str>) -> impl Fn(&str) -> Option<String> {
59 move |name| map.get(name).map(|v| (*v).to_string())
60 }
61
62 #[test]
63 fn agent_dir_uses_capo_agent_dir_env() {
64 let env = HashMap::from([("CAPO_AGENT_DIR", "/tmp/x")]);
65 assert_eq!(agent_dir_with(lookup(env)), PathBuf::from("/tmp/x"));
66 }
67
68 #[test]
69 fn agent_dir_expands_tilde_in_capo_agent_dir() {
70 let env = HashMap::from([("CAPO_AGENT_DIR", "~/.test-capo"), ("HOME", "/Users/wade")]);
71 assert_eq!(
72 agent_dir_with(lookup(env)),
73 PathBuf::from("/Users/wade/.test-capo")
74 );
75 }
76
77 #[test]
78 fn agent_dir_defaults_to_home_capo_agent() {
79 let env = HashMap::from([("HOME", "/Users/wade")]);
80 assert_eq!(
81 agent_dir_with(lookup(env)),
82 PathBuf::from("/Users/wade/.capo/agent")
83 );
84 }
85}