metis_docs_cli/
workspace.rs

1use std::path::PathBuf;
2
3/// Check if we're in a Metis workspace by walking up the directory tree
4///
5/// Returns (found, metis_dir_path) where:
6/// - found: true if a valid .metis/ vault was found
7/// - metis_dir_path: absolute path to the .metis/ directory (if found)
8pub fn has_metis_vault() -> (bool, Option<PathBuf>) {
9    let Ok(mut current) = std::env::current_dir() else {
10        return (false, None);
11    };
12
13    loop {
14        let metis_dir = current.join(".metis");
15        let db_path = metis_dir.join("metis.db");
16
17        // Check if this directory has a valid Metis vault
18        if metis_dir.exists() && metis_dir.is_dir() && db_path.exists() && db_path.is_file() {
19            return (true, Some(metis_dir));
20        }
21
22        // Move up to parent directory
23        if let Some(parent) = current.parent() {
24            current = parent.to_path_buf();
25        } else {
26            // Reached filesystem root, no workspace found
27            break;
28        }
29    }
30
31    (false, None)
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use tempfile::tempdir;
38
39    #[test]
40    fn test_has_metis_vault_false_when_no_directory() {
41        let temp_dir = tempdir().unwrap();
42        std::env::set_current_dir(temp_dir.path()).unwrap();
43
44        let (found, _) = has_metis_vault();
45        assert!(!found);
46    }
47
48    #[test]
49    fn test_has_metis_vault_true_when_valid() {
50        let temp_dir = tempdir().unwrap();
51        let metis_dir = temp_dir.path().join(".metis");
52        let db_path = metis_dir.join("metis.db");
53
54        std::fs::create_dir(&metis_dir).unwrap();
55        std::fs::write(&db_path, "test").unwrap();
56        std::env::set_current_dir(temp_dir.path()).unwrap();
57
58        let (found, metis_dir_path) = has_metis_vault();
59        assert!(found);
60
61        // Canonicalize both paths to handle symlinks (e.g., /var vs /private/var on macOS)
62        let returned_path = metis_dir_path.unwrap().canonicalize().unwrap();
63        let expected_path = metis_dir.canonicalize().unwrap();
64        assert_eq!(returned_path, expected_path);
65    }
66}