oxios_kernel/kernel_handle/
mount_api.rs1use std::path::PathBuf;
10use std::sync::Arc;
11
12use anyhow::{Context, Result};
13use serde::{Deserialize, Serialize};
14use uuid::Uuid;
15
16use crate::mount::{Mount, MountId, MountManager, MountMeta, MountSource};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20#[allow(missing_docs)]
21pub struct MountInfo {
22 pub id: String,
23 pub name: String,
24 pub paths: Vec<String>,
25 pub auto_description: String,
26 pub auto_meta: MountMeta,
27 pub source: String,
28 pub enrichment_pending: bool,
29 pub last_enriched_at: Option<String>,
30 pub created_at: String,
31 pub updated_at: String,
32 pub last_active_at: String,
33}
34
35impl From<&Mount> for MountInfo {
36 fn from(m: &Mount) -> Self {
37 Self {
38 id: m.id.to_string(),
39 name: m.name.clone(),
40 paths: m
41 .paths
42 .iter()
43 .map(|p| p.to_string_lossy().to_string())
44 .collect(),
45 auto_description: m.auto_description.clone(),
46 auto_meta: m.auto_meta.clone(),
47 source: m.source.to_string(),
48 enrichment_pending: m.enrichment_pending,
49 last_enriched_at: m.last_enriched_at.map(|t| t.to_rfc3339()),
50 created_at: m.created_at.to_rfc3339(),
51 updated_at: m.updated_at.to_rfc3339(),
52 last_active_at: m.last_active_at.to_rfc3339(),
53 }
54 }
55}
56
57#[allow(dead_code)]
59pub struct MountApi {
60 pub(crate) mount_manager: Arc<MountManager>,
62}
63
64impl MountApi {
65 pub fn new(mount_manager: Arc<MountManager>) -> Self {
67 Self { mount_manager }
68 }
69
70 pub fn list_mounts(&self) -> Vec<MountInfo> {
72 self.mount_manager
73 .list_mounts()
74 .iter()
75 .map(MountInfo::from)
76 .collect()
77 }
78
79 pub fn get_mount(&self, id: &str) -> Option<MountInfo> {
81 let mount_id: MountId = Uuid::parse_str(id).ok()?;
82 self.mount_manager
83 .get_mount(mount_id)
84 .as_ref()
85 .map(MountInfo::from)
86 }
87
88 pub fn get_mount_by_name(&self, name: &str) -> Option<MountInfo> {
90 self.mount_manager
91 .get_mount_by_name(name)
92 .as_ref()
93 .map(MountInfo::from)
94 }
95
96 pub fn resolve_mounts(&self, mount_ids: &[MountId]) -> Vec<Mount> {
99 self.mount_manager.get_mounts_ordered(mount_ids)
100 }
101
102 pub fn create_mount(&self, name: String, paths: Vec<String>) -> Result<MountInfo> {
104 let paths: Vec<PathBuf> = paths.into_iter().map(PathBuf::from).collect();
105 let mount = self
106 .mount_manager
107 .create_mount(name, paths, MountSource::Manual)?;
108 Ok(MountInfo::from(&mount))
109 }
110
111 pub fn update_enrichment(
113 &self,
114 id: &str,
115 auto_description: Option<String>,
116 auto_meta: Option<MountMeta>,
117 ) -> Result<MountInfo> {
118 let mount_id: MountId = Uuid::parse_str(id).context("Invalid mount ID")?;
119 let mount = self
120 .mount_manager
121 .update_enrichment(mount_id, auto_description, auto_meta)?;
122 Ok(MountInfo::from(&mount))
123 }
124
125 pub fn rename_mount(&self, id: &str, new_name: String) -> Result<MountInfo> {
127 let mount_id: MountId = Uuid::parse_str(id).context("Invalid mount ID")?;
128 let mount = self.mount_manager.rename(mount_id, new_name)?;
129 Ok(MountInfo::from(&mount))
130 }
131
132 pub fn remove_mount(&self, id: &str) -> Result<()> {
134 let mount_id: MountId = Uuid::parse_str(id).context("Invalid mount ID")?;
135 self.mount_manager.remove_mount(mount_id)
136 }
137
138 pub fn touch_mount(&self, id: &str) {
140 if let Ok(mount_id) = Uuid::parse_str(id) {
141 self.mount_manager.touch(mount_id);
142 }
143 }
144
145 pub fn rescan(&self, id: &str) -> Result<MountInfo> {
147 let mount_id: MountId = Uuid::parse_str(id).context("Invalid mount ID")?;
148 self.mount_manager
149 .seed_auto_meta(mount_id)
150 .context("Failed to rescan mount")?;
151 self.get_mount(id)
152 .ok_or_else(|| anyhow::anyhow!("Mount not found after rescan"))
153 }
154
155 pub fn detect(&self, message: &str) -> Option<MountInfo> {
157 use crate::mount::DetectionResult;
158 match self.mount_manager.detect(message) {
159 DetectionResult::Found(id) => self
160 .mount_manager
161 .get_mount(id)
162 .as_ref()
163 .map(MountInfo::from),
164 DetectionResult::NoMatch { .. } => None,
165 }
166 }
167}