thoughts_tool/mount/
resolver.rs1use crate::config::{Mount, RepoMappingManager};
2use crate::mount::utils::normalize_mount_path;
3use anyhow::Result;
4use std::collections::HashMap;
5use std::path::PathBuf;
6
7pub struct MountResolver {
8 repo_mapping: RepoMappingManager,
9}
10
11impl MountResolver {
12 pub fn new() -> Result<Self> {
13 Ok(Self {
14 repo_mapping: RepoMappingManager::new()?,
15 })
16 }
17
18 pub fn resolve_mount(&self, mount: &Mount) -> Result<PathBuf> {
20 match mount {
21 Mount::Directory { path, .. } => {
22 Ok(normalize_mount_path(path)?)
24 }
25 Mount::Git { url, subpath, .. } => {
26 let full_url = if let Some(sub) = subpath {
28 format!("{url}:{sub}")
29 } else {
30 url.clone()
31 };
32
33 self.repo_mapping.resolve_url(&full_url)?.ok_or_else(|| {
35 use colored::Colorize;
36 anyhow::anyhow!(
37 "Repository not cloned: {}\n\n\
38 To fix this, run one of:\n \
39 • {} (auto-managed)\n \
40 • {} (custom location)",
41 url,
42 format!("thoughts mount clone {url}").cyan(),
43 format!("thoughts mount clone {url} /your/path").cyan()
44 )
45 })
46 }
47 }
48 }
49
50 pub fn needs_clone(&self, mount: &Mount) -> Result<bool> {
52 match mount {
53 Mount::Directory { .. } => Ok(false),
54 Mount::Git { url, .. } => Ok(self.repo_mapping.resolve_url(url)?.is_none()),
55 }
56 }
57
58 #[allow(dead_code)]
60 pub fn get_clone_info(&self, mount: &Mount) -> Result<Option<(String, PathBuf)>> {
62 match mount {
63 Mount::Directory { .. } => Ok(None),
64 Mount::Git { url, .. } => {
65 if self.needs_clone(mount)? {
66 let clone_path = RepoMappingManager::get_default_clone_path(url)?;
67 Ok(Some((url.clone(), clone_path)))
68 } else {
69 Ok(None)
70 }
71 }
72 }
73 }
74
75 #[allow(dead_code)]
77 pub fn resolve_all(&self, mounts: &HashMap<String, Mount>) -> Vec<(String, Result<PathBuf>)> {
79 mounts
80 .iter()
81 .map(|(name, mount)| (name.clone(), self.resolve_mount(mount)))
82 .collect()
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::config::SyncStrategy;
90
91 #[test]
92 fn test_directory_resolution() {
93 let resolver = MountResolver::new().unwrap();
94 let mount = Mount::Directory {
95 path: PathBuf::from("/home/user/docs"),
96 sync: SyncStrategy::None,
97 };
98
99 let resolved = resolver.resolve_mount(&mount).unwrap();
100 assert_eq!(resolved, PathBuf::from("/home/user/docs"));
101 }
102
103 #[test]
104 fn test_git_mount_detection() {
105 let mount = Mount::Git {
106 url: "git@github.com:test/repo.git".to_string(),
107 sync: SyncStrategy::Auto,
108 subpath: None,
109 };
110
111 assert!(mount.is_git());
113 }
114}