1use std::path::{Path, PathBuf};
8
9use packset_core::identity::workspace_slug;
10
11#[derive(Debug, Clone)]
13pub struct Home {
14 root: PathBuf,
15}
16
17impl Home {
18 #[must_use]
20 pub fn new(root: impl Into<PathBuf>) -> Self {
21 Self { root: root.into() }
22 }
23
24 #[must_use]
26 pub fn default_root() -> PathBuf {
27 let home = std::env::var_os("HOME").map_or_else(|| PathBuf::from("."), PathBuf::from);
28 home.join(".grokinside").join("memory")
29 }
30
31 #[must_use]
33 pub fn root(&self) -> &Path {
34 &self.root
35 }
36
37 #[must_use]
39 pub fn db_path(&self) -> PathBuf {
40 self.root.join("memory.lmdb")
41 }
42
43 #[must_use]
45 pub fn milli_dir(&self) -> PathBuf {
46 self.root.join("memory.milli")
47 }
48
49 #[must_use]
51 pub fn lock_path(&self) -> PathBuf {
52 self.root.join("packsetd.lock")
53 }
54
55 #[must_use]
57 pub fn workspace_dir(&self, workspace: &str) -> PathBuf {
58 self.root.join("workspaces").join(workspace_slug(workspace))
59 }
60
61 #[must_use]
63 pub fn user_path(&self) -> PathBuf {
64 self.root.join("USER.md")
65 }
66
67 #[must_use]
69 pub fn memory_path(&self, workspace: &str) -> PathBuf {
70 self.workspace_dir(workspace).join("MEMORY.md")
71 }
72
73 #[must_use]
75 pub fn atoms_path(&self, workspace: &str) -> PathBuf {
76 self.workspace_dir(workspace).join("atoms.jsonl")
77 }
78
79 #[must_use]
81 pub fn archive_path(&self, workspace: &str, day: &str) -> PathBuf {
82 self.workspace_dir(workspace)
83 .join("archive")
84 .join(format!("{day}.md"))
85 }
86
87 #[must_use]
89 pub fn pin_path(&self, workspace: &str) -> PathBuf {
90 self.workspace_dir(workspace).join("pin")
91 }
92
93 #[must_use]
95 pub fn set_dir(&self, workspace: &str, name: &str) -> PathBuf {
96 self.workspace_dir(workspace).join("sets").join(name)
97 }
98
99 #[must_use]
101 pub fn set_user_path(&self, workspace: &str, name: &str) -> PathBuf {
102 self.set_dir(workspace, name).join("USER.md")
103 }
104
105 #[must_use]
107 pub fn set_memory_path(&self, workspace: &str, name: &str) -> PathBuf {
108 self.set_dir(workspace, name).join("MEMORY.md")
109 }
110
111 #[must_use]
113 pub fn set_instructions_path(&self, workspace: &str, name: &str) -> PathBuf {
114 self.set_dir(workspace, name).join("INSTRUCTIONS.md")
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn a_workspace_name_becomes_one_directory() {
124 let home = Home::new("/tmp/pack");
125 let dir = home.workspace_dir("git:github.com/HaoZeke/vissue");
126 assert_eq!(
127 dir,
128 PathBuf::from("/tmp/pack/workspaces/git_github.com_HaoZeke_vissue")
129 );
130 assert_eq!(dir.components().count(), 5);
132 }
133
134 #[test]
135 fn the_seat_card_is_above_the_workspaces() {
136 let home = Home::new("/tmp/pack");
137 assert_eq!(home.user_path(), PathBuf::from("/tmp/pack/USER.md"));
138 assert!(home
139 .memory_path("global")
140 .starts_with("/tmp/pack/workspaces"));
141 }
142
143 #[test]
144 fn a_set_lives_under_its_workspace() {
145 let home = Home::new("/tmp/pack");
146 assert_eq!(
147 home.set_user_path("global", "review"),
148 PathBuf::from("/tmp/pack/workspaces/global/sets/review/USER.md")
149 );
150 }
151}