1use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Paths {
9 state_dir: PathBuf,
10}
11
12impl Paths {
13 pub fn new(state_dir: impl Into<PathBuf>) -> Self {
14 Self {
15 state_dir: state_dir.into(),
16 }
17 }
18
19 pub fn from_env() -> Self {
21 let base = std::env::var_os("XDG_STATE_HOME")
22 .map(PathBuf::from)
23 .filter(|p| p.is_absolute())
24 .unwrap_or_else(|| {
25 std::env::var_os("HOME")
26 .map(PathBuf::from)
27 .unwrap_or_else(|| PathBuf::from("."))
28 .join(".local/state")
29 });
30 Self::new(base.join("stackless"))
31 }
32
33 pub fn state_dir(&self) -> &Path {
34 &self.state_dir
35 }
36
37 pub fn db_path(&self) -> PathBuf {
38 self.state_dir.join("state.db")
39 }
40
41 pub fn socket_path(&self) -> PathBuf {
42 self.state_dir.join("daemon.sock")
43 }
44
45 pub fn daemon_log(&self) -> PathBuf {
46 self.state_dir.join("daemon.log")
47 }
48
49 pub fn spawn_lock(&self) -> PathBuf {
50 self.state_dir.join("daemon.spawn.lock")
51 }
52
53 pub fn logs_dir(&self, instance: &str) -> PathBuf {
54 self.state_dir.join("logs").join(instance)
55 }
56
57 pub fn persistence_marker(&self) -> PathBuf {
59 self.state_dir.join("daemon.persistence")
60 }
61
62 pub fn self_update_ledger(&self) -> PathBuf {
64 self.state_dir.join("self_update.ledger.json")
65 }
66
67 pub fn self_update_lock(&self) -> PathBuf {
69 self.state_dir.join("self_update.lock")
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn layout_under_state_dir() {
79 let paths = Paths::new("/tmp/stackless-test");
80 assert_eq!(paths.state_dir(), Path::new("/tmp/stackless-test"));
81 assert_eq!(
82 paths.db_path(),
83 PathBuf::from("/tmp/stackless-test/state.db")
84 );
85 assert_eq!(
86 paths.socket_path(),
87 PathBuf::from("/tmp/stackless-test/daemon.sock")
88 );
89 assert_eq!(
90 paths.daemon_log(),
91 PathBuf::from("/tmp/stackless-test/daemon.log")
92 );
93 assert_eq!(
94 paths.spawn_lock(),
95 PathBuf::from("/tmp/stackless-test/daemon.spawn.lock")
96 );
97 assert_eq!(
98 paths.logs_dir("demo"),
99 PathBuf::from("/tmp/stackless-test/logs/demo")
100 );
101 assert_eq!(
102 paths.persistence_marker(),
103 PathBuf::from("/tmp/stackless-test/daemon.persistence")
104 );
105 assert_eq!(
106 paths.self_update_ledger(),
107 PathBuf::from("/tmp/stackless-test/self_update.ledger.json")
108 );
109 assert_eq!(
110 paths.self_update_lock(),
111 PathBuf::from("/tmp/stackless-test/self_update.lock")
112 );
113 }
114
115 #[test]
116 fn from_env_matches_store_wrappers() {
117 let paths = Paths::from_env();
118 assert_eq!(paths.state_dir(), crate::state::Store::state_dir());
119 assert_eq!(paths.db_path(), crate::state::Store::default_path());
120 }
121}