1use super::{cache_root, repo_hash};
4use crate::error::PathError;
5use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone)]
9pub struct CacheLayout {
10 pub root: PathBuf,
11}
12
13impl CacheLayout {
14 pub fn for_repo(repo_root: &Path) -> Result<Self, PathError> {
16 Ok(Self {
17 root: cache_root()?.join(repo_hash(repo_root)),
18 })
19 }
20
21 pub fn from_dir(root: PathBuf) -> Self {
24 Self { root }
25 }
26
27 pub fn shims_bin(&self) -> PathBuf {
28 self.root.join("shims").join("bin")
29 }
30 pub fn db(&self) -> PathBuf {
31 self.root.join("runs.sqlite")
32 }
33 pub fn logs_dir(&self) -> PathBuf {
34 self.root.join("logs")
35 }
36 pub fn stdout_log(&self, run_id: &str) -> PathBuf {
37 self.logs_dir().join(format!("{run_id}.stdout"))
38 }
39 pub fn stderr_log(&self, run_id: &str) -> PathBuf {
40 self.logs_dir().join(format!("{run_id}.stderr"))
41 }
42 pub fn normalized_log(&self, run_id: &str) -> PathBuf {
43 self.logs_dir().join(format!("{run_id}.normalized.txt"))
44 }
45 pub fn sessions_dir(&self) -> PathBuf {
46 self.root.join("sessions")
47 }
48 pub fn session_file(&self, session_id: &str) -> PathBuf {
49 self.sessions_dir().join(format!("{session_id}.jsonl"))
50 }
51 pub fn effective_config(&self) -> PathBuf {
52 self.root.join("config.effective.json")
53 }
54 pub fn state_file(&self) -> PathBuf {
55 self.root.join("state.json")
56 }
57 pub fn zdot_dir(&self) -> PathBuf {
59 self.root.join("zdot")
60 }
61
62 pub fn ensure_dirs(&self) -> Result<(), PathError> {
64 for dir in [
65 self.root.clone(),
66 self.shims_bin(),
67 self.logs_dir(),
68 self.sessions_dir(),
69 ] {
70 std::fs::create_dir_all(&dir)?;
71 }
72 Ok(())
73 }
74}