distri_filesystem/
wrapper.rs1use crate::GrepSearcher;
2use anyhow::Result;
3use async_trait::async_trait;
4use distri_types::filesystem::{
5 DirectoryListing, FileMetadata, FileReadResult, FileSystemOps, ReadParams, SearchResult,
6};
7use std::sync::Arc;
8
9#[derive(Debug, Clone)]
11pub struct FileSystem {
12 file_store: Arc<crate::FileSystemStore>,
13 grep_searcher: Arc<dyn GrepSearcher>,
14 root_prefix: Option<String>,
15}
16
17impl FileSystem {
18 pub fn new(
19 file_store: Arc<crate::FileSystemStore>,
20 grep_searcher: Arc<dyn GrepSearcher>,
21 ) -> Self {
22 let root_prefix = file_store.root_prefix();
23 Self {
24 file_store,
25 grep_searcher,
26 root_prefix,
27 }
28 }
29
30 pub fn root_prefix(&self) -> Option<String> {
31 self.root_prefix.clone()
32 }
33
34 pub fn create_tools(&self) -> Vec<Arc<dyn distri_types::Tool>> {
35 crate::create_filesystem_tools(Arc::new(self.clone()))
36 }
37
38 pub fn scoped(&self, prefix: Option<&str>) -> anyhow::Result<Self> {
39 let store = Arc::new(self.file_store.scoped(prefix)?);
40 let grep_searcher =
41 Arc::new(crate::FileSystemGrepSearcher::new(store.clone())) as Arc<dyn GrepSearcher>;
42 Ok(Self {
43 root_prefix: store.root_prefix(),
44 file_store: store,
45 grep_searcher,
46 })
47 }
48
49 pub async fn create_artifact_wrapper(
51 &self,
52 base_path: String,
53 ) -> Result<crate::ArtifactWrapper, anyhow::Error> {
54 crate::ArtifactWrapper::new(Arc::new(self.clone()), base_path).await
55 }
56
57 pub async fn write_binary(&self, path: &str, content: &[u8]) -> Result<()> {
59 self.file_store.write_binary(path, content).await
60 }
61
62 pub async fn read_binary(&self, path: &str) -> Result<Vec<u8>> {
64 self.file_store.read_binary(path).await
65 }
66}
67
68#[async_trait]
69impl FileSystemOps for FileSystem {
70 async fn read(&self, path: &str, params: ReadParams) -> Result<FileReadResult> {
71 let read_params = crate::ReadParams {
72 start_line: params.start_line,
73 end_line: params.end_line,
74 };
75 let result = self.file_store.read(path, read_params).await?;
76 Ok(FileReadResult {
77 content: result.content,
78 start_line: result.start_line,
79 end_line: result.end_line,
80 total_lines: result.total_lines,
81 })
82 }
83
84 async fn read_raw(&self, path: &str) -> Result<String> {
85 self.file_store.read_raw(path).await
86 }
87
88 async fn read_with_line_numbers(
89 &self,
90 path: &str,
91 params: ReadParams,
92 ) -> Result<FileReadResult> {
93 self.read(path, params).await
94 }
95
96 async fn write(&self, path: &str, content: &str) -> Result<()> {
97 self.file_store.write(path, content).await
98 }
99
100 async fn list(&self, path: &str) -> Result<DirectoryListing> {
101 let listing = self.file_store.list(path).await?;
102 Ok(DirectoryListing {
103 path: listing.path,
104 entries: listing
105 .entries
106 .into_iter()
107 .map(|e| distri_types::filesystem::DirectoryEntry {
108 name: e.name,
109 is_file: e.is_file,
110 is_dir: e.is_dir,
111 size: e.size,
112 })
113 .collect(),
114 })
115 }
116
117 async fn delete(&self, path: &str, recursive: bool) -> Result<()> {
118 self.file_store.delete(path, recursive).await
119 }
120
121 async fn search(
122 &self,
123 path: &str,
124 content_pattern: Option<&str>,
125 file_pattern: Option<&str>,
126 ) -> Result<SearchResult> {
127 let result = self
128 .grep_searcher
129 .search(path, content_pattern, file_pattern)
130 .await?;
131 Ok(SearchResult {
132 path: result.path,
133 matches: result
134 .matches
135 .into_iter()
136 .map(|m| distri_types::filesystem::SearchMatch {
137 file_path: m.file_path,
138 line_number: m.line_number,
139 line_content: m.line_content,
140 match_text: m.match_text,
141 })
142 .collect(),
143 })
144 }
145
146 async fn copy(&self, from: &str, to: &str) -> Result<()> {
147 let content = self
148 .file_store
149 .read(from, crate::ReadParams::default())
150 .await?
151 .content;
152 self.file_store.write(to, &content).await
153 }
154
155 async fn move_file(&self, from: &str, to: &str) -> Result<()> {
156 self.copy(from, to).await?;
157 self.file_store.delete(from, false).await
158 }
159
160 async fn mkdir(&self, _path: &str) -> Result<()> {
161 Ok(())
163 }
164
165 async fn info(&self, path: &str) -> Result<FileMetadata> {
166 self.file_store.info(path).await
167 }
168
169 async fn tree(&self, path: &str) -> Result<DirectoryListing> {
170 self.list(path).await
171 }
172}
173
174pub async fn create_file_system(config: crate::FileSystemConfig) -> anyhow::Result<FileSystem> {
175 let file_store = Arc::new(crate::FileSystemStore::new(config).await?);
176 let grep_searcher =
177 Arc::new(crate::FileSystemGrepSearcher::new(file_store.clone())) as Arc<dyn GrepSearcher>;
178
179 Ok(FileSystem::new(file_store, grep_searcher))
180}