Test scoped path glob filtering

This commit is contained in:
Félix Saparelli 2021-12-02 21:33:48 +13:00
parent ce3f2a3cbd
commit 0826d531af
No known key found for this signature in database
GPG Key ID: B948C4BAE44FC474
2 changed files with 88 additions and 8 deletions

View File

@ -138,8 +138,10 @@ impl TaggedFilterer {
if let Some(igs) = gc.as_ref() {
trace!("checking against compiled Glob filters");
match if path.strip_prefix(&self.origin).is_ok() {
trace!("checking against path or parents");
igs.matched_path_or_any_parents(path, is_dir)
} else {
trace!("checking against path only");
igs.matched(path, is_dir)
} {
Match::None => {
@ -147,8 +149,12 @@ impl TaggedFilterer {
tag_match = false;
}
Match::Ignore(glob) => {
trace!(?glob, "positive match (pass)");
tag_match = true;
if glob.from().map_or(true, |f| path.strip_prefix(f).is_ok()) {
trace!(?glob, "positive match (pass)");
tag_match = true;
} else {
trace!(?glob, "positive match, but not in scope (ignore)");
}
}
Match::Whitelist(glob) => {
trace!(?glob, "negative match (ignore)");
@ -160,8 +166,10 @@ impl TaggedFilterer {
if let Some(ngs) = ngc.as_ref() {
trace!("checking against compiled NotGlob filters");
match if path.strip_prefix(&self.origin).is_ok() {
trace!("checking against path or parents");
ngs.matched_path_or_any_parents(path, is_dir)
} else {
trace!("checking against path only");
ngs.matched(path, is_dir)
} {
Match::None => {
@ -169,8 +177,12 @@ impl TaggedFilterer {
tag_match = true;
}
Match::Ignore(glob) => {
trace!(?glob, "positive match (fail)");
tag_match = false;
if glob.from().map_or(true, |f| path.strip_prefix(f).is_ok()) {
trace!(?glob, "positive match (fail)");
tag_match = false;
} else {
trace!(?glob, "positive match, but not in scope (ignore)");
}
}
Match::Whitelist(glob) => {
trace!(?glob, "negative match (pass)");

View File

@ -1,4 +1,7 @@
use std::{path::PathBuf, sync::Arc};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use watchexec::{
error::RuntimeError,
@ -20,6 +23,8 @@ trait Harness {
let origin = dunce::canonicalize(".").unwrap();
let full_path = if let Some(suf) = path.strip_prefix("/test/") {
origin.join(suf)
} else if Path::new(path).has_root() {
path.into()
} else {
origin.join(path)
};
@ -111,13 +116,20 @@ fn not_filter(pat: &str) -> Filter {
}
trait FilterExt {
fn in_path(self) -> Self;
fn in_path(self) -> Self
where
Self: Sized,
{
self.in_subpath("")
}
fn in_subpath(self, sub: impl AsRef<Path>) -> Self;
}
impl FilterExt for Filter {
fn in_path(mut self) -> Self {
fn in_subpath(mut self, sub: impl AsRef<Path>) -> Self {
let origin = dunce::canonicalize(".").unwrap();
self.in_path = Some(origin);
self.in_path = Some(origin.join(sub));
self
}
}
@ -438,6 +450,62 @@ async fn ignores_take_precedence() {
filterer.file_does_pass("FINAL-FINAL.docx");
}
#[tokio::test]
async fn scopes_global() {
let filterer = filt(&[not_filter("*.toml")]).await;
filterer.file_doesnt_pass("Cargo.toml");
filterer.dir_doesnt_pass("Cargo.toml");
filterer.file_doesnt_pass("/outside/Cargo.toml");
filterer.dir_doesnt_pass("/outside/Cargo.toml");
filterer.file_does_pass("/outside/package.json");
filterer.dir_does_pass("/outside/package.json");
filterer.file_does_pass("package.json");
filterer.file_does_pass("FINAL-FINAL.docx");
}
#[tokio::test]
async fn scopes_local() {
let filterer = filt(&[not_filter("*.toml").in_path()]).await;
filterer.file_doesnt_pass("/test/Cargo.toml");
filterer.dir_doesnt_pass("/test/Cargo.toml");
filterer.file_does_pass("/outside/Cargo.toml");
filterer.dir_does_pass("/outside/Cargo.toml");
filterer.file_does_pass("/outside/package.json");
filterer.dir_does_pass("/outside/package.json");
filterer.file_does_pass("package.json");
filterer.file_does_pass("FINAL-FINAL.docx");
}
#[tokio::test]
async fn scopes_sublocal() {
let filterer = filt(&[not_filter("*.toml").in_subpath("src")]).await;
filterer.file_doesnt_pass("/test/src/Cargo.toml");
filterer.dir_doesnt_pass("/test/src/Cargo.toml");
filterer.file_does_pass("/test/Cargo.toml");
filterer.dir_does_pass("/test/Cargo.toml");
filterer.file_does_pass("/test/tests/Cargo.toml");
filterer.dir_does_pass("/test/tests/Cargo.toml");
filterer.file_does_pass("/outside/Cargo.toml");
filterer.dir_does_pass("/outside/Cargo.toml");
filterer.file_does_pass("/outside/package.json");
filterer.dir_does_pass("/outside/package.json");
filterer.file_does_pass("package.json");
filterer.file_does_pass("FINAL-FINAL.docx");
}
// The following tests check that the "buggy"/"confusing" watchexec v1 behaviour
// is no longer present.