1use std::path::{Path, PathBuf};
2
3use crate::error::ZigError;
4
5pub fn global_workflows_dir_from(home: &Path) -> PathBuf {
7 home.join(".zig").join("workflows")
8}
9
10pub fn global_workflows_dir() -> Option<PathBuf> {
13 std::env::var("HOME")
14 .ok()
15 .map(|home| global_workflows_dir_from(Path::new(&home)))
16}
17
18pub fn ensure_global_workflows_dir() -> Result<PathBuf, ZigError> {
20 let dir = global_workflows_dir()
21 .ok_or_else(|| ZigError::Io("HOME environment variable not set".into()))?;
22 if !dir.exists() {
23 std::fs::create_dir_all(&dir)
24 .map_err(|e| ZigError::Io(format!("failed to create {}: {e}", dir.display())))?;
25 }
26 Ok(dir)
27}
28
29pub fn global_base_dir() -> Option<PathBuf> {
47 std::env::var("HOME")
48 .ok()
49 .map(|h| Path::new(&h).join(".zig"))
50}
51
52pub fn sanitize_project_path(path: &str) -> String {
57 path.trim_start_matches('/').replace('/', "-")
58}
59
60fn find_git_root(start: &Path) -> Option<PathBuf> {
62 let mut current = start;
63 loop {
64 if current.join(".git").exists() {
65 return Some(current.to_path_buf());
66 }
67 current = current.parent()?;
68 }
69}
70
71pub fn project_dir(root: Option<&str>) -> Option<PathBuf> {
78 let base = global_base_dir()?;
79 if let Some(r) = root {
80 return Some(base.join("projects").join(sanitize_project_path(r)));
81 }
82 let cwd = std::env::current_dir().ok()?;
83 if let Some(git_root) = find_git_root(&cwd) {
84 let sanitized = sanitize_project_path(&git_root.to_string_lossy());
85 return Some(base.join("projects").join(sanitized));
86 }
87 Some(base)
88}
89
90pub fn project_logs_dir(root: Option<&str>) -> Option<PathBuf> {
92 project_dir(root).map(|p| p.join("logs"))
93}
94
95pub fn project_sessions_dir(root: Option<&str>) -> Option<PathBuf> {
97 project_logs_dir(root).map(|p| p.join("sessions"))
98}
99
100pub fn project_index_path(root: Option<&str>) -> Option<PathBuf> {
102 project_logs_dir(root).map(|p| p.join("index.json"))
103}
104
105pub fn global_sessions_index_path() -> Option<PathBuf> {
107 global_base_dir().map(|p| p.join("sessions_index.json"))
108}
109
110pub fn ensure_project_sessions_dir(root: Option<&str>) -> Result<PathBuf, ZigError> {
112 let dir = project_sessions_dir(root)
113 .ok_or_else(|| ZigError::Io("HOME environment variable not set".into()))?;
114 if !dir.exists() {
115 std::fs::create_dir_all(&dir)
116 .map_err(|e| ZigError::Io(format!("failed to create {}: {e}", dir.display())))?;
117 }
118 Ok(dir)
119}
120
121#[cfg(test)]
122#[path = "paths_tests.rs"]
123mod tests;