Mountain/RPC/CocoonService/FileSystem/
FindFiles.rs1#![allow(non_snake_case)]
2
3use globset::Glob;
7use tonic::{Response, Status};
8
9use crate::{
10 RPC::CocoonService::CocoonServiceImpl,
11 Vine::Generated::{FindFilesRequest, FindFilesResponse},
12 dev_log,
13};
14
15pub async fn Fn(Service:&CocoonServiceImpl, Request:FindFilesRequest) -> Result<Response<FindFilesResponse>, Status> {
16 dev_log!("cocoon", "[CocoonService] Finding files with pattern: {}", Request.pattern);
17
18 let Matcher = Glob::new(&Request.pattern)
19 .map_err(|Error| {
20 Status::invalid_argument(format!("find_files: invalid pattern '{}': {}", Request.pattern, Error))
21 })?
22 .compile_matcher();
23
24 let Roots:Vec<std::path::PathBuf> = {
25 match Service.environment.ApplicationState.Workspace.WorkspaceFolders.lock() {
26 Ok(Guard) => Guard.iter().map(|F| std::path::PathBuf::from(F.URI.path())).collect(),
27
28 Err(_) => Vec::new(),
29 }
30 };
31
32 let SearchRoots = if Roots.is_empty() {
33 vec![std::env::current_dir().unwrap_or_default()]
34 } else {
35 Roots
36 };
37
38 let mut URIs = Vec::new();
39
40 fn WalkAndCollect(
41 Directory:&std::path::Path,
42
43 Root:&std::path::Path,
44
45 Matcher:&globset::GlobMatcher,
46
47 Results:&mut Vec<String>,
48 ) {
49 if let Ok(Entries) = std::fs::read_dir(Directory) {
50 for Entry in Entries.flatten() {
51 let EntryPath = Entry.path();
52
53 if EntryPath.is_dir() {
54 WalkAndCollect(&EntryPath, Root, Matcher, Results);
55 } else if let Ok(Relative) = EntryPath.strip_prefix(Root) {
56 if Matcher.is_match(Relative) {
57 Results.push(format!("file://{}", EntryPath.display()));
58 }
59 }
60 }
61 }
62 }
63
64 for Root in &SearchRoots {
65 WalkAndCollect(Root, Root, &Matcher, &mut URIs);
66 }
67
68 dev_log!(
69 "cocoon",
70 "[CocoonService] find_files: {} results for pattern '{}'",
71 URIs.len(),
72 Request.pattern
73 );
74
75 Ok(Response::new(FindFilesResponse { uris:URIs }))
76}