1use std::path::{Path, PathBuf};
13
14use anyhow::{Context, Result};
15use directories::ProjectDirs;
16
17#[derive(Clone)]
18pub struct Paths {
19 config_dir: PathBuf,
20 data_dir: PathBuf,
21}
22
23impl Paths {
24 pub fn discover() -> Result<Self> {
27 let dirs = ProjectDirs::from("", "", "review-queue")
28 .context("could not determine home directory")?;
29 Ok(Self {
30 config_dir: dirs.config_dir().to_path_buf(),
31 data_dir: dirs.data_dir().to_path_buf(),
32 })
33 }
34
35 pub fn with_overrides(mut self, data_dir: Option<PathBuf>) -> Self {
36 if let Some(d) = data_dir {
37 self.data_dir = d;
38 }
39 self
40 }
41
42 pub fn config_file(&self) -> PathBuf {
43 self.config_dir.join("config.toml")
44 }
45
46 pub fn state_file(&self) -> PathBuf {
47 self.data_dir.join("state.json")
48 }
49
50 pub fn repos_file(&self) -> PathBuf {
51 self.data_dir.join("repos.json")
52 }
53
54 pub fn sync_lock_file(&self) -> PathBuf {
55 self.data_dir.join("sync.lock")
56 }
57
58 pub fn workdir_cache_file(&self) -> PathBuf {
60 self.data_dir.join("workdir.json")
61 }
62
63 pub fn repos_dir(&self) -> PathBuf {
65 self.data_dir.join("repos")
66 }
67
68 pub fn repo_dir(&self, name: &str) -> PathBuf {
70 self.repos_dir().join(name)
71 }
72
73 pub fn workspaces_dir(&self) -> PathBuf {
75 self.data_dir.join("workspaces")
76 }
77
78 pub fn workspace_dir(&self, slug: &str) -> PathBuf {
82 self.workspaces_dir().join(slug)
83 }
84
85 pub fn data_dir(&self) -> &Path {
86 &self.data_dir
87 }
88
89 pub fn ensure_dirs(&self) -> Result<()> {
91 std::fs::create_dir_all(&self.data_dir)
92 .with_context(|| format!("creating data dir {}", self.data_dir.display()))?;
93 std::fs::create_dir_all(&self.config_dir)
94 .with_context(|| format!("creating config dir {}", self.config_dir.display()))?;
95 Ok(())
96 }
97}