@@ -29,7 +29,7 @@ impl Directories {
2929 self . reference_files = Vec :: new ( ) ;
3030 self . reference_directories = Vec :: new ( ) ;
3131 let paths = if cfg ! ( target_family = "windows" ) {
32- reference_paths. into_iter ( ) . map ( |p| normalize_windows_path ( p ) ) . collect ( )
32+ reference_paths. into_iter ( ) . map ( normalize_windows_path) . collect ( )
3333 } else {
3434 reference_paths
3535 } ;
@@ -40,7 +40,7 @@ impl Directories {
4040 self . included_files = Vec :: new ( ) ;
4141 self . included_directories = Vec :: new ( ) ;
4242 let paths = if cfg ! ( target_family = "windows" ) {
43- included_paths. into_iter ( ) . map ( |p| normalize_windows_path ( p ) ) . collect ( )
43+ included_paths. into_iter ( ) . map ( normalize_windows_path) . collect ( )
4444 } else {
4545 included_paths
4646 } ;
@@ -51,7 +51,7 @@ impl Directories {
5151 self . excluded_files = Vec :: new ( ) ;
5252 self . excluded_directories = Vec :: new ( ) ;
5353 let paths = if cfg ! ( target_family = "windows" ) {
54- excluded_paths. into_iter ( ) . map ( |p| normalize_windows_path ( p ) ) . collect ( )
54+ excluded_paths. into_iter ( ) . map ( normalize_windows_path) . collect ( )
5555 } else {
5656 excluded_paths
5757 } ;
@@ -134,13 +134,11 @@ impl Directories {
134134 pub ( crate ) fn optimize_directories ( & mut self , recursive_search : bool , skip_exist_check : bool ) -> Result < Messages , Messages > {
135135 let mut messages: Messages = Messages :: new ( ) ;
136136
137- dbg ! ( "1" , & self ) ;
138137 if self . included_directories . is_empty ( ) && self . included_files . is_empty ( ) {
139138 messages. critical = Some ( flc ! ( "core_missing_no_chosen_included_path" ) ) ;
140139 return Err ( messages) ;
141140 }
142141
143- dbg ! ( "2" , & self ) ;
144142 // Remove duplicated entries like: "/", "/"
145143 for items in & mut [
146144 & mut self . included_directories ,
@@ -153,7 +151,6 @@ impl Directories {
153151 items. sort_unstable ( ) ;
154152 items. dedup ( ) ;
155153 }
156- dbg ! ( "3" , & self ) ;
157154
158155 // Optimize for duplicated included directories - "/", "/home". "/home/Pulpit" to "/"
159156 // Do not use when not using recursive search
@@ -163,21 +160,18 @@ impl Directories {
163160 kk. retain ( |item| !cloned. iter ( ) . any ( |other_item| item != other_item && item. starts_with ( other_item) ) ) ;
164161 }
165162 }
166- dbg ! ( "4" , & self ) ;
167163
168164 // Remove included directories which are inside any excluded directory
169165 // Same with included files
170166 for kk in [ & mut self . included_directories , & mut self . included_files ] {
171167 kk. retain ( |id| !self . excluded_directories . iter ( ) . any ( |ed| id. starts_with ( ed) ) ) ;
172168 }
173- dbg ! ( "5" , & self ) ;
174169
175170 // Also check if files are not excluded directly
176171 {
177172 let kk = & mut self . included_files ;
178173 kk. retain ( |id| !self . excluded_directories . iter ( ) . any ( |ed| id == ed) ) ;
179174 }
180- dbg ! ( "6" , & self ) ;
181175
182176 // Remove non existed directories and files
183177 if !skip_exist_check {
@@ -190,22 +184,19 @@ impl Directories {
190184 kk. retain ( |path| path. exists ( ) ) ;
191185 }
192186 }
193- dbg ! ( "7" , & self ) ;
194187
195188 // Excluded paths must are inside included path, because otherwise they are pointless
196189 // So first, removing included files, that are inside excluded directories
197190 // So this will allow to remove excluded directories outside included directories
198191 self . included_files . retain ( |ifile| !self . excluded_directories . iter ( ) . any ( |ed| ifile. starts_with ( ed) ) ) ;
199192 self . excluded_directories . retain ( |ed| self . included_directories . iter ( ) . any ( |id| ed. starts_with ( id) ) ) ;
200193
201- dbg ! ( "8" , & self ) ;
202194 // Selecting Reference folders
203195 {
204196 self . reference_directories . retain ( |folder| self . included_directories . iter ( ) . any ( |e| folder. starts_with ( e) ) ) ;
205197 self . reference_files
206198 . retain ( |file| self . included_directories . iter ( ) . any ( |e| file. starts_with ( e) ) || self . included_files . iter ( ) . any ( |f| file == f) ) ;
207199 }
208- dbg ! ( "9" , & self ) ;
209200
210201 // Not needed, but better is to have sorted everything
211202 for items in & mut [
@@ -218,7 +209,6 @@ impl Directories {
218209 ] {
219210 items. sort_unstable ( ) ;
220211 }
221- dbg ! ( "10" , & self ) ;
222212
223213 // Get device IDs for included directories, probably ther better solution would be to get one id per directory, but this is faster, but a little less precise
224214 #[ cfg( target_family = "unix" ) ]
@@ -230,19 +220,16 @@ impl Directories {
230220 }
231221 }
232222 }
233- dbg ! ( "11" , & self ) ;
234223
235224 if self . included_directories . is_empty ( ) && self . included_files . is_empty ( ) {
236225 messages. critical = Some ( flc ! ( "core_missing_no_chosen_included_path" ) ) ;
237226 return Err ( messages) ;
238227 }
239- dbg ! ( "12" , & self ) ;
240228
241229 if self . reference_directories == self . included_directories && self . included_files == self . reference_files {
242230 messages. critical = Some ( flc ! ( "core_reference_included_paths_same" ) ) ;
243231 return Err ( messages) ;
244232 }
245- dbg ! ( "13" , & self ) ;
246233
247234 Ok ( messages)
248235 }
@@ -300,9 +287,10 @@ impl Directories {
300287
301288#[ cfg( test) ]
302289mod tests {
303- use super :: * ;
304290 use std:: path:: PathBuf ;
305291
292+ use super :: * ;
293+
306294 #[ test]
307295 fn test_no_included_paths_errors ( ) {
308296 let mut d = Directories :: new ( ) ;
@@ -316,20 +304,89 @@ mod tests {
316304 let mut d = Directories :: new ( ) ;
317305 d. included_directories . push ( p. clone ( ) ) ;
318306 d. included_directories . push ( p. clone ( ) ) ;
319- let msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
320- assert_eq ! ( d. included_directories, vec![
321- p. clone( ) ,
322- ] ) ;
307+ let _msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
308+ assert_eq ! ( d. included_directories, vec![ p] ) ;
323309 }
324310
325311 #[ test]
326312 fn test_excluded_removes_included_inside ( ) {
327313 let base = PathBuf :: from ( "/this/base/does/not/exist" ) ;
328314 let sub = base. join ( "sub" ) ;
329315 let mut d = Directories :: new ( ) ;
330- d. included_directories . push ( sub. clone ( ) ) ;
331- d. excluded_directories . push ( base. clone ( ) ) ;
316+ d. included_directories . push ( sub) ;
317+ d. excluded_directories . push ( base) ;
332318 let _msgs = d. optimize_directories ( true , true ) . unwrap_err ( ) ;
333319 assert_eq ! ( d. included_directories, Vec :: <PathBuf >:: new( ) ) ;
334320 }
321+
322+ #[ test]
323+ fn test_optimize_nested_included_directories_dedup ( ) {
324+ let mut d = Directories :: new ( ) ;
325+ d. included_directories . push ( PathBuf :: from ( "/" ) ) ;
326+ d. included_directories . push ( PathBuf :: from ( "/home" ) ) ;
327+ d. included_directories . push ( PathBuf :: from ( "/home/Pulpit" ) ) ;
328+
329+ // use recursive_search = true and skip_exist_check = true as requested
330+ let msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
331+ // only root should remain after dedup
332+ assert_eq ! ( d. included_directories, vec![ PathBuf :: from( "/" ) ] ) ;
333+ assert ! ( msgs. critical. is_none( ) ) ;
334+ }
335+
336+ #[ test]
337+ fn test_excluded_directories_pruned_to_inside_included ( ) {
338+ let mut d = Directories :: new ( ) ;
339+ d. included_directories . push ( PathBuf :: from ( "/this/include" ) ) ;
340+ d. excluded_directories . push ( PathBuf :: from ( "/this/include/sub" ) ) ;
341+ d. excluded_directories . push ( PathBuf :: from ( "/other/place" ) ) ;
342+
343+ let _msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
344+ assert_eq ! ( d. excluded_directories, vec![ PathBuf :: from( "/this/include/sub" ) ] ) ;
345+ }
346+
347+ #[ test]
348+ fn test_reference_dirs_and_files_retained_correctly ( ) {
349+ let mut d = Directories :: new ( ) ;
350+ d. included_directories . push ( PathBuf :: from ( "/a" ) ) ;
351+ d. included_files . push ( PathBuf :: from ( "/a/included_file.txt" ) ) ;
352+
353+ d. reference_directories . push ( PathBuf :: from ( "/a/sub" ) ) ;
354+ d. reference_directories . push ( PathBuf :: from ( "/other" ) ) ;
355+
356+ d. reference_files . push ( PathBuf :: from ( "/a/included_file.txt" ) ) ;
357+ d. reference_files . push ( PathBuf :: from ( "/other/file2.txt" ) ) ;
358+
359+ let _msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
360+
361+ assert_eq ! ( d. reference_directories, vec![ PathBuf :: from( "/a/sub" ) ] ) ;
362+ assert_eq ! ( d. reference_files, vec![ PathBuf :: from( "/a/included_file.txt" ) ] ) ;
363+ }
364+
365+ #[ test]
366+ fn test_reference_equals_included_error ( ) {
367+ let mut d = Directories :: new ( ) ;
368+ d. included_directories . push ( PathBuf :: from ( "/same" ) ) ;
369+ d. reference_directories . push ( PathBuf :: from ( "/same" ) ) ;
370+ d. included_files = Vec :: new ( ) ;
371+ d. reference_files = Vec :: new ( ) ;
372+
373+ let msgs = d. optimize_directories ( true , true ) . unwrap_err ( ) ;
374+ assert ! ( msgs. critical. is_some( ) ) ;
375+ }
376+
377+ #[ test]
378+ fn test_included_files_removed_when_equal_to_excluded_directory ( ) {
379+ let mut d = Directories :: new ( ) ;
380+ d. included_directories . push ( PathBuf :: from ( "/base" ) ) ;
381+ d. included_files . push ( PathBuf :: from ( "/base/file" ) ) ;
382+
383+ // excluded directory equals included file path
384+ d. excluded_directories . push ( PathBuf :: from ( "/base/file" ) ) ;
385+
386+ let _msgs = d. optimize_directories ( true , true ) . unwrap ( ) ;
387+ // included_files should be removed because it equals an excluded directory
388+ assert ! ( d. included_files. is_empty( ) ) ;
389+ // excluded_directories should be retained as it's inside included_directories
390+ assert_eq ! ( d. excluded_directories, vec![ PathBuf :: from( "/base/file" ) ] ) ;
391+ }
335392}
0 commit comments