DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/ProcessManagement/
WorkspaceContainsGlob.rs1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3pub fn FindMatchingWorkspaceContainsPatterns(Folders:&[std::path::PathBuf], Patterns:&[String]) -> Vec<String> {
18 use std::collections::HashSet;
19
20 const MAX_DEPTH:usize = 3;
21
22 const MAX_ENTRIES_PER_ROOT:usize = 4096;
23
24 let mut Matched:HashSet<String> = HashSet::new();
25
26 for Folder in Folders {
27 if !Folder.is_dir() {
28 continue;
29 }
30
31 let mut Entries:Vec<String> = Vec::new();
32
33 let mut Stack:Vec<(std::path::PathBuf, usize)> = vec![(Folder.clone(), 0)];
34
35 while let Some((Current, Depth)) = Stack.pop() {
36 if Entries.len() >= MAX_ENTRIES_PER_ROOT {
37 break;
38 }
39
40 let ReadDir = match std::fs::read_dir(&Current) {
41 Ok(R) => R,
42
43 Err(_) => continue,
44 };
45
46 for Entry in ReadDir.flatten() {
47 if Entries.len() >= MAX_ENTRIES_PER_ROOT {
48 break;
49 }
50
51 let Path = Entry.path();
52
53 let Relative = match Path.strip_prefix(Folder) {
54 Ok(R) => R.to_string_lossy().replace('\\', "/"),
55
56 Err(_) => continue,
57 };
58
59 let IsDir = Entry.file_type().map(|T| T.is_dir()).unwrap_or(false);
60
61 Entries.push(Relative.clone());
62
63 if IsDir && Depth + 1 < MAX_DEPTH {
64 Stack.push((Path, Depth + 1));
65 }
66 }
67 }
68
69 for Pattern in Patterns {
70 if Matched.contains(Pattern) {
71 continue;
72 }
73
74 if PatternMatchesAnyEntry(Pattern, &Entries) {
75 Matched.insert(Pattern.clone());
76 }
77 }
78 }
79
80 Matched.into_iter().collect()
81}
82
83pub fn PatternMatchesAnyEntry(Pattern:&str, Entries:&[String]) -> bool {
87 let HasWildcard = Pattern.contains('*') || Pattern.contains('?');
88
89 if !HasWildcard {
90 return Entries.iter().any(|E| E == Pattern);
91 }
92
93 let PatternSegments:Vec<&str> = Pattern.split('/').collect();
94
95 Entries
96 .iter()
97 .any(|E| SegmentMatch(&PatternSegments, &E.split('/').collect::<Vec<_>>()))
98}
99
100pub fn SegmentMatch(Pattern:&[&str], Entry:&[&str]) -> bool {
103 if Pattern.is_empty() {
104 return Entry.is_empty();
105 }
106
107 let Head = Pattern[0];
108
109 if Head == "**" {
110 for Consumed in 0..=Entry.len() {
111 if SegmentMatch(&Pattern[1..], &Entry[Consumed..]) {
112 return true;
113 }
114 }
115
116 return false;
117 }
118
119 if Entry.is_empty() {
120 return false;
121 }
122
123 if SingleSegmentMatch(Head, Entry[0]) {
124 return SegmentMatch(&Pattern[1..], &Entry[1..]);
125 }
126
127 false
128}
129
130pub fn SingleSegmentMatch(Pattern:&str, Segment:&str) -> bool {
134 if Pattern == "*" {
135 return true;
136 }
137
138 if !Pattern.contains('*') && !Pattern.contains('?') {
139 return Pattern == Segment;
140 }
141
142 let Fragments:Vec<&str> = Pattern.split('*').collect();
143
144 let mut Cursor = 0usize;
145
146 for (Index, Fragment) in Fragments.iter().enumerate() {
147 if Fragment.is_empty() {
148 continue;
149 }
150
151 if Index == 0 {
152 if !Segment[Cursor..].starts_with(Fragment) {
153 return false;
154 }
155
156 Cursor += Fragment.len();
157
158 continue;
159 }
160
161 match Segment[Cursor..].find(Fragment) {
162 Some(Offset) => Cursor += Offset + Fragment.len(),
163
164 None => return false,
165 }
166 }
167
168 if let Some(Last) = Fragments.last()
169 && !Last.is_empty()
170 {
171 return Segment.ends_with(Last);
172 }
173
174 true
175}