mirror of
https://gitee.com/openharmony/third_party_rust_glob
synced 2024-11-26 17:20:25 +00:00
ran cargo fmt
This commit is contained in:
parent
3c53061d36
commit
2f09a1f7d2
319
src/lib.rs
319
src/lib.rs
@ -55,24 +55,26 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/glob/")]
|
||||
#![doc(
|
||||
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/glob/"
|
||||
)]
|
||||
#![deny(missing_docs)]
|
||||
#![cfg_attr(all(test, windows), feature(std_misc))]
|
||||
|
||||
use std::cmp;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{self, Path, PathBuf, Component};
|
||||
use std::path::{self, Component, Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::error::Error;
|
||||
|
||||
use PatternToken::{Char, AnyChar, AnySequence, AnyRecursiveSequence, AnyWithin};
|
||||
use CharSpecifier::{CharRange, SingleChar};
|
||||
use MatchResult::{EntirePatternDoesntMatch, Match, SubPatternDoesntMatch};
|
||||
use PatternToken::AnyExcept;
|
||||
use CharSpecifier::{SingleChar, CharRange};
|
||||
use MatchResult::{Match, SubPatternDoesntMatch, EntirePatternDoesntMatch};
|
||||
use PatternToken::{AnyChar, AnyRecursiveSequence, AnySequence, AnyWithin, Char};
|
||||
|
||||
/// An iterator that yields `Path`s from the filesystem that match a particular
|
||||
/// pattern.
|
||||
@ -165,8 +167,7 @@ pub fn glob(pattern: &str) -> Result<Paths, PatternError> {
|
||||
/// passed to this function.
|
||||
///
|
||||
/// Paths are yielded in alphabetical order.
|
||||
pub fn glob_with(pattern: &str, options: MatchOptions)
|
||||
-> Result<Paths, PatternError> {
|
||||
pub fn glob_with(pattern: &str, options: MatchOptions) -> Result<Paths, PatternError> {
|
||||
#[cfg(windows)]
|
||||
fn check_windows_verbatim(p: &Path) -> bool {
|
||||
use std::path::Prefix;
|
||||
@ -195,12 +196,10 @@ pub fn glob_with(pattern: &str, options: MatchOptions)
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
|
||||
let mut components = Path::new(pattern).components().peekable();
|
||||
loop {
|
||||
match components.peek() {
|
||||
Some(&Component::Prefix(..)) |
|
||||
Some(&Component::RootDir) => {
|
||||
Some(&Component::Prefix(..)) | Some(&Component::RootDir) => {
|
||||
components.next();
|
||||
}
|
||||
_ => break,
|
||||
@ -231,8 +230,8 @@ pub fn glob_with(pattern: &str, options: MatchOptions)
|
||||
let scope = root.map_or_else(|| PathBuf::from("."), to_scope);
|
||||
|
||||
let mut dir_patterns = Vec::new();
|
||||
let components = pattern[cmp::min(root_len, pattern.len())..]
|
||||
.split_terminator(path::is_separator);
|
||||
let components =
|
||||
pattern[cmp::min(root_len, pattern.len())..].split_terminator(path::is_separator);
|
||||
|
||||
for component in components {
|
||||
dir_patterns.push(Pattern::new(component)?);
|
||||
@ -299,10 +298,12 @@ impl Error for GlobError {
|
||||
|
||||
impl fmt::Display for GlobError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f,
|
||||
"attempting to read `{}` resulted in an error: {}",
|
||||
self.path.display(),
|
||||
self.error)
|
||||
write!(
|
||||
f,
|
||||
"attempting to read `{}` resulted in an error: {}",
|
||||
self.path.display(),
|
||||
self.error
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,11 +330,7 @@ impl Iterator for Paths {
|
||||
// Shouldn't happen, but we're using -1 as a special index.
|
||||
assert!(self.dir_patterns.len() < !0 as usize);
|
||||
|
||||
fill_todo(&mut self.todo,
|
||||
&self.dir_patterns,
|
||||
0,
|
||||
&scope,
|
||||
self.options);
|
||||
fill_todo(&mut self.todo, &self.dir_patterns, 0, &scope, self.options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,8 +357,9 @@ impl Iterator for Paths {
|
||||
let mut next = idx;
|
||||
|
||||
// collapse consecutive recursive patterns
|
||||
while (next + 1) < self.dir_patterns.len() &&
|
||||
self.dir_patterns[next + 1].is_recursive {
|
||||
while (next + 1) < self.dir_patterns.len()
|
||||
&& self.dir_patterns[next + 1].is_recursive
|
||||
{
|
||||
next += 1;
|
||||
}
|
||||
|
||||
@ -369,11 +367,13 @@ impl Iterator for Paths {
|
||||
// the path is a directory, so it's a match
|
||||
|
||||
// push this directory's contents
|
||||
fill_todo(&mut self.todo,
|
||||
&self.dir_patterns,
|
||||
next,
|
||||
&path,
|
||||
self.options);
|
||||
fill_todo(
|
||||
&mut self.todo,
|
||||
&self.dir_patterns,
|
||||
next,
|
||||
&path,
|
||||
self.options,
|
||||
);
|
||||
|
||||
if next == self.dir_patterns.len() - 1 {
|
||||
// pattern ends in recursive pattern, so return this
|
||||
@ -394,15 +394,18 @@ impl Iterator for Paths {
|
||||
}
|
||||
|
||||
// not recursive, so match normally
|
||||
if self.dir_patterns[idx].matches_with({
|
||||
match path.file_name().and_then(|s| s.to_str()) {
|
||||
// FIXME (#9639): How do we handle non-utf8 filenames?
|
||||
// Ignore them for now; ideally we'd still match them
|
||||
// against a *
|
||||
None => continue,
|
||||
Some(x) => x
|
||||
}
|
||||
}, self.options) {
|
||||
if self.dir_patterns[idx].matches_with(
|
||||
{
|
||||
match path.file_name().and_then(|s| s.to_str()) {
|
||||
// FIXME (#9639): How do we handle non-utf8 filenames?
|
||||
// Ignore them for now; ideally we'd still match them
|
||||
// against a *
|
||||
None => continue,
|
||||
Some(x) => x,
|
||||
}
|
||||
},
|
||||
self.options,
|
||||
) {
|
||||
if idx == self.dir_patterns.len() - 1 {
|
||||
// it is not possible for a pattern to match a directory
|
||||
// *AND* its children so we don't need to check the
|
||||
@ -412,8 +415,13 @@ impl Iterator for Paths {
|
||||
return Some(Ok(path));
|
||||
}
|
||||
} else {
|
||||
fill_todo(&mut self.todo, &self.dir_patterns,
|
||||
idx + 1, &path, self.options);
|
||||
fill_todo(
|
||||
&mut self.todo,
|
||||
&self.dir_patterns,
|
||||
idx + 1,
|
||||
&path,
|
||||
self.options,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -439,10 +447,11 @@ impl Error for PatternError {
|
||||
|
||||
impl fmt::Display for PatternError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f,
|
||||
"Pattern syntax error near position {}: {}",
|
||||
self.pos,
|
||||
self.msg)
|
||||
write!(
|
||||
f,
|
||||
"Pattern syntax error near position {}: {}",
|
||||
self.pos, self.msg
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,7 +527,7 @@ enum MatchResult {
|
||||
|
||||
const ERROR_WILDCARDS: &str = "wildcards are either regular `*` or recursive `**`";
|
||||
const ERROR_RECURSIVE_WILDCARDS: &str = "recursive wildcards must form a single path \
|
||||
component";
|
||||
component";
|
||||
const ERROR_INVALID_RANGE: &str = "invalid range pattern";
|
||||
|
||||
impl Pattern {
|
||||
@ -526,7 +535,6 @@ impl Pattern {
|
||||
///
|
||||
/// An invalid glob pattern will yield a `PatternError`.
|
||||
pub fn new(pattern: &str) -> Result<Self, PatternError> {
|
||||
|
||||
let chars = pattern.chars().collect::<Vec<_>>();
|
||||
let mut tokens = Vec::new();
|
||||
let mut is_recursive = false;
|
||||
@ -561,18 +569,18 @@ impl Pattern {
|
||||
if i < chars.len() && path::is_separator(chars[i]) {
|
||||
i += 1;
|
||||
true
|
||||
// or the pattern ends here
|
||||
// this enables the existing globbing mechanism
|
||||
// or the pattern ends here
|
||||
// this enables the existing globbing mechanism
|
||||
} else if i == chars.len() {
|
||||
true
|
||||
// `**` ends in non-separator
|
||||
// `**` ends in non-separator
|
||||
} else {
|
||||
return Err(PatternError {
|
||||
pos: i,
|
||||
msg: ERROR_RECURSIVE_WILDCARDS,
|
||||
});
|
||||
}
|
||||
// `**` begins with non-separator
|
||||
// `**` begins with non-separator
|
||||
} else {
|
||||
return Err(PatternError {
|
||||
pos: old - 1,
|
||||
@ -595,7 +603,6 @@ impl Pattern {
|
||||
}
|
||||
}
|
||||
'[' => {
|
||||
|
||||
if i + 4 <= chars.len() && chars[i + 1] == '!' {
|
||||
match chars[i + 3..].iter().position(|x| *x == ']') {
|
||||
None => (),
|
||||
@ -694,7 +701,8 @@ impl Pattern {
|
||||
/// `Pattern` using the specified match options.
|
||||
pub fn matches_path_with(&self, path: &Path, options: MatchOptions) -> bool {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
path.to_str().map_or(false, |s| self.matches_with(s, options))
|
||||
path.to_str()
|
||||
.map_or(false, |s| self.matches_with(s, options))
|
||||
}
|
||||
|
||||
/// Access the original glob pattern.
|
||||
@ -702,13 +710,13 @@ impl Pattern {
|
||||
&self.original
|
||||
}
|
||||
|
||||
fn matches_from(&self,
|
||||
mut follows_separator: bool,
|
||||
mut file: std::str::Chars,
|
||||
i: usize,
|
||||
options: MatchOptions)
|
||||
-> MatchResult {
|
||||
|
||||
fn matches_from(
|
||||
&self,
|
||||
mut follows_separator: bool,
|
||||
mut file: std::str::Chars,
|
||||
i: usize,
|
||||
options: MatchOptions,
|
||||
) -> MatchResult {
|
||||
for (ti, token) in self.tokens[i..].iter().enumerate() {
|
||||
match *token {
|
||||
AnySequence | AnyRecursiveSequence => {
|
||||
@ -731,14 +739,19 @@ impl Pattern {
|
||||
follows_separator = path::is_separator(c);
|
||||
match *token {
|
||||
AnyRecursiveSequence if !follows_separator => continue,
|
||||
AnySequence if options.require_literal_separator &&
|
||||
follows_separator => return SubPatternDoesntMatch,
|
||||
AnySequence
|
||||
if options.require_literal_separator && follows_separator =>
|
||||
{
|
||||
return SubPatternDoesntMatch
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
match self.matches_from(follows_separator,
|
||||
file.clone(),
|
||||
i + ti + 1,
|
||||
options) {
|
||||
match self.matches_from(
|
||||
follows_separator,
|
||||
file.clone(),
|
||||
i + ti + 1,
|
||||
options,
|
||||
) {
|
||||
SubPatternDoesntMatch => (), // keep trying
|
||||
m => return m,
|
||||
}
|
||||
@ -754,9 +767,13 @@ impl Pattern {
|
||||
|
||||
if !match *token {
|
||||
AnyChar | AnyWithin(..) | AnyExcept(..)
|
||||
if (options.require_literal_separator && is_sep) ||
|
||||
(follows_separator && options.require_literal_leading_dot &&
|
||||
c == '.') => false,
|
||||
if (options.require_literal_separator && is_sep)
|
||||
|| (follows_separator
|
||||
&& options.require_literal_leading_dot
|
||||
&& c == '.') =>
|
||||
{
|
||||
false
|
||||
}
|
||||
AnyChar => true,
|
||||
AnyWithin(ref specifiers) => in_char_specifiers(&specifiers, c, options),
|
||||
AnyExcept(ref specifiers) => !in_char_specifiers(&specifiers, c, options),
|
||||
@ -782,11 +799,13 @@ impl Pattern {
|
||||
// Fills `todo` with paths under `path` to be matched by `patterns[idx]`,
|
||||
// special-casing patterns to match `.` and `..`, and avoiding `readdir()`
|
||||
// calls when there are no metacharacters in the pattern.
|
||||
fn fill_todo(todo: &mut Vec<Result<(PathBuf, usize), GlobError>>,
|
||||
patterns: &[Pattern],
|
||||
idx: usize,
|
||||
path: &Path,
|
||||
options: MatchOptions) {
|
||||
fn fill_todo(
|
||||
todo: &mut Vec<Result<(PathBuf, usize), GlobError>>,
|
||||
patterns: &[Pattern],
|
||||
idx: usize,
|
||||
path: &Path,
|
||||
options: MatchOptions,
|
||||
) {
|
||||
// convert a pattern that's just many Char(_) to a string
|
||||
fn pattern_as_str(pattern: &Pattern) -> Option<String> {
|
||||
let mut s = String::new();
|
||||
@ -834,15 +853,15 @@ fn fill_todo(todo: &mut Vec<Result<(PathBuf, usize), GlobError>>,
|
||||
None if is_dir => {
|
||||
let dirs = fs::read_dir(path).and_then(|d| {
|
||||
d.map(|e| {
|
||||
e.map(|e| {
|
||||
if curdir {
|
||||
PathBuf::from(e.path().file_name().unwrap())
|
||||
} else {
|
||||
e.path()
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
e.map(|e| {
|
||||
if curdir {
|
||||
PathBuf::from(e.path().file_name().unwrap())
|
||||
} else {
|
||||
e.path()
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
});
|
||||
match dirs {
|
||||
Ok(mut children) => {
|
||||
@ -892,7 +911,6 @@ fn parse_char_specifiers(s: &[char]) -> Vec<CharSpecifier> {
|
||||
}
|
||||
|
||||
fn in_char_specifiers(specifiers: &[CharSpecifier], c: char, options: MatchOptions) -> bool {
|
||||
|
||||
for &specifier in specifiers.iter() {
|
||||
match specifier {
|
||||
SingleChar(sc) => {
|
||||
@ -901,10 +919,8 @@ fn in_char_specifiers(specifiers: &[CharSpecifier], c: char, options: MatchOptio
|
||||
}
|
||||
}
|
||||
CharRange(start, end) => {
|
||||
|
||||
// FIXME: work with non-ascii chars properly (issue #1347)
|
||||
if !options.case_sensitive && c.is_ascii() && start.is_ascii() && end.is_ascii() {
|
||||
|
||||
let start = start.to_ascii_lowercase();
|
||||
let end = end.to_ascii_lowercase();
|
||||
|
||||
@ -943,7 +959,6 @@ fn chars_eq(a: char, b: char, case_sensitive: bool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Configuration options to modify the behaviour of `Pattern::matches_with(..)`.
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
@ -992,8 +1007,8 @@ impl MatchOptions {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{glob, MatchOptions, Pattern};
|
||||
use std::path::Path;
|
||||
use super::{glob, Pattern, MatchOptions};
|
||||
|
||||
#[test]
|
||||
fn test_pattern_from_str() {
|
||||
@ -1031,7 +1046,7 @@ mod test {
|
||||
// this test assumes that there is a /root directory and that
|
||||
// the user running this test is not root or otherwise doesn't
|
||||
// have permission to read its contents
|
||||
#[cfg(all(unix, not(target_os="macos")))]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
#[test]
|
||||
fn test_iteration_errors() {
|
||||
use std::io;
|
||||
@ -1067,11 +1082,14 @@ mod test {
|
||||
|
||||
// check windows absolute paths with host/device components
|
||||
let root_with_device = current_dir()
|
||||
.ok()
|
||||
.and_then(|p| p.prefix().map(|p| p.join("*")))
|
||||
.unwrap();
|
||||
.ok()
|
||||
.and_then(|p| p.prefix().map(|p| p.join("*")))
|
||||
.unwrap();
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
assert!(glob(root_with_device.as_os_str().to_str().unwrap()).unwrap().next().is_some());
|
||||
assert!(glob(root_with_device.as_os_str().to_str().unwrap())
|
||||
.unwrap()
|
||||
.next()
|
||||
.is_some());
|
||||
}
|
||||
win()
|
||||
}
|
||||
@ -1083,11 +1101,15 @@ mod test {
|
||||
assert!(!Pattern::new("a*b*c").unwrap().matches("abcd"));
|
||||
assert!(Pattern::new("a*b*c").unwrap().matches("a_b_c"));
|
||||
assert!(Pattern::new("a*b*c").unwrap().matches("a___b___c"));
|
||||
assert!(Pattern::new("abc*abc*abc").unwrap().matches("abcabcabcabcabcabcabc"));
|
||||
assert!(!Pattern::new("abc*abc*abc").unwrap().matches("abcabcabcabcabcabcabca"));
|
||||
assert!(Pattern::new("abc*abc*abc")
|
||||
.unwrap()
|
||||
.matches("abcabcabcabcabcabcabc"));
|
||||
assert!(!Pattern::new("abc*abc*abc")
|
||||
.unwrap()
|
||||
.matches("abcabcabcabcabcabcabca"));
|
||||
assert!(Pattern::new("a*a*a*a*a*a*a*a*a")
|
||||
.unwrap()
|
||||
.matches("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
.unwrap()
|
||||
.matches("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
assert!(Pattern::new("a*b[xyz]c*d").unwrap().matches("abxcdbxcddd"));
|
||||
}
|
||||
|
||||
@ -1109,7 +1131,6 @@ mod test {
|
||||
assert!(pat.matches(".asdf"));
|
||||
assert!(pat.matches("/x/.asdf"));
|
||||
|
||||
|
||||
// collapse consecutive wildcards
|
||||
let pat = Pattern::new("some/**/**/needle.txt").unwrap();
|
||||
assert!(pat.matches("some/needle.txt"));
|
||||
@ -1148,7 +1169,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_range_pattern() {
|
||||
|
||||
let pat = Pattern::new("a[0-9]b").unwrap();
|
||||
for i in 0..10 {
|
||||
assert!(pat.matches(&format!("a{}b", i)));
|
||||
@ -1168,7 +1188,10 @@ mod test {
|
||||
assert!(pat.matches(&c.to_string()));
|
||||
}
|
||||
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars() {
|
||||
let options = MatchOptions { case_sensitive: false, ..MatchOptions::new() };
|
||||
let options = MatchOptions {
|
||||
case_sensitive: false,
|
||||
..MatchOptions::new()
|
||||
};
|
||||
assert!(pat.matches_with(&c.to_string(), options));
|
||||
}
|
||||
assert!(pat.matches("1"));
|
||||
@ -1221,7 +1244,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_pattern_matches_case_insensitive() {
|
||||
|
||||
let pat = Pattern::new("aBcDeFg").unwrap();
|
||||
let options = MatchOptions {
|
||||
case_sensitive: false,
|
||||
@ -1237,7 +1259,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_pattern_matches_case_insensitive_range() {
|
||||
|
||||
let pat_within = Pattern::new("[a]").unwrap();
|
||||
let pat_except = Pattern::new("[!a]").unwrap();
|
||||
|
||||
@ -1263,7 +1284,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_pattern_matches_require_literal_separator() {
|
||||
|
||||
let options_require_literal = MatchOptions {
|
||||
case_sensitive: true,
|
||||
require_literal_separator: true,
|
||||
@ -1275,34 +1295,35 @@ mod test {
|
||||
require_literal_leading_dot: false,
|
||||
};
|
||||
|
||||
assert!(Pattern::new("abc/def").unwrap().matches_with("abc/def", options_require_literal));
|
||||
assert!(Pattern::new("abc/def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
assert!(!Pattern::new("abc?def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
assert!(!Pattern::new("abc*def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
assert!(!Pattern::new("abc[/]def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_require_literal));
|
||||
|
||||
assert!(Pattern::new("abc/def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
assert!(Pattern::new("abc?def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
assert!(Pattern::new("abc*def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
assert!(Pattern::new("abc[/]def")
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
.unwrap()
|
||||
.matches_with("abc/def", options_not_require_literal));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pattern_matches_require_literal_leading_dot() {
|
||||
|
||||
let options_require_literal_leading_dot = MatchOptions {
|
||||
case_sensitive: true,
|
||||
require_literal_separator: false,
|
||||
@ -1314,33 +1335,59 @@ mod test {
|
||||
require_literal_leading_dot: false,
|
||||
};
|
||||
|
||||
let f = |options| Pattern::new("*.txt").unwrap().matches_with(".hello.txt", options);
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(!f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| Pattern::new(".*.*").unwrap().matches_with(".hello.txt", options);
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| Pattern::new("aaa/bbb/*").unwrap().matches_with("aaa/bbb/.ccc", options);
|
||||
let f = |options| {
|
||||
Pattern::new("*.txt")
|
||||
.unwrap()
|
||||
.matches_with(".hello.txt", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(!f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/bbb/*").unwrap().matches_with("aaa/bbb/c.c.c.", options)
|
||||
Pattern::new(".*.*")
|
||||
.unwrap()
|
||||
.matches_with(".hello.txt", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| Pattern::new("aaa/bbb/.*").unwrap().matches_with("aaa/bbb/.ccc", options);
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| Pattern::new("aaa/?bbb").unwrap().matches_with("aaa/.bbb", options);
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/bbb/*")
|
||||
.unwrap()
|
||||
.matches_with("aaa/bbb/.ccc", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(!f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| Pattern::new("aaa/[.]bbb").unwrap().matches_with("aaa/.bbb", options);
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/bbb/*")
|
||||
.unwrap()
|
||||
.matches_with("aaa/bbb/c.c.c.", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/bbb/.*")
|
||||
.unwrap()
|
||||
.matches_with("aaa/bbb/.ccc", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/?bbb")
|
||||
.unwrap()
|
||||
.matches_with("aaa/.bbb", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(!f(options_require_literal_leading_dot));
|
||||
|
||||
let f = |options| {
|
||||
Pattern::new("aaa/[.]bbb")
|
||||
.unwrap()
|
||||
.matches_with("aaa/.bbb", options)
|
||||
};
|
||||
assert!(f(options_not_require_literal_leading_dot));
|
||||
assert!(!f(options_require_literal_leading_dot));
|
||||
|
||||
|
@ -17,8 +17,8 @@ extern crate tempdir;
|
||||
|
||||
use glob::glob;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use tempdir::TempDir;
|
||||
|
||||
#[test]
|
||||
@ -79,63 +79,91 @@ fn main() {
|
||||
mk_file("r/three/c.md", false);
|
||||
|
||||
// all recursive entities
|
||||
assert_eq!(glob_vec("r/**"), vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/two")));
|
||||
assert_eq!(
|
||||
glob_vec("r/**"),
|
||||
vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/two")
|
||||
)
|
||||
);
|
||||
|
||||
// collapse consecutive recursive patterns
|
||||
assert_eq!(glob_vec("r/**/**"), vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/two")));
|
||||
assert_eq!(
|
||||
glob_vec("r/**/**"),
|
||||
vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/two")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("r/**/*"), vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/current_dir.md"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/a.md"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/one/another/deep/spelunking.md"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/three/c.md"),
|
||||
PathBuf::from("r/two"),
|
||||
PathBuf::from("r/two/b.md")));
|
||||
assert_eq!(
|
||||
glob_vec("r/**/*"),
|
||||
vec!(
|
||||
PathBuf::from("r/another"),
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/current_dir.md"),
|
||||
PathBuf::from("r/one"),
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another"),
|
||||
PathBuf::from("r/one/another/a.md"),
|
||||
PathBuf::from("r/one/another/deep"),
|
||||
PathBuf::from("r/one/another/deep/spelunking.md"),
|
||||
PathBuf::from("r/three"),
|
||||
PathBuf::from("r/three/c.md"),
|
||||
PathBuf::from("r/two"),
|
||||
PathBuf::from("r/two/b.md")
|
||||
)
|
||||
);
|
||||
|
||||
// followed by a wildcard
|
||||
assert_eq!(glob_vec("r/**/*.md"), vec!(
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/current_dir.md"),
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md"),
|
||||
PathBuf::from("r/one/another/deep/spelunking.md"),
|
||||
PathBuf::from("r/three/c.md"),
|
||||
PathBuf::from("r/two/b.md")));
|
||||
assert_eq!(
|
||||
glob_vec("r/**/*.md"),
|
||||
vec!(
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/current_dir.md"),
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md"),
|
||||
PathBuf::from("r/one/another/deep/spelunking.md"),
|
||||
PathBuf::from("r/three/c.md"),
|
||||
PathBuf::from("r/two/b.md")
|
||||
)
|
||||
);
|
||||
|
||||
// followed by a precise pattern
|
||||
assert_eq!(glob_vec("r/one/**/a.md"), vec!(
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")));
|
||||
assert_eq!(
|
||||
glob_vec("r/one/**/a.md"),
|
||||
vec!(
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")
|
||||
)
|
||||
);
|
||||
|
||||
// followed by another recursive pattern
|
||||
// collapses consecutive recursives into one
|
||||
assert_eq!(glob_vec("r/one/**/**/a.md"), vec!(
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")));
|
||||
assert_eq!(
|
||||
glob_vec("r/one/**/**/a.md"),
|
||||
vec!(
|
||||
PathBuf::from("r/one/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")
|
||||
)
|
||||
);
|
||||
|
||||
// followed by two precise patterns
|
||||
assert_eq!(glob_vec("r/**/another/a.md"), vec!(
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")));
|
||||
assert_eq!(
|
||||
glob_vec("r/**/another/a.md"),
|
||||
vec!(
|
||||
PathBuf::from("r/another/a.md"),
|
||||
PathBuf::from("r/one/another/a.md")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec(""), Vec::<PathBuf>::new());
|
||||
assert_eq!(glob_vec("."), vec!(PathBuf::from(".")));
|
||||
@ -155,20 +183,32 @@ fn main() {
|
||||
assert_eq!(glob_vec("aaa\\apple"), vec!(PathBuf::from("aaa/apple")));
|
||||
}
|
||||
|
||||
assert_eq!(glob_vec("???/"), vec!(
|
||||
PathBuf::from("aaa"),
|
||||
PathBuf::from("bbb"),
|
||||
PathBuf::from("ccc"),
|
||||
PathBuf::from("xyz")));
|
||||
assert_eq!(
|
||||
glob_vec("???/"),
|
||||
vec!(
|
||||
PathBuf::from("aaa"),
|
||||
PathBuf::from("bbb"),
|
||||
PathBuf::from("ccc"),
|
||||
PathBuf::from("xyz")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("aaa/tomato/tom?to.txt"), vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")));
|
||||
assert_eq!(
|
||||
glob_vec("aaa/tomato/tom?to.txt"),
|
||||
vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("xyz/?"), vec!(
|
||||
PathBuf::from("xyz/x"),
|
||||
PathBuf::from("xyz/y"),
|
||||
PathBuf::from("xyz/z")));
|
||||
assert_eq!(
|
||||
glob_vec("xyz/?"),
|
||||
vec!(
|
||||
PathBuf::from("xyz/x"),
|
||||
PathBuf::from("xyz/y"),
|
||||
PathBuf::from("xyz/z")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("a*"), vec!(PathBuf::from("aaa")));
|
||||
assert_eq!(glob_vec("*a*"), vec!(PathBuf::from("aaa")));
|
||||
@ -179,23 +219,39 @@ fn main() {
|
||||
assert_eq!(glob_vec("*a*a*a*"), vec!(PathBuf::from("aaa")));
|
||||
assert_eq!(glob_vec("aaa*/"), vec!(PathBuf::from("aaa")));
|
||||
|
||||
assert_eq!(glob_vec("aaa/*"), vec!(
|
||||
PathBuf::from("aaa/apple"),
|
||||
PathBuf::from("aaa/orange"),
|
||||
PathBuf::from("aaa/tomato")));
|
||||
assert_eq!(
|
||||
glob_vec("aaa/*"),
|
||||
vec!(
|
||||
PathBuf::from("aaa/apple"),
|
||||
PathBuf::from("aaa/orange"),
|
||||
PathBuf::from("aaa/tomato")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("aaa/*a*"), vec!(
|
||||
PathBuf::from("aaa/apple"),
|
||||
PathBuf::from("aaa/orange"),
|
||||
PathBuf::from("aaa/tomato")));
|
||||
assert_eq!(
|
||||
glob_vec("aaa/*a*"),
|
||||
vec!(
|
||||
PathBuf::from("aaa/apple"),
|
||||
PathBuf::from("aaa/orange"),
|
||||
PathBuf::from("aaa/tomato")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("*/*/*.txt"), vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")));
|
||||
assert_eq!(
|
||||
glob_vec("*/*/*.txt"),
|
||||
vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("*/*/t[aob]m?to[.]t[!y]t"), vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")));
|
||||
assert_eq!(
|
||||
glob_vec("*/*/t[aob]m?to[.]t[!y]t"),
|
||||
vec!(
|
||||
PathBuf::from("aaa/tomato/tomato.txt"),
|
||||
PathBuf::from("aaa/tomato/tomoto.txt")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("./aaa"), vec!(PathBuf::from("aaa")));
|
||||
assert_eq!(glob_vec("./*"), glob_vec("*"));
|
||||
@ -219,60 +275,103 @@ fn main() {
|
||||
assert_eq!(glob_vec("aa[!a]"), Vec::<PathBuf>::new());
|
||||
assert_eq!(glob_vec("aa[!abc]"), Vec::<PathBuf>::new());
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[[]"), vec!(PathBuf::from("bbb/specials/[")));
|
||||
assert_eq!(glob_vec("bbb/specials/!"), vec!(PathBuf::from("bbb/specials/!")));
|
||||
assert_eq!(glob_vec("bbb/specials/[]]"), vec!(PathBuf::from("bbb/specials/]")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[[]"),
|
||||
vec!(PathBuf::from("bbb/specials/["))
|
||||
);
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/!"),
|
||||
vec!(PathBuf::from("bbb/specials/!"))
|
||||
);
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[]]"),
|
||||
vec!(PathBuf::from("bbb/specials/]"))
|
||||
);
|
||||
|
||||
if env::consts::FAMILY != "windows" {
|
||||
assert_eq!(glob_vec("bbb/specials/[*]"), vec!(PathBuf::from("bbb/specials/*")));
|
||||
assert_eq!(glob_vec("bbb/specials/[?]"), vec!(PathBuf::from("bbb/specials/?")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[*]"),
|
||||
vec!(PathBuf::from("bbb/specials/*"))
|
||||
);
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[?]"),
|
||||
vec!(PathBuf::from("bbb/specials/?"))
|
||||
);
|
||||
}
|
||||
|
||||
if env::consts::FAMILY == "windows" {
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[![]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[![]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!]]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/[")));
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!!]"), vec!(
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!]]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/[")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!!]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[![]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[![]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!]]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/[")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!]]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/[")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!!]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!!]"), vec!(
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!*]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
|
||||
assert_eq!(glob_vec("bbb/specials/[!?]"), vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")));
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!*]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/?"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
glob_vec("bbb/specials/[!?]"),
|
||||
vec!(
|
||||
PathBuf::from("bbb/specials/!"),
|
||||
PathBuf::from("bbb/specials/*"),
|
||||
PathBuf::from("bbb/specials/["),
|
||||
PathBuf::from("bbb/specials/]")
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user