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 #[allow(dead_code)]
61 pub fn get_clone_info(&self, mount: &Mount) -> Result<Option<(String, PathBuf)>> {
63 match mount {
64 Mount::Directory { .. } => Ok(None),
65 Mount::Git { url, .. } => {
66 if self.needs_clone(mount)? {
67 let clone_path = RepoMappingManager::get_default_clone_path(url)?;
68 Ok(Some((url.clone(), clone_path)))
69 } else {
70 Ok(None)
71 }
72 }
73 }
74 }
75
76 #[allow(dead_code)]
78 pub fn resolve_all(&self, mounts: &HashMap<String, Mount>) -> Vec<(String, Result<PathBuf>)> {
80 mounts
81 .iter()
82 .map(|(name, mount)| (name.clone(), self.resolve_mount(mount)))
83 .collect()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::config::SyncStrategy;
91
92 #[test]
93 fn test_directory_resolution() {
94 let resolver = MountResolver::new().unwrap();
95 let mount = Mount::Directory {
96 path: PathBuf::from("/home/user/docs"),
97 sync: SyncStrategy::None,
98 };
99
100 let resolved = resolver.resolve_mount(&mount).unwrap();
101 assert_eq!(resolved, PathBuf::from("/home/user/docs"));
102 }
103
104 #[test]
105 fn test_git_mount_detection() {
106 let mount = Mount::Git {
107 url: "git@github.com:test/repo.git".to_string(),
108 sync: SyncStrategy::Auto,
109 subpath: None,
110 };
111
112 assert!(mount.is_git());
114 }
115}