thoughts_tool/mount/
manager.rs1use super::types::MountInfo;
2use super::types::MountOptions;
3use crate::error::Result;
4use crate::platform::Platform;
5use crate::platform::PlatformInfo;
6use async_trait::async_trait;
7use std::path::Path;
8use std::path::PathBuf;
9
10#[cfg(target_os = "linux")]
11use super::mergerfs::MergerfsManager;
12
13#[cfg(target_os = "macos")]
14use super::fuse_t::FuseTManager;
15
16#[async_trait]
18pub trait MountManager: Send + Sync {
19 async fn mount(&self, sources: &[PathBuf], target: &Path, options: &MountOptions)
21 -> Result<()>;
22
23 async fn unmount(&self, target: &Path, force: bool) -> Result<()>;
25
26 async fn is_mounted(&self, target: &Path) -> Result<bool>;
28
29 async fn list_mounts(&self) -> Result<Vec<MountInfo>>;
31
32 async fn get_mount_info(&self, target: &Path) -> Result<Option<MountInfo>>;
34
35 async fn check_health(&self) -> Result<()>;
37
38 fn get_mount_command(
40 &self,
41 sources: &[PathBuf],
42 target: &Path,
43 options: &MountOptions,
44 ) -> String;
45}
46
47pub fn get_mount_manager(platform_info: &PlatformInfo) -> Result<Box<dyn MountManager>> {
49 match &platform_info.platform {
50 #[cfg(target_os = "linux")]
51 Platform::Linux(info) => {
52 if !info.has_mergerfs {
53 return Err(crate::error::ThoughtsError::ToolNotFound {
54 tool: "mergerfs".to_string(),
55 });
56 }
57 if !info.fuse_available {
58 return Err(crate::error::ThoughtsError::PlatformNotSupported {
59 platform: "Linux without FUSE support".to_string(),
60 });
61 }
62 Ok(Box::new(MergerfsManager::new(info.clone())))
63 }
64 #[cfg(target_os = "macos")]
65 Platform::MacOS(info) => {
66 if !info.has_fuse_t && !info.has_macfuse {
67 return Err(crate::error::ThoughtsError::ToolNotFound {
68 tool: "FUSE-T or macFUSE".to_string(),
69 });
70 }
71 Ok(Box::new(FuseTManager::new(info.clone())))
72 }
73 #[cfg(not(target_os = "linux"))]
74 Platform::Linux(_) => Err(crate::error::ThoughtsError::PlatformNotSupported {
75 platform: "Linux support not compiled in".to_string(),
76 }),
77 #[cfg(not(target_os = "macos"))]
78 Platform::MacOS(_) => Err(crate::error::ThoughtsError::PlatformNotSupported {
79 platform: "macOS support not compiled in".to_string(),
80 }),
81 Platform::Unsupported(os) => Err(crate::error::ThoughtsError::PlatformNotSupported {
82 platform: os.clone(),
83 }),
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 #[cfg(any(target_os = "linux", target_os = "macos"))]
90 use super::get_mount_manager;
91 #[cfg(any(target_os = "linux", target_os = "macos"))]
92 use crate::platform::Platform;
93 #[cfg(any(target_os = "linux", target_os = "macos"))]
94 use crate::platform::PlatformInfo;
95 #[cfg(target_os = "linux")]
96 use crate::platform::detector::LinuxInfo;
97 #[cfg(target_os = "macos")]
98 use crate::platform::detector::MacOSInfo;
99 #[cfg(any(target_os = "linux", target_os = "macos"))]
100 use std::path::PathBuf;
101
102 #[test]
103 #[cfg(target_os = "linux")]
104 fn test_get_mount_manager_linux() {
105 let platform_info = PlatformInfo {
106 platform: Platform::Linux(LinuxInfo {
107 distro: "Ubuntu".to_string(),
108 version: "22.04".to_string(),
109 has_mergerfs: true,
110 mergerfs_version: Some("2.33.5".to_string()),
111 fuse_available: true,
112 has_fusermount: false, mergerfs_path: None,
114 fusermount_path: None,
115 }),
116 arch: "x86_64".to_string(),
117 };
118
119 let manager = get_mount_manager(&platform_info);
120 assert!(manager.is_ok());
121 }
122
123 #[test]
124 #[cfg(target_os = "linux")]
125 fn test_get_mount_manager_missing_tools() {
126 let platform_info = PlatformInfo {
127 platform: Platform::Linux(LinuxInfo {
128 distro: "Ubuntu".to_string(),
129 version: "22.04".to_string(),
130 has_mergerfs: false,
131 mergerfs_version: None,
132 fuse_available: true,
133 has_fusermount: true, mergerfs_path: None,
135 fusermount_path: Some(PathBuf::from("/bin/fusermount")),
136 }),
137 arch: "x86_64".to_string(),
138 };
139
140 let result = get_mount_manager(&platform_info);
141 assert!(result.is_err());
142 if let Err(e) = result {
143 match e {
144 crate::error::ThoughtsError::ToolNotFound { tool } => {
145 assert_eq!(tool, "mergerfs");
146 }
147 _ => panic!("Expected ToolNotFound error"),
148 }
149 }
150 }
151
152 #[test]
153 #[cfg(target_os = "macos")]
154 fn test_get_mount_manager_macos() {
155 let platform_info = PlatformInfo {
156 platform: Platform::MacOS(MacOSInfo {
157 version: "14.0".to_string(),
158 has_fuse_t: true,
159 fuse_t_version: Some("1.0.0".to_string()),
160 has_macfuse: false,
161 macfuse_version: None,
162 has_unionfs: true,
163 unionfs_path: Some(PathBuf::from("/usr/local/bin/unionfs-fuse")),
164 }),
165 arch: "aarch64".to_string(),
166 };
167
168 let manager = get_mount_manager(&platform_info);
169 assert!(manager.is_ok());
170 }
171
172 #[test]
173 #[cfg(target_os = "macos")]
174 fn test_get_mount_manager_no_fuse() {
175 let platform_info = PlatformInfo {
176 platform: Platform::MacOS(MacOSInfo {
177 version: "14.0".to_string(),
178 has_fuse_t: false,
179 fuse_t_version: None,
180 has_macfuse: false,
181 macfuse_version: None,
182 has_unionfs: false,
183 unionfs_path: None,
184 }),
185 arch: "aarch64".to_string(),
186 };
187
188 let result = get_mount_manager(&platform_info);
189 assert!(result.is_err());
190 if let Err(e) = result {
191 match e {
192 crate::error::ThoughtsError::ToolNotFound { tool } => {
193 assert_eq!(tool, "FUSE-T or macFUSE");
194 }
195 _ => panic!("Expected ToolNotFound error"),
196 }
197 }
198 }
199}