11use crate :: crossdev;
22use crate :: traverse:: { EntryData , Tree , TreeIndex } ;
33use byte_unit:: { n_gb_bytes, n_gib_bytes, n_mb_bytes, n_mib_bytes, ByteUnit } ;
4- use std:: fs ;
4+ use std:: collections :: BTreeSet ;
55use std:: path:: PathBuf ;
66use std:: sync:: atomic:: { AtomicBool , Ordering } ;
77use std:: sync:: Arc ;
@@ -171,14 +171,15 @@ pub struct WalkOptions {
171171 pub apparent_size : bool ,
172172 pub sorting : TraversalSorting ,
173173 pub cross_filesystems : bool ,
174- pub ignore_dirs : Vec < PathBuf > ,
174+ pub ignore_dirs : BTreeSet < PathBuf > ,
175175}
176176
177177type WalkDir = jwalk:: WalkDirGeneric < ( ( ) , Option < Result < std:: fs:: Metadata , jwalk:: Error > > ) > ;
178178
179179impl WalkOptions {
180180 pub ( crate ) fn iter_from_path ( & self , root : & Path , root_device_id : u64 ) -> WalkDir {
181181 let ignore_dirs = self . ignore_dirs . clone ( ) ;
182+ let cwd = std:: env:: current_dir ( ) . unwrap_or_else ( |_| root. to_owned ( ) ) ;
182183 WalkDir :: new ( root)
183184 . follow_links ( false )
184185 . sort ( match self . sorting {
@@ -199,7 +200,9 @@ impl WalkOptions {
199200 . as_ref ( )
200201 . map ( |m| crossdev:: is_same_device ( root_device_id, m) )
201202 . unwrap_or ( true ) ;
202- if !ok_for_fs || ignore_directory ( & dir_entry. path ( ) , & ignore_dirs) {
203+ if !ok_for_fs
204+ || ignore_directory ( & dir_entry. path ( ) , & ignore_dirs, & cwd)
205+ {
203206 dir_entry. read_children_path = None ;
204207 }
205208 }
@@ -241,21 +244,29 @@ impl WalkResult {
241244 }
242245}
243246
244- pub fn canonicalize_ignore_dirs ( ignore_dirs : & [ PathBuf ] ) -> Vec < PathBuf > {
245- ignore_dirs
247+ pub fn canonicalize_ignore_dirs ( ignore_dirs : & [ PathBuf ] ) -> BTreeSet < PathBuf > {
248+ let dirs = ignore_dirs
246249 . iter ( )
247- . map ( fs :: canonicalize )
250+ . map ( gix_path :: realpath )
248251 . filter_map ( Result :: ok)
249- . collect ( )
252+ . collect ( ) ;
253+ log:: info!( "Ignoring canonicalized {dirs:?}" ) ;
254+ dirs
250255}
251256
252- fn ignore_directory ( path : & Path , ignore_dirs : & [ PathBuf ] ) -> bool {
257+ fn ignore_directory ( path : & Path , ignore_dirs : & BTreeSet < PathBuf > , cwd : & Path ) -> bool {
253258 if ignore_dirs. is_empty ( ) {
254259 return false ;
255260 }
256- let path = fs:: canonicalize ( path) ;
257- path. map ( |path| ignore_dirs. contains ( & path) )
258- . unwrap_or ( false )
261+ let path = gix_path:: realpath_opts ( path, cwd, 32 ) ;
262+ path. map ( |path| {
263+ let ignored = ignore_dirs. contains ( & path) ;
264+ if ignored {
265+ log:: debug!( "Ignored {path:?}" ) ;
266+ }
267+ ignored
268+ } )
269+ . unwrap_or ( false )
259270}
260271
261272#[ cfg( test) ]
@@ -264,6 +275,7 @@ mod tests {
264275
265276 #[ test]
266277 fn test_ignore_directories ( ) {
278+ let cwd = std:: env:: current_dir ( ) . unwrap ( ) ;
267279 #[ cfg( unix) ]
268280 let mut parameters = vec ! [
269281 ( "/usr" , vec![ "/usr" ] , true ) ,
@@ -303,7 +315,7 @@ mod tests {
303315 & ignore_dirs. into_iter ( ) . map ( Into :: into) . collect :: < Vec < _ > > ( ) ,
304316 ) ;
305317 assert_eq ! (
306- ignore_directory( path. as_ref( ) , & ignore_dirs) ,
318+ ignore_directory( path. as_ref( ) , & ignore_dirs, & cwd ) ,
307319 expected_result,
308320 "result='{expected_result}' for path='{path}' and ignore_dir='{ignore_dirs:?}' "
309321 ) ;
0 commit comments