1use std::env;
10use std::fs;
11use std::path::PathBuf;
12
13fn legacy_dir() -> PathBuf {
15 let home = env::var("HOME").unwrap_or_default();
16 PathBuf::from(home).join(".cove")
17}
18
19pub fn state_dir() -> PathBuf {
21 env::var("XDG_STATE_HOME")
22 .map(PathBuf::from)
23 .unwrap_or_else(|_| {
24 let home = env::var("HOME").unwrap_or_default();
25 PathBuf::from(home).join(".local").join("state")
26 })
27 .join("cove")
28}
29
30pub fn events_dir() -> PathBuf {
32 state_dir().join("events")
33}
34
35pub fn migrate_legacy() {
41 let legacy = legacy_dir();
42 let xdg = state_dir();
43
44 if !legacy.is_dir() {
46 return;
47 }
48
49 if xdg.is_dir() {
51 return;
52 }
53
54 if let Some(parent) = xdg.parent() {
56 let _ = fs::create_dir_all(parent);
57 }
58
59 match fs::rename(&legacy, &xdg) {
61 Ok(()) => {
62 eprintln!("cove: migrated {} → {}", legacy.display(), xdg.display());
63 #[cfg(unix)]
65 {
66 let _ = std::os::unix::fs::symlink(&xdg, &legacy);
67 }
68 }
69 Err(e) => {
70 eprintln!(
72 "cove: could not migrate {} → {}: {e}",
73 legacy.display(),
74 xdg.display()
75 );
76 eprintln!("cove: continuing with {}", legacy.display());
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use std::sync::Mutex;
85
86 static ENV_LOCK: Mutex<()> = Mutex::new(());
87
88 #[test]
89 fn state_dir_respects_xdg_env() {
90 let _lock = ENV_LOCK.lock().unwrap();
91 unsafe { env::set_var("XDG_STATE_HOME", "/tmp/test-xdg-state") };
92 let dir = state_dir();
93 unsafe { env::remove_var("XDG_STATE_HOME") };
94 assert_eq!(dir, PathBuf::from("/tmp/test-xdg-state/cove"));
95 }
96
97 #[test]
98 fn events_dir_is_under_state() {
99 let _lock = ENV_LOCK.lock().unwrap();
100 unsafe { env::set_var("XDG_STATE_HOME", "/tmp/test-xdg-state") };
101 let dir = events_dir();
102 unsafe { env::remove_var("XDG_STATE_HOME") };
103 assert_eq!(dir, PathBuf::from("/tmp/test-xdg-state/cove/events"));
104 }
105
106 #[test]
107 fn migrate_noop_when_no_legacy() {
108 let _lock = ENV_LOCK.lock().unwrap();
109 let orig_home = env::var("HOME").ok();
110 unsafe { env::set_var("HOME", "/tmp/nonexistent-home-for-cove-test") };
111 unsafe { env::set_var("XDG_STATE_HOME", "/tmp/nonexistent-xdg-for-cove-test") };
112 migrate_legacy();
113 unsafe { env::remove_var("XDG_STATE_HOME") };
114 if let Some(h) = orig_home {
115 unsafe { env::set_var("HOME", h) };
116 }
117 }
118}