use std::borrow::Cow;
pub fn to_absolute_globs(file_patterns: Vec<String>, base_dir: &str) -> Vec<String> {
file_patterns.into_iter().map(|p| to_absolute_glob(&p, base_dir)).collect()
}
pub fn to_absolute_glob(pattern: &str, dir: &str) -> String {
let mut pattern = pattern.replace("\\", "/");
let dir = dir.replace("\\", "/");
let is_negated = is_negated_glob(&pattern);
if is_negated {
pattern.drain(..1); }
let is_relative = match pattern.find("/") {
Some(index) => index != pattern.len() - 1, None => false,
};
if pattern.starts_with("./") {
pattern.drain(..2);
}
if pattern == "." {
pattern = String::new();
}
let suffix = pattern.chars().last();
if !is_absolute_pattern(&pattern) {
if is_relative || pattern.starts_with("**/") || pattern.trim().is_empty() {
pattern = glob_join(dir, pattern);
} else {
pattern = glob_join(dir, format!("**/{}", pattern));
}
}
if suffix == Some('/') && !pattern.ends_with('/') {
pattern.push('/');
}
if is_negated {
format!("!{}", pattern)
} else {
pattern
}
}
pub fn is_negated_glob(pattern: &str) -> bool {
let mut chars = pattern.chars();
let first_char = chars.next();
let second_char = chars.next();
return first_char == Some('!') && second_char != Some('(');
}
fn glob_join(dir: String, pattern: String) -> String {
let dir = if dir.ends_with('/') {
Cow::Borrowed(&dir[..dir.len() - 1])
} else {
Cow::Owned(dir)
};
let pattern = if pattern.starts_with('/') {
Cow::Borrowed(&pattern[1..])
} else {
Cow::Owned(pattern)
};
if pattern.len() == 0 {
dir.into_owned()
} else {
format!("{}/{}", dir, pattern)
}
}
pub fn is_absolute_pattern(pattern: &str) -> bool {
let pattern = if is_negated_glob(pattern) { &pattern[1..] } else { &pattern };
pattern.starts_with("/") || is_windows_absolute_pattern(pattern)
}
fn is_windows_absolute_pattern(pattern: &str) -> bool {
let mut chars = pattern.chars();
let next_char = chars.next();
if next_char.is_none() || !next_char.unwrap().is_ascii_alphabetic() {
return false;
}
let mut next_char = chars.next();
while next_char.is_some() && next_char.unwrap().is_ascii_alphabetic() {
next_char = chars.next();
}
if next_char != Some(':') {
return false;
}
let next_char = chars.next();
matches!(next_char, Some('/'))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_should_get_if_absolute_pattern() {
assert_eq!(is_absolute_pattern("test.ts"), false);
assert_eq!(is_absolute_pattern("!test.ts"), false);
assert_eq!(is_absolute_pattern("/test.ts"), true);
assert_eq!(is_absolute_pattern("!/test.ts"), true);
assert_eq!(is_absolute_pattern("D:/test.ts"), true);
assert_eq!(is_absolute_pattern("!D:/test.ts"), true);
}
#[test]
fn it_should_get_absolute_globs() {
assert_eq!(to_absolute_glob("**/*.ts", "/"), "/**/*.ts");
assert_eq!(to_absolute_glob("/**/*.ts", "/"), "/**/*.ts");
assert_eq!(to_absolute_glob("**/*.ts", "/test"), "/test/**/*.ts");
assert_eq!(to_absolute_glob("**/*.ts", "/test/"), "/test/**/*.ts");
assert_eq!(to_absolute_glob("/**/*.ts", "/test"), "/**/*.ts");
assert_eq!(to_absolute_glob("/**/*.ts", "/test/"), "/**/*.ts");
assert_eq!(to_absolute_glob("D:/**/*.ts", "/test/"), "D:/**/*.ts");
assert_eq!(to_absolute_glob("**/*.ts", "D:/"), "D:/**/*.ts");
assert_eq!(to_absolute_glob(".", "D:\\test"), "D:/test");
assert_eq!(to_absolute_glob("\\test\\asdf.ts", "D:\\test"), "/test/asdf.ts");
assert_eq!(to_absolute_glob("!**/*.ts", "D:\\test"), "!D:/test/**/*.ts");
assert_eq!(to_absolute_glob("///test/**/*.ts", "D:\\test"), "///test/**/*.ts");
assert_eq!(to_absolute_glob("**/*.ts", "CD:\\"), "CD:/**/*.ts");
assert_eq!(to_absolute_glob("./test.ts", "/test/"), "/test/test.ts");
assert_eq!(to_absolute_glob("test.ts", "/test/"), "/test/**/test.ts");
assert_eq!(to_absolute_glob("*/test.ts", "/test/"), "/test/*/test.ts");
assert_eq!(to_absolute_glob("*test.ts", "/test/"), "/test/**/*test.ts");
assert_eq!(to_absolute_glob("**/test.ts", "/test/"), "/test/**/test.ts");
assert_eq!(to_absolute_glob("/test.ts", "/test/"), "/test.ts");
assert_eq!(to_absolute_glob("test/", "/test/"), "/test/**/test/");
assert_eq!(to_absolute_glob("!./test.ts", "/test/"), "!/test/test.ts");
assert_eq!(to_absolute_glob("!test.ts", "/test/"), "!/test/**/test.ts");
assert_eq!(to_absolute_glob("!*/test.ts", "/test/"), "!/test/*/test.ts");
assert_eq!(to_absolute_glob("!*test.ts", "/test/"), "!/test/**/*test.ts");
assert_eq!(to_absolute_glob("!**/test.ts", "/test/"), "!/test/**/test.ts");
assert_eq!(to_absolute_glob("!/test.ts", "/test/"), "!/test.ts");
assert_eq!(to_absolute_glob("!test/", "/test/"), "!/test/**/test/");
assert_eq!(to_absolute_glob("test/test.ts", "/test/"), "/test/test/test.ts");
}
}