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