@@ -73,7 +73,9 @@ use std::cmp;
73
73
use std:: error:: Error ;
74
74
use std:: fmt;
75
75
use std:: fs;
76
+ use std:: fs:: DirEntry ;
76
77
use std:: io;
78
+ use std:: ops:: Deref ;
77
79
use std:: path:: { self , Component , Path , PathBuf } ;
78
80
use std:: str:: FromStr ;
79
81
@@ -96,8 +98,8 @@ pub struct Paths {
96
98
dir_patterns : Vec < Pattern > ,
97
99
require_dir : bool ,
98
100
options : MatchOptions ,
99
- todo : Vec < Result < ( PathBuf , usize ) , GlobError > > ,
100
- scope : Option < PathBuf > ,
101
+ todo : Vec < Result < ( PathWrapper , usize ) , GlobError > > ,
102
+ scope : Option < PathWrapper > ,
101
103
}
102
104
103
105
/// Return an iterator that produces all the `Path`s that match the given
@@ -242,6 +244,7 @@ pub fn glob_with(pattern: &str, options: MatchOptions) -> Result<Paths, PatternE
242
244
}
243
245
244
246
let scope = root. map_or_else ( || PathBuf :: from ( "." ) , to_scope) ;
247
+ let scope = PathWrapper :: from_path ( scope) ;
245
248
246
249
let mut dir_patterns = Vec :: new ( ) ;
247
250
let components =
@@ -323,8 +326,45 @@ impl fmt::Display for GlobError {
323
326
}
324
327
}
325
328
326
- fn is_dir ( p : & Path ) -> bool {
327
- fs:: metadata ( p) . map ( |m| m. is_dir ( ) ) . unwrap_or ( false )
329
+ #[ derive( Debug ) ]
330
+ struct PathWrapper {
331
+ path : PathBuf ,
332
+ is_dir : Option < bool > ,
333
+ }
334
+
335
+ impl PathWrapper {
336
+ fn from_dir_entry ( path : PathBuf , e : DirEntry ) -> Self {
337
+ Self {
338
+ path,
339
+ is_dir : e. file_type ( ) . ok ( ) . map ( |file_type| file_type. is_dir ( ) ) ,
340
+ }
341
+ }
342
+ fn from_path ( path : PathBuf ) -> Self {
343
+ Self { path, is_dir : None }
344
+ }
345
+
346
+ fn into_path ( self ) -> PathBuf {
347
+ self . path
348
+ }
349
+ }
350
+
351
+ impl Deref for PathWrapper {
352
+ type Target = Path ;
353
+
354
+ fn deref ( & self ) -> & Self :: Target {
355
+ self . path . deref ( )
356
+ }
357
+ }
358
+
359
+ impl AsRef < Path > for PathWrapper {
360
+ fn as_ref ( & self ) -> & Path {
361
+ self . path . as_ref ( )
362
+ }
363
+ }
364
+
365
+ fn is_dir ( p : & PathWrapper ) -> bool {
366
+ p. is_dir
367
+ . unwrap_or_else ( || fs:: metadata ( & p. path ) . map ( |m| m. is_dir ( ) ) . unwrap_or ( false ) )
328
368
}
329
369
330
370
/// An alias for a glob iteration result.
@@ -366,7 +406,7 @@ impl Iterator for Paths {
366
406
if self . require_dir && !is_dir ( & path) {
367
407
continue ;
368
408
}
369
- return Some ( Ok ( path) ) ;
409
+ return Some ( Ok ( path. into_path ( ) ) ) ;
370
410
}
371
411
372
412
if self . dir_patterns [ idx] . is_recursive {
@@ -394,7 +434,7 @@ impl Iterator for Paths {
394
434
if next == self . dir_patterns . len ( ) - 1 {
395
435
// pattern ends in recursive pattern, so return this
396
436
// directory as a result
397
- return Some ( Ok ( path) ) ;
437
+ return Some ( Ok ( path. into_path ( ) ) ) ;
398
438
} else {
399
439
// advanced to the next pattern for this path
400
440
idx = next + 1 ;
@@ -428,7 +468,7 @@ impl Iterator for Paths {
428
468
// children
429
469
430
470
if !self . require_dir || is_dir ( & path) {
431
- return Some ( Ok ( path) ) ;
471
+ return Some ( Ok ( path. into_path ( ) ) ) ;
432
472
}
433
473
} else {
434
474
fill_todo (
@@ -817,10 +857,10 @@ impl Pattern {
817
857
// special-casing patterns to match `.` and `..`, and avoiding `readdir()`
818
858
// calls when there are no metacharacters in the pattern.
819
859
fn fill_todo (
820
- todo : & mut Vec < Result < ( PathBuf , usize ) , GlobError > > ,
860
+ todo : & mut Vec < Result < ( PathWrapper , usize ) , GlobError > > ,
821
861
patterns : & [ Pattern ] ,
822
862
idx : usize ,
823
- path : & Path ,
863
+ path : & PathWrapper ,
824
864
options : MatchOptions ,
825
865
) {
826
866
// convert a pattern that's just many Char(_) to a string
@@ -836,7 +876,7 @@ fn fill_todo(
836
876
Some ( s)
837
877
}
838
878
839
- let add = |todo : & mut Vec < _ > , next_path : PathBuf | {
879
+ let add = |todo : & mut Vec < _ > , next_path : PathWrapper | {
840
880
if idx + 1 == patterns. len ( ) {
841
881
// We know it's good, so don't make the iterator match this path
842
882
// against the pattern again. In particular, it can't match
@@ -849,7 +889,7 @@ fn fill_todo(
849
889
850
890
let pattern = & patterns[ idx] ;
851
891
let is_dir = is_dir ( path) ;
852
- let curdir = path == Path :: new ( "." ) ;
892
+ let curdir = path. as_ref ( ) == Path :: new ( "." ) ;
853
893
match pattern_as_str ( pattern) {
854
894
Some ( s) => {
855
895
// This pattern component doesn't have any metacharacters, so we
@@ -863,6 +903,7 @@ fn fill_todo(
863
903
} else {
864
904
path. join ( & s)
865
905
} ;
906
+ let next_path = PathWrapper :: from_path ( next_path) ;
866
907
if ( special && is_dir)
867
908
|| ( !special
868
909
&& ( fs:: metadata ( & next_path) . is_ok ( )
@@ -875,19 +916,21 @@ fn fill_todo(
875
916
let dirs = fs:: read_dir ( path) . and_then ( |d| {
876
917
d. map ( |e| {
877
918
e. map ( |e| {
878
- if curdir {
919
+ let path = if curdir {
879
920
PathBuf :: from ( e. path ( ) . file_name ( ) . unwrap ( ) )
880
921
} else {
881
922
e. path ( )
882
- }
923
+ } ;
924
+ PathWrapper :: from_dir_entry ( path, e)
883
925
} )
884
926
} )
885
927
. collect :: < Result < Vec < _ > , _ > > ( )
886
928
} ) ;
887
929
match dirs {
888
930
Ok ( mut children) => {
889
931
if options. require_literal_leading_dot {
890
- children. retain ( |x| !x. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . starts_with ( "." ) ) ;
932
+ children
933
+ . retain ( |x| !x. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . starts_with ( "." ) ) ;
891
934
}
892
935
children. sort_by ( |p1, p2| p2. file_name ( ) . cmp ( & p1. file_name ( ) ) ) ;
893
936
todo. extend ( children. into_iter ( ) . map ( |x| Ok ( ( x, idx) ) ) ) ;
@@ -900,7 +943,7 @@ fn fill_todo(
900
943
if !pattern. tokens . is_empty ( ) && pattern. tokens [ 0 ] == Char ( '.' ) {
901
944
for & special in & [ "." , ".." ] {
902
945
if pattern. matches_with ( special, options) {
903
- add ( todo, path. join ( special) ) ;
946
+ add ( todo, PathWrapper :: from_path ( path. join ( special) ) ) ;
904
947
}
905
948
}
906
949
}
0 commit comments