@@ -259,6 +259,7 @@ pub fn glob_with(pattern: &str, options: MatchOptions) -> Result<Paths, PatternE
259259 original : "" . to_string ( ) ,
260260 tokens : Vec :: new ( ) ,
261261 is_recursive : false ,
262+ is_regular : true ,
262263 } ) ;
263264 }
264265
@@ -552,6 +553,7 @@ pub struct Pattern {
552553 original : String ,
553554 tokens : Vec < PatternToken > ,
554555 is_recursive : bool ,
556+ is_regular : bool ,
555557}
556558
557559/// Show the original glob pattern.
@@ -605,11 +607,13 @@ impl Pattern {
605607 let chars = pattern. chars ( ) . collect :: < Vec < _ > > ( ) ;
606608 let mut tokens = Vec :: new ( ) ;
607609 let mut is_recursive = false ;
610+ let mut is_regular = true ;
608611 let mut i = 0 ;
609612
610613 while i < chars. len ( ) {
611614 match chars[ i] {
612615 '?' => {
616+ is_regular = false ;
613617 tokens. push ( AnyChar ) ;
614618 i += 1 ;
615619 }
@@ -663,10 +667,12 @@ impl Pattern {
663667
664668 if !( tokens_len > 1 && tokens[ tokens_len - 1 ] == AnyRecursiveSequence ) {
665669 is_recursive = true ;
670+ is_regular = false ;
666671 tokens. push ( AnyRecursiveSequence ) ;
667672 }
668673 }
669674 } else {
675+ is_regular = false ;
670676 tokens. push ( AnySequence ) ;
671677 }
672678 }
@@ -678,6 +684,7 @@ impl Pattern {
678684 let chars = & chars[ i + 2 ..i + 3 + j] ;
679685 let cs = parse_char_specifiers ( chars) ;
680686 tokens. push ( AnyExcept ( cs) ) ;
687+ is_regular = false ;
681688 i += j + 4 ;
682689 continue ;
683690 }
@@ -688,6 +695,7 @@ impl Pattern {
688695 Some ( j) => {
689696 let cs = parse_char_specifiers ( & chars[ i + 1 ..i + 2 + j] ) ;
690697 tokens. push ( AnyWithin ( cs) ) ;
698+ is_regular = false ;
691699 i += j + 3 ;
692700 continue ;
693701 }
@@ -711,6 +719,7 @@ impl Pattern {
711719 tokens,
712720 original : pattern. to_string ( ) ,
713721 is_recursive,
722+ is_regular,
714723 } )
715724 }
716725
@@ -874,19 +883,6 @@ fn fill_todo(
874883 path : & PathWrapper ,
875884 options : MatchOptions ,
876885) {
877- // convert a pattern that's just many Char(_) to a string
878- fn pattern_as_str ( pattern : & Pattern ) -> Option < String > {
879- let mut s = String :: new ( ) ;
880- for token in & pattern. tokens {
881- match * token {
882- Char ( c) => s. push ( c) ,
883- _ => return None ,
884- }
885- }
886-
887- Some ( s)
888- }
889-
890886 let add = |todo : & mut Vec < _ > , next_path : PathWrapper | {
891887 if idx + 1 == patterns. len ( ) {
892888 // We know it's good, so don't make the iterator match this path
@@ -901,75 +897,70 @@ fn fill_todo(
901897 let pattern = & patterns[ idx] ;
902898 let is_dir = path. is_directory ;
903899 let curdir = path. as_ref ( ) == Path :: new ( "." ) ;
904- match pattern_as_str ( pattern) {
905- Some ( s) => {
906- // This pattern component doesn't have any metacharacters, so we
907- // don't need to read the current directory to know where to
908- // continue. So instead of passing control back to the iterator,
909- // we can just check for that one entry and potentially recurse
910- // right away.
911- let special = "." == s || ".." == s;
912- let next_path = if curdir {
913- PathBuf :: from ( s)
914- } else {
915- path. join ( & s)
916- } ;
917- let next_path = PathWrapper :: from_path ( next_path) ;
918- if ( special && is_dir)
919- || ( !special
920- && ( fs:: metadata ( & next_path) . is_ok ( )
921- || fs:: symlink_metadata ( & next_path) . is_ok ( ) ) )
922- {
923- add ( todo, next_path) ;
924- }
900+ if pattern. is_regular {
901+ let s = pattern. as_str ( ) ;
902+ // This pattern component doesn't have any metacharacters, so we
903+ // don't need to read the current directory to know where to
904+ // continue. So instead of passing control back to the iterator,
905+ // we can just check for that one entry and potentially recurse
906+ // right away.
907+ let special = "." == s || ".." == s;
908+ let next_path = if curdir {
909+ PathBuf :: from ( s)
910+ } else {
911+ path. join ( & s)
912+ } ;
913+ let next_path = PathWrapper :: from_path ( next_path) ;
914+ if ( special && is_dir)
915+ || ( !special
916+ && ( fs:: metadata ( & next_path) . is_ok ( ) || fs:: symlink_metadata ( & next_path) . is_ok ( ) ) )
917+ {
918+ add ( todo, next_path) ;
925919 }
926- None if is_dir => {
927- let dirs = fs:: read_dir ( path) . and_then ( |d| {
928- d. map ( |e| {
929- e. map ( |e| {
930- let path = if curdir {
931- PathBuf :: from ( e. path ( ) . file_name ( ) . unwrap ( ) )
932- } else {
933- e. path ( )
934- } ;
935- PathWrapper :: from_dir_entry ( path, e)
936- } )
920+ } else if is_dir {
921+ let dirs = fs:: read_dir ( path) . and_then ( |d| {
922+ d. map ( |e| {
923+ e. map ( |e| {
924+ let path = if curdir {
925+ PathBuf :: from ( e. path ( ) . file_name ( ) . unwrap ( ) )
926+ } else {
927+ e. path ( )
928+ } ;
929+ PathWrapper :: from_dir_entry ( path, e)
937930 } )
938- . collect :: < Result < Vec < _ > , _ > > ( )
939- } ) ;
940- match dirs {
941- Ok ( mut children) => {
942- if options. require_literal_leading_dot {
943- children
944- . retain ( |x| !x. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . starts_with ( "." ) ) ;
945- }
946- children. sort_by ( |p1, p2| p2. file_name ( ) . cmp ( & p1. file_name ( ) ) ) ;
947- todo. extend ( children. into_iter ( ) . map ( |x| Ok ( ( x, idx) ) ) ) ;
948-
949- // Matching the special directory entries . and .. that
950- // refer to the current and parent directory respectively
951- // requires that the pattern has a leading dot, even if the
952- // `MatchOptions` field `require_literal_leading_dot` is not
953- // set.
954- if !pattern. tokens . is_empty ( ) && pattern. tokens [ 0 ] == Char ( '.' ) {
955- for & special in & [ "." , ".." ] {
956- if pattern. matches_with ( special, options) {
957- add ( todo, PathWrapper :: from_path ( path. join ( special) ) ) ;
958- }
931+ } )
932+ . collect :: < Result < Vec < _ > , _ > > ( )
933+ } ) ;
934+ match dirs {
935+ Ok ( mut children) => {
936+ if options. require_literal_leading_dot {
937+ children. retain ( |x| !x. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . starts_with ( "." ) ) ;
938+ }
939+ children. sort_by ( |p1, p2| p2. file_name ( ) . cmp ( & p1. file_name ( ) ) ) ;
940+ todo. extend ( children. into_iter ( ) . map ( |x| Ok ( ( x, idx) ) ) ) ;
941+
942+ // Matching the special directory entries . and .. that
943+ // refer to the current and parent directory respectively
944+ // requires that the pattern has a leading dot, even if the
945+ // `MatchOptions` field `require_literal_leading_dot` is not
946+ // set.
947+ if !pattern. tokens . is_empty ( ) && pattern. tokens [ 0 ] == Char ( '.' ) {
948+ for & special in & [ "." , ".." ] {
949+ if pattern. matches_with ( special, options) {
950+ add ( todo, PathWrapper :: from_path ( path. join ( special) ) ) ;
959951 }
960952 }
961953 }
962- Err ( e ) => {
963- todo . push ( Err ( GlobError {
964- path : path . to_path_buf ( ) ,
965- error : e ,
966- } ) ) ;
967- }
954+ }
955+ Err ( e ) => {
956+ todo . push ( Err ( GlobError {
957+ path : path . to_path_buf ( ) ,
958+ error : e ,
959+ } ) ) ;
968960 }
969961 }
970- None => {
971- // not a directory, nothing more to find
972- }
962+ } else {
963+ // not a directory, nothing more to find
973964 }
974965}
975966
0 commit comments