fix(core): change combine glob patterns to use the +() pattern (#20254)

This commit is contained in:
Jonathan Cammisuli 2023-11-17 11:33:39 -05:00 committed by GitHub
parent dc8c0edb70
commit ed77cb0b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 2 deletions

View File

@ -69,11 +69,22 @@ impl NxGlobSet {
}
}
fn potential_glob_split(
glob: &str,
) -> itertools::Either<std::str::Split<char>, std::iter::Once<&str>> {
use itertools::Either::*;
if glob.starts_with('{') && glob.ends_with('}') {
Left(glob.trim_matches('{').trim_end_matches('}').split(','))
} else {
Right(std::iter::once(glob))
}
}
pub(crate) fn build_glob_set<S: AsRef<str> + Debug>(globs: &[S]) -> anyhow::Result<NxGlobSet> {
let result = globs
.iter()
.map(|s| {
let glob = s.as_ref();
.flat_map(|s| potential_glob_split(s.as_ref()))
.map(|glob| {
if glob.contains('!') || glob.contains('|') || glob.contains('(') {
convert_glob(glob)
} else {
@ -214,6 +225,12 @@ mod test {
assert!(!glob_set.is_match("packages/package-a-b"));
assert!(!glob_set.is_match("packages/package-a-b/nested"));
assert!(!glob_set.is_match("packages/package-b/nested"));
let glob_set = build_glob_set(&["packages/!(package-a)*/package.json"]).unwrap();
assert!(glob_set.is_match("packages/package-b/package.json"));
assert!(glob_set.is_match("packages/package-c/package.json"));
assert!(!glob_set.is_match("packages/package-a/package.json"));
assert!(!glob_set.is_match("packages/package/a/package.json"));
}
#[test]
@ -283,4 +300,24 @@ mod test {
assert!(!glob_set.is_match("test.module.spec.tsx"));
assert!(!glob_set.is_match("nested/comp.test.component.spec.ts"));
}
#[test]
fn supports_brace_expansion() {
let glob_set = build_glob_set(&["{packages,apps}/*"]).unwrap();
assert!(glob_set.is_match("packages/package-a"));
assert!(glob_set.is_match("apps/app-a"));
assert!(!glob_set.is_match("apps/app-a/nested"));
let glob_set = build_glob_set(&["{package-lock.json,yarn.lock,pnpm-lock.yaml}"]).unwrap();
assert!(glob_set.is_match("package-lock.json"));
assert!(glob_set.is_match("yarn.lock"));
assert!(glob_set.is_match("pnpm-lock.yaml"));
let glob_set =
build_glob_set(&["{packages/!(package-a)*/package.json,packages/*/package.json}"])
.unwrap();
assert!(glob_set.is_match("packages/package-b/package.json"));
assert!(glob_set.is_match("packages/package-c/package.json"));
assert!(!glob_set.is_match("packages/package-a/package.json"));
}
}

View File

@ -13,7 +13,10 @@ pub enum GlobGroup<'a> {
ExactOne(Cow<'a, str>),
// !(a|b|c)
Negated(Cow<'a, str>),
// !(a|b|c).js
NegatedFileName(Cow<'a, str>),
// !(a|b|c)*
NegatedWildcard(Cow<'a, str>),
NonSpecialGroup(Cow<'a, str>),
NonSpecial(Cow<'a, str>),
}
@ -40,6 +43,13 @@ impl<'a> Display for GlobGroup<'a> {
write!(f, "{}.", s)
}
}
GlobGroup::NegatedWildcard(s) => {
if s.contains(',') {
write!(f, "{{{}}}*", s)
} else {
write!(f, "{}*", s)
}
}
GlobGroup::NonSpecial(s) => write!(f, "{}", s),
}
}

View File

@ -58,6 +58,14 @@ fn negated_file_group(input: &str) -> IResult<&str, GlobGroup, VerboseError<&str
})(input)
}
fn negated_wildcard(input: &str) -> IResult<&str, GlobGroup, VerboseError<&str>> {
context("negated_wildcard", |input| {
let (input, result) = preceded(tag("!("), group)(input)?;
let (input, _) = tag("*")(input)?;
Ok((input, GlobGroup::NegatedWildcard(result)))
})(input)
}
fn non_special_character(input: &str) -> IResult<&str, GlobGroup, VerboseError<&str>> {
context(
"non_special_character",
@ -107,6 +115,7 @@ fn parse_segment(input: &str) -> IResult<&str, Vec<GlobGroup>, VerboseError<&str
one_or_more_group,
exact_one_group,
negated_file_group,
negated_wildcard,
negated_group,
non_special_character,
)),
@ -149,6 +158,7 @@ pub fn parse_glob(input: &str) -> anyhow::Result<(bool, Vec<Vec<GlobGroup>>)> {
#[cfg(test)]
mod test {
use crate::native::glob::glob_group::GlobGroup;
use crate::native::glob::glob_parser::parse_glob;
@ -272,5 +282,18 @@ mod test {
]
)
);
let result = parse_glob("packages/!(package-a)*/package.json").unwrap();
assert_eq!(
result,
(
false,
vec![
vec![GlobGroup::NonSpecial("packages".into())],
vec![GlobGroup::NegatedWildcard("package-a".into()),],
vec![GlobGroup::NonSpecial("package.json".into())]
]
)
);
}
}

View File

@ -88,6 +88,11 @@ fn build_segment(
let on_group = build_segment(&built_glob, &group[1..], is_last_segment, true);
off_group.into_iter().chain(on_group).collect::<Vec<_>>()
}
GlobGroup::NegatedWildcard(_) => {
let off_group = build_segment("*", &group[1..], is_last_segment, is_negative);
let on_group = build_segment(&built_glob, &group[1..], is_last_segment, true);
off_group.into_iter().chain(on_group).collect::<Vec<_>>()
}
GlobGroup::OneOrMore(_)
| GlobGroup::ExactOne(_)
| GlobGroup::NonSpecial(_)
@ -153,6 +158,15 @@ mod test {
assert_eq!(negative_single_dir, ["!packages/package-a*", "packages/*"]);
}
#[test]
fn convert_globs_single_negative_wildcard_directory() {
let negative_single_dir = convert_glob("packages/!(package-a)*/package.json").unwrap();
assert_eq!(
negative_single_dir,
["!packages/package-a*/", "packages/*/package.json"]
);
}
#[test]
fn test_transforming_globs() {
let globs = convert_glob("!(test|e2e)/?(*.)+(spec|test).[jt]s!(x)?(.snap)").unwrap();