47
47
//! case_sensitive: false,
48
48
//! require_literal_separator: false,
49
49
//! require_literal_leading_dot: false,
50
+ //! follow_links: false,
50
51
//! };
51
52
//! for entry in glob_with("local/*a*", &options).unwrap() {
52
53
//! if let Ok(path) = entry {
@@ -299,8 +300,13 @@ impl fmt::Display for GlobError {
299
300
}
300
301
}
301
302
302
- fn is_dir ( p : & Path ) -> bool {
303
- fs:: metadata ( p) . map ( |m| m. is_dir ( ) ) . unwrap_or ( false )
303
+ fn is_dir ( p : & Path , follow_links : bool ) -> bool {
304
+ let metadata = if follow_links {
305
+ fs:: metadata ( p)
306
+ } else {
307
+ fs:: symlink_metadata ( p)
308
+ } ;
309
+ metadata. map ( |m| m. is_dir ( ) ) . unwrap_or ( false )
304
310
}
305
311
306
312
/// An alias for a glob iteration result.
@@ -343,7 +349,8 @@ impl Iterator for Paths {
343
349
// idx -1: was already checked by fill_todo, maybe path was '.' or
344
350
// '..' that we can't match here because of normalization.
345
351
if idx == !0 as usize {
346
- if self . require_dir && !is_dir ( & path) {
352
+ if self . require_dir && !is_dir ( & path,
353
+ self . options . follow_links ) {
347
354
continue ;
348
355
}
349
356
return Some ( Ok ( path) ) ;
@@ -358,7 +365,7 @@ impl Iterator for Paths {
358
365
next += 1 ;
359
366
}
360
367
361
- if is_dir ( & path) {
368
+ if is_dir ( & path, self . options . follow_links ) {
362
369
// the path is a directory, so it's a match
363
370
364
371
// push this directory's contents
@@ -401,7 +408,8 @@ impl Iterator for Paths {
401
408
// *AND* its children so we don't need to check the
402
409
// children
403
410
404
- if !self . require_dir || is_dir ( & path) {
411
+ if !self . require_dir || is_dir ( & path,
412
+ self . options . follow_links ) {
405
413
return Some ( Ok ( path) ) ;
406
414
}
407
415
} else {
@@ -804,7 +812,7 @@ fn fill_todo(todo: &mut Vec<Result<(PathBuf, usize), GlobError>>,
804
812
} ;
805
813
806
814
let pattern = & patterns[ idx] ;
807
- let is_dir = is_dir ( path) ;
815
+ let is_dir = is_dir ( path, options . follow_links ) ;
808
816
let curdir = path == Path :: new ( "." ) ;
809
817
match pattern_as_str ( pattern) {
810
818
Some ( s) => {
@@ -957,6 +965,10 @@ pub struct MatchOptions {
957
965
/// conventionally considered hidden on Unix systems and it might be
958
966
/// desirable to skip them when listing files.
959
967
pub require_literal_leading_dot : bool ,
968
+
969
+ /// Whether ot not paths that are symbolic links are followed
970
+ /// during the walk.
971
+ pub follow_links : bool ,
960
972
}
961
973
962
974
impl MatchOptions {
@@ -970,14 +982,16 @@ impl MatchOptions {
970
982
/// MatchOptions {
971
983
/// case_sensitive: true,
972
984
/// require_literal_separator: false,
973
- /// require_literal_leading_dot: false
985
+ /// require_literal_leading_dot: false,
986
+ /// follow_links: false,
974
987
/// }
975
988
/// ```
976
989
pub fn new ( ) -> MatchOptions {
977
990
MatchOptions {
978
991
case_sensitive : true ,
979
992
require_literal_separator : false ,
980
993
require_literal_leading_dot : false ,
994
+ follow_links : false ,
981
995
}
982
996
}
983
997
}
@@ -1219,6 +1233,7 @@ mod test {
1219
1233
case_sensitive : false ,
1220
1234
require_literal_separator : false ,
1221
1235
require_literal_leading_dot : false ,
1236
+ follow_links : false ,
1222
1237
} ;
1223
1238
1224
1239
assert ! ( pat. matches_with( "aBcDeFg" , & options) ) ;
@@ -1237,11 +1252,13 @@ mod test {
1237
1252
case_sensitive : false ,
1238
1253
require_literal_separator : false ,
1239
1254
require_literal_leading_dot : false ,
1255
+ follow_links : false ,
1240
1256
} ;
1241
1257
let options_case_sensitive = MatchOptions {
1242
1258
case_sensitive : true ,
1243
1259
require_literal_separator : false ,
1244
1260
require_literal_leading_dot : false ,
1261
+ follow_links : false ,
1245
1262
} ;
1246
1263
1247
1264
assert ! ( pat_within. matches_with( "a" , & options_case_insensitive) ) ;
@@ -1260,11 +1277,13 @@ mod test {
1260
1277
case_sensitive : true ,
1261
1278
require_literal_separator : true ,
1262
1279
require_literal_leading_dot : false ,
1280
+ follow_links : false ,
1263
1281
} ;
1264
1282
let options_not_require_literal = MatchOptions {
1265
1283
case_sensitive : true ,
1266
1284
require_literal_separator : false ,
1267
1285
require_literal_leading_dot : false ,
1286
+ follow_links : false ,
1268
1287
} ;
1269
1288
1270
1289
assert ! ( Pattern :: new( "abc/def" ) . unwrap( ) . matches_with( "abc/def" , & options_require_literal) ) ;
@@ -1299,11 +1318,13 @@ mod test {
1299
1318
case_sensitive : true ,
1300
1319
require_literal_separator : false ,
1301
1320
require_literal_leading_dot : true ,
1321
+ follow_links : false ,
1302
1322
} ;
1303
1323
let options_not_require_literal_leading_dot = MatchOptions {
1304
1324
case_sensitive : true ,
1305
1325
require_literal_separator : false ,
1306
1326
require_literal_leading_dot : false ,
1327
+ follow_links : false ,
1307
1328
} ;
1308
1329
1309
1330
let f = |options| Pattern :: new ( "*.txt" ) . unwrap ( ) . matches_with ( ".hello.txt" , options) ;
0 commit comments