1use std::path::{Path, PathBuf};
2
3#[derive(Debug, Clone)]
4pub struct DefaultPaths {
5 pub root: PathBuf,
6 pub state_dir: PathBuf,
7 pub cache_dir: PathBuf,
8 pub logs_dir: PathBuf,
9}
10
11impl DefaultPaths {
12 pub fn from_root(root: &Path) -> Self {
13 let state_dir = root.join(".greentic");
14 let cache_dir = state_dir.join("cache");
15 let logs_dir = state_dir.join("logs");
16 Self {
17 root: root.to_path_buf(),
18 state_dir,
19 cache_dir,
20 logs_dir,
21 }
22 }
23}
24
25pub fn discover_project_root(start: &Path) -> Option<PathBuf> {
26 for ancestor in start.ancestors() {
27 let greentic_dir = ancestor.join(".greentic");
28 if greentic_dir.is_dir() {
29 return Some(ancestor.to_path_buf());
30 }
31 let git_dir = ancestor.join(".git");
32 if git_dir.is_dir() {
33 return Some(ancestor.to_path_buf());
34 }
35 let cargo = ancestor.join("Cargo.toml");
36 if cargo.is_file() {
37 return Some(ancestor.to_path_buf());
38 }
39 }
40 None
41}
42
43pub fn absolute_path(path: &Path) -> anyhow::Result<PathBuf> {
44 if path.is_absolute() {
45 return Ok(path.to_path_buf());
46 }
47 let cwd = std::env::current_dir()?;
48 Ok(cwd.join(path))
49}