Skip to main content

kaizen/core/
workspace.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2//! Workspace path canonicalization + machine-local registry.
3
4use anyhow::Result;
5use std::path::{Path, PathBuf};
6
7pub use crate::core::paths::{canonical, kaizen_dir};
8
9pub fn resolve(path: Option<&Path>) -> Result<PathBuf> {
10    let root = path
11        .map(Path::to_path_buf)
12        .map(Ok)
13        .unwrap_or_else(std::env::current_dir)?;
14    let canonical = canonical(&root);
15    let _ = crate::core::machine_registry::upsert_from_resolve(&canonical);
16    Ok(canonical)
17}
18
19pub fn machine_workspaces(seed: Option<&Path>) -> Result<Vec<PathBuf>> {
20    let seed = seed.map(canonical);
21    let mut roots = registry_entries()?;
22    if let Some(path) = seed.as_ref() {
23        push_unique(&mut roots, path.clone());
24    }
25    roots.retain(|p| {
26        if seed.as_ref() == Some(p) {
27            return true;
28        }
29        p.exists() && (db_path(p).exists() || crate::core::machine_registry::is_registered(p))
30    });
31    if roots.is_empty()
32        && let Some(path) = seed
33    {
34        roots.push(path);
35    }
36    Ok(roots)
37}
38
39pub fn db_path(workspace: &Path) -> PathBuf {
40    workspace.join(".kaizen/kaizen.db")
41}
42
43fn registry_entries() -> Result<Vec<PathBuf>> {
44    crate::core::machine_registry::list_paths()
45}
46
47fn push_unique(roots: &mut Vec<PathBuf>, path: PathBuf) {
48    if !roots.iter().any(|row| row == &path) {
49        roots.push(path);
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56    use crate::core::paths::test_lock;
57    use tempfile::TempDir;
58
59    #[test]
60    fn registry_round_trip() {
61        let _guard = test_lock::global().lock().unwrap();
62        let home = TempDir::new().unwrap();
63        let ws = home.path().join("repo");
64        std::fs::create_dir_all(&ws).unwrap();
65        unsafe { std::env::set_var("KAIZEN_HOME", home.path().join(".kaizen")) };
66        let first = resolve(Some(&ws)).unwrap();
67        let rows = machine_workspaces(Some(&first)).unwrap();
68        assert_eq!(rows, vec![first]);
69        unsafe { std::env::remove_var("KAIZEN_HOME") };
70    }
71}