mirror of
https://github.com/watchexec/watchexec.git
synced 2024-09-28 22:21:33 +02:00
Integrate IgnoreFilterer into GlobsetFilterer
This commit is contained in:
parent
d6dfb87063
commit
b8d9ad728e
@ -6,7 +6,6 @@ use std::{
|
|||||||
|
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use tracing::debug;
|
|
||||||
use watchexec::{
|
use watchexec::{
|
||||||
error::RuntimeError,
|
error::RuntimeError,
|
||||||
event::{
|
event::{
|
||||||
@ -18,7 +17,7 @@ use watchexec::{
|
|||||||
|
|
||||||
pub async fn globset(args: &ArgMatches<'static>) -> Result<Arc<WatchexecFilterer>> {
|
pub async fn globset(args: &ArgMatches<'static>) -> Result<Arc<WatchexecFilterer>> {
|
||||||
let (project_origin, workdir) = super::common::dirs(args).await?;
|
let (project_origin, workdir) = super::common::dirs(args).await?;
|
||||||
let ignorefiles = super::common::ignores(args, &project_origin).await?;
|
let ignore_files = super::common::ignores(args, &project_origin).await?;
|
||||||
|
|
||||||
let mut ignores = Vec::new();
|
let mut ignores = Vec::new();
|
||||||
|
|
||||||
@ -37,10 +36,6 @@ pub async fn globset(args: &ArgMatches<'static>) -> Result<Arc<WatchexecFilterer
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ignore in ignorefiles {
|
|
||||||
ignores.extend(GlobsetFilterer::list_from_ignore_file(&ignore).await?);
|
|
||||||
}
|
|
||||||
|
|
||||||
let filters = args
|
let filters = args
|
||||||
.values_of("filter")
|
.values_of("filter")
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
@ -58,9 +53,8 @@ pub async fn globset(args: &ArgMatches<'static>) -> Result<Arc<WatchexecFilterer
|
|||||||
.map(|s| s.split(b','))
|
.map(|s| s.split(b','))
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
debug!(filters=%filters.len(), ignores=%ignores.len(), "vecs lengths");
|
|
||||||
Ok(Arc::new(WatchexecFilterer {
|
Ok(Arc::new(WatchexecFilterer {
|
||||||
inner: GlobsetFilterer::new(project_origin, filters, ignores, exts).into_diagnostic()?,
|
inner: GlobsetFilterer::new(project_origin, filters, ignores, ignore_files, exts).await.into_diagnostic()?,
|
||||||
no_meta: args.is_present("no-meta"),
|
no_meta: args.is_present("no-meta"),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -219,12 +219,12 @@ pub enum RuntimeError {
|
|||||||
#[diagnostic(code(watchexec::runtime::clearscreen))]
|
#[diagnostic(code(watchexec::runtime::clearscreen))]
|
||||||
Clearscreen(#[from] clearscreen::Error),
|
Clearscreen(#[from] clearscreen::Error),
|
||||||
|
|
||||||
/// Error received when parsing a glob from an [`IgnoreFile`](crate::ignore::files::IgnoreFile) fails.
|
/// Error received when parsing a glob (possibly from an [`IgnoreFile`](crate::ignore::files::IgnoreFile)) fails.
|
||||||
#[error("cannot parse glob from ignore '{file}': {err}")]
|
#[error("cannot parse glob from ignore '{file:?}': {err}")]
|
||||||
#[diagnostic(code(watchexec::runtime::ignore_file_glob))]
|
#[diagnostic(code(watchexec::runtime::ignore_glob))]
|
||||||
IgnoreFileGlob {
|
GlobsetGlob {
|
||||||
/// The path to the erroring ignore file.
|
/// The path to the erroring ignore file.
|
||||||
file: PathBuf,
|
file: Option<PathBuf>,
|
||||||
|
|
||||||
/// The underlying error.
|
/// The underlying error.
|
||||||
#[source]
|
#[source]
|
||||||
|
@ -10,18 +10,19 @@ use tracing::{debug, trace, trace_span};
|
|||||||
use crate::error::RuntimeError;
|
use crate::error::RuntimeError;
|
||||||
use crate::event::{Event, FileType};
|
use crate::event::{Event, FileType};
|
||||||
use crate::filter::Filterer;
|
use crate::filter::Filterer;
|
||||||
use crate::ignore::IgnoreFile;
|
use crate::ignore::{IgnoreFile, IgnoreFilterer};
|
||||||
|
|
||||||
/// A path-only filterer based on globsets.
|
/// A path-only filterer based on globsets.
|
||||||
///
|
///
|
||||||
/// This filterer mimics the behavior of the `watchexec` v1 filter, but does not match it exactly,
|
/// This filterer mimics the behavior of the `watchexec` v1 filter, but does not match it exactly,
|
||||||
/// due to differing internals. It is intended to be used as a stopgap until the tagged filter
|
/// due to differing internals. It is intended to be used as a stopgap until the tagged filterer
|
||||||
/// reaches a stable state or becomes the default. As such it does not have an updatable
|
/// or another advanced filterer, reaches a stable state or becomes the default. As such it does not
|
||||||
/// configuration.
|
/// have an updatable configuration.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GlobsetFilterer {
|
pub struct GlobsetFilterer {
|
||||||
filters: Gitignore,
|
filters: Gitignore,
|
||||||
ignores: Gitignore,
|
ignores: Gitignore,
|
||||||
|
ignore_files: IgnoreFilterer,
|
||||||
extensions: Vec<OsString>,
|
extensions: Vec<OsString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,32 +36,45 @@ impl GlobsetFilterer {
|
|||||||
/// The extensions list is used to filter files by extension.
|
/// The extensions list is used to filter files by extension.
|
||||||
///
|
///
|
||||||
/// Non-path events are always passed.
|
/// Non-path events are always passed.
|
||||||
pub fn new(
|
pub async fn new(
|
||||||
origin: impl AsRef<Path>,
|
origin: impl AsRef<Path>,
|
||||||
filters: impl IntoIterator<Item = (String, Option<PathBuf>)>,
|
filters: impl IntoIterator<Item = (String, Option<PathBuf>)>,
|
||||||
ignores: impl IntoIterator<Item = (String, Option<PathBuf>)>,
|
ignores: impl IntoIterator<Item = (String, Option<PathBuf>)>,
|
||||||
|
ignore_files: impl IntoIterator<Item = IgnoreFile>,
|
||||||
extensions: impl IntoIterator<Item = OsString>,
|
extensions: impl IntoIterator<Item = OsString>,
|
||||||
) -> Result<Self, ignore::Error> {
|
) -> Result<Self, RuntimeError> {
|
||||||
let mut filters_builder = GitignoreBuilder::new(origin);
|
let origin = origin.as_ref();
|
||||||
let mut ignores_builder = filters_builder.clone();
|
let mut filters_builder = GitignoreBuilder::new(&origin);
|
||||||
|
let mut ignores_builder = GitignoreBuilder::new(&origin);
|
||||||
|
|
||||||
for (filter, in_path) in filters {
|
for (filter, in_path) in filters {
|
||||||
trace!(filter=?&filter, "add filter to globset filterer");
|
trace!(filter=?&filter, "add filter to globset filterer");
|
||||||
filters_builder.add_line(in_path, &filter)?;
|
filters_builder.add_line(in_path.clone(), &filter)
|
||||||
|
.map_err(|err| RuntimeError::GlobsetGlob { file: in_path, err })
|
||||||
|
?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ignore, in_path) in ignores {
|
for (ignore, in_path) in ignores {
|
||||||
trace!(ignore=?&ignore, "add ignore to globset filterer");
|
trace!(ignore=?&ignore, "add ignore to globset filterer");
|
||||||
ignores_builder.add_line(in_path, &ignore)?;
|
ignores_builder.add_line(in_path.clone(), &ignore)
|
||||||
|
.map_err(|err| RuntimeError::GlobsetGlob { file: in_path, err })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let filters = filters_builder.build()?;
|
let filters = filters_builder.build()
|
||||||
let ignores = ignores_builder.build()?;
|
.map_err(|err| RuntimeError::GlobsetGlob { file: None, err })?;
|
||||||
|
let ignores = ignores_builder.build()
|
||||||
|
.map_err(|err| RuntimeError::GlobsetGlob { file: None, err })?;
|
||||||
|
|
||||||
let extensions: Vec<OsString> = extensions.into_iter().collect();
|
let extensions: Vec<OsString> = extensions.into_iter().collect();
|
||||||
|
|
||||||
|
let mut ignore_files = IgnoreFilterer::new(origin, &ignore_files.into_iter().collect::<Vec<_>>()).await?;
|
||||||
|
ignore_files.finish();
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
num_filters=%filters.num_ignores(),
|
num_filters=%filters.num_ignores(),
|
||||||
num_neg_filters=%filters.num_whitelists(),
|
num_neg_filters=%filters.num_whitelists(),
|
||||||
num_ignores=%ignores.num_ignores(),
|
num_ignores=%ignores.num_ignores(),
|
||||||
|
num_in_ignore_files=?ignore_files.num_ignores(),
|
||||||
num_neg_ignores=%ignores.num_whitelists(),
|
num_neg_ignores=%ignores.num_whitelists(),
|
||||||
num_extensions=%extensions.len(),
|
num_extensions=%extensions.len(),
|
||||||
"globset filterer built");
|
"globset filterer built");
|
||||||
@ -68,6 +82,7 @@ impl GlobsetFilterer {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
filters,
|
filters,
|
||||||
ignores,
|
ignores,
|
||||||
|
ignore_files,
|
||||||
extensions,
|
extensions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -97,9 +112,16 @@ impl Filterer for GlobsetFilterer {
|
|||||||
///
|
///
|
||||||
/// This implementation never errors.
|
/// This implementation never errors.
|
||||||
fn check_event(&self, event: &Event) -> Result<bool, RuntimeError> {
|
fn check_event(&self, event: &Event) -> Result<bool, RuntimeError> {
|
||||||
// TODO: integrate ignore::Filter
|
|
||||||
|
|
||||||
let _span = trace_span!("filterer_check").entered();
|
let _span = trace_span!("filterer_check").entered();
|
||||||
|
|
||||||
|
{
|
||||||
|
trace!("checking internal ignore filterer");
|
||||||
|
if !self.ignore_files.check_event(event).expect("IgnoreFilterer never errors") {
|
||||||
|
trace!("internal ignore filterer matched (fail)");
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (path, file_type) in event.paths() {
|
for (path, file_type) in event.paths() {
|
||||||
let _span = trace_span!("path", ?path).entered();
|
let _span = trace_span!("path", ?path).entered();
|
||||||
let is_dir = file_type
|
let is_dir = file_type
|
||||||
|
@ -95,8 +95,8 @@ impl IgnoreFilterer {
|
|||||||
trace!(?line, "adding ignore line");
|
trace!(?line, "adding ignore line");
|
||||||
builder
|
builder
|
||||||
.add_line(file.applies_in.clone(), line)
|
.add_line(file.applies_in.clone(), line)
|
||||||
.map_err(|err| RuntimeError::IgnoreFileGlob {
|
.map_err(|err| RuntimeError::GlobsetGlob {
|
||||||
file: file.path.clone(),
|
file: Some(file.path.clone()),
|
||||||
err,
|
err,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ impl IgnoreFilterer {
|
|||||||
trace!("compiling globset");
|
trace!("compiling globset");
|
||||||
let compiled = builder
|
let compiled = builder
|
||||||
.build()
|
.build()
|
||||||
.map_err(|err| RuntimeError::IgnoreFileGlob {
|
.map_err(|err| RuntimeError::GlobsetGlob {
|
||||||
file: "set of ignores".into(),
|
file: None,
|
||||||
err,
|
err,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -124,6 +124,11 @@ impl IgnoreFilterer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of ignores and allowlists loaded.
|
||||||
|
pub fn num_ignores(&self) -> (u64, u64) {
|
||||||
|
(self.compiled.num_ignores(), self.compiled.num_whitelists())
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes the internal builder, to save memory.
|
/// Deletes the internal builder, to save memory.
|
||||||
///
|
///
|
||||||
/// This makes it impossible to add new ignore files without re-compiling the whole set.
|
/// This makes it impossible to add new ignore files without re-compiling the whole set.
|
||||||
@ -154,8 +159,8 @@ impl IgnoreFilterer {
|
|||||||
trace!(?line, "adding ignore line");
|
trace!(?line, "adding ignore line");
|
||||||
builder
|
builder
|
||||||
.add_line(file.applies_in.clone(), line)
|
.add_line(file.applies_in.clone(), line)
|
||||||
.map_err(|err| RuntimeError::IgnoreFileGlob {
|
.map_err(|err| RuntimeError::GlobsetGlob {
|
||||||
file: file.path.clone(),
|
file: Some(file.path.clone()),
|
||||||
err,
|
err,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -174,7 +179,7 @@ impl IgnoreFilterer {
|
|||||||
trace!("recompiling globset");
|
trace!("recompiling globset");
|
||||||
let recompiled = builder
|
let recompiled = builder
|
||||||
.build()
|
.build()
|
||||||
.map_err(|err| RuntimeError::IgnoreFileGlob { file, err })?;
|
.map_err(|err| RuntimeError::GlobsetGlob { file: Some(file), err })?;
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
new_ignores=%(recompiled.num_ignores() - pre_ignores),
|
new_ignores=%(recompiled.num_ignores() - pre_ignores),
|
||||||
@ -204,8 +209,8 @@ impl IgnoreFilterer {
|
|||||||
|
|
||||||
trace!(?line, "adding ignore line");
|
trace!(?line, "adding ignore line");
|
||||||
builder.add_line(applies_in.clone(), line).map_err(|err| {
|
builder.add_line(applies_in.clone(), line).map_err(|err| {
|
||||||
RuntimeError::IgnoreFileGlob {
|
RuntimeError::GlobsetGlob {
|
||||||
file: "manual glob".into(),
|
file: None,
|
||||||
err,
|
err,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
use helpers::globset::*;
|
use helpers::globset::*;
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn empty_filter_passes_everything() {
|
async fn empty_filter_passes_everything() {
|
||||||
let filterer = filt(&[], &[], &[]);
|
let filterer = filt(&[], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("Cargo.json");
|
filterer.file_does_pass("Cargo.json");
|
||||||
@ -21,9 +21,9 @@ fn empty_filter_passes_everything() {
|
|||||||
filterer.dir_does_pass("apples/oranges/bananas");
|
filterer.dir_does_pass("apples/oranges/bananas");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn exact_filename() {
|
async fn exact_filename() {
|
||||||
let filterer = filt(&["Cargo.toml"], &[], &[]);
|
let filterer = filt(&["Cargo.toml"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("/test/foo/bar/Cargo.toml");
|
filterer.file_does_pass("/test/foo/bar/Cargo.toml");
|
||||||
@ -34,9 +34,9 @@ fn exact_filename() {
|
|||||||
filterer.dir_does_pass("/test/Cargo.toml");
|
filterer.dir_does_pass("/test/Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn exact_filenames_multiple() {
|
async fn exact_filenames_multiple() {
|
||||||
let filterer = filt(&["Cargo.toml", "package.json"], &[], &[]);
|
let filterer = filt(&["Cargo.toml", "package.json"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("/test/foo/bar/Cargo.toml");
|
filterer.file_does_pass("/test/foo/bar/Cargo.toml");
|
||||||
@ -51,9 +51,9 @@ fn exact_filenames_multiple() {
|
|||||||
filterer.dir_does_pass("/test/package.json");
|
filterer.dir_does_pass("/test/package.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_single_final_ext_star() {
|
async fn glob_single_final_ext_star() {
|
||||||
let filterer = filt(&["Cargo.*"], &[], &[]);
|
let filterer = filt(&["Cargo.*"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("Cargo.json");
|
filterer.file_does_pass("Cargo.json");
|
||||||
@ -63,9 +63,9 @@ fn glob_single_final_ext_star() {
|
|||||||
filterer.dir_does_pass("Cargo.toml");
|
filterer.dir_does_pass("Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_star_trailing_slash() {
|
async fn glob_star_trailing_slash() {
|
||||||
let filterer = filt(&["Cargo.*/"], &[], &[]);
|
let filterer = filt(&["Cargo.*/"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("Cargo.json");
|
filterer.file_doesnt_pass("Cargo.json");
|
||||||
@ -76,9 +76,9 @@ fn glob_star_trailing_slash() {
|
|||||||
filterer.unk_doesnt_pass("Cargo.toml");
|
filterer.unk_doesnt_pass("Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_star_leading_slash() {
|
async fn glob_star_leading_slash() {
|
||||||
let filterer = filt(&["/Cargo.*"], &[], &[]);
|
let filterer = filt(&["/Cargo.*"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("Cargo.json");
|
filterer.file_does_pass("Cargo.json");
|
||||||
@ -88,9 +88,9 @@ fn glob_star_leading_slash() {
|
|||||||
filterer.dir_doesnt_pass("foo/Cargo.toml");
|
filterer.dir_doesnt_pass("foo/Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_leading_double_star() {
|
async fn glob_leading_double_star() {
|
||||||
let filterer = filt(&["**/possum"], &[], &[]);
|
let filterer = filt(&["**/possum"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("possum");
|
filterer.file_does_pass("possum");
|
||||||
filterer.file_does_pass("foo/bar/possum");
|
filterer.file_does_pass("foo/bar/possum");
|
||||||
@ -103,9 +103,9 @@ fn glob_leading_double_star() {
|
|||||||
filterer.file_doesnt_pass("/foo/bar/rat");
|
filterer.file_doesnt_pass("/foo/bar/rat");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_trailing_double_star() {
|
async fn glob_trailing_double_star() {
|
||||||
let filterer = filt(&["possum/**"], &[], &[]);
|
let filterer = filt(&["possum/**"], &[], &[]).await;
|
||||||
|
|
||||||
// these do work by expectation and in v1
|
// these do work by expectation and in v1
|
||||||
filterer.file_does_pass("/test/possum/foo/bar");
|
filterer.file_does_pass("/test/possum/foo/bar");
|
||||||
@ -117,9 +117,9 @@ fn glob_trailing_double_star() {
|
|||||||
filterer.file_doesnt_pass("/foo/bar/rat");
|
filterer.file_doesnt_pass("/foo/bar/rat");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_middle_double_star() {
|
async fn glob_middle_double_star() {
|
||||||
let filterer = filt(&["apples/**/oranges"], &[], &[]);
|
let filterer = filt(&["apples/**/oranges"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.dir_doesnt_pass("/a/folder");
|
filterer.dir_doesnt_pass("/a/folder");
|
||||||
filterer.file_does_pass("apples/carrots/oranges");
|
filterer.file_does_pass("apples/carrots/oranges");
|
||||||
@ -132,9 +132,9 @@ fn glob_middle_double_star() {
|
|||||||
filterer.dir_doesnt_pass("apples/oranges/bananas");
|
filterer.dir_doesnt_pass("apples/oranges/bananas");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn glob_double_star_trailing_slash() {
|
async fn glob_double_star_trailing_slash() {
|
||||||
let filterer = filt(&["apples/**/oranges/"], &[], &[]);
|
let filterer = filt(&["apples/**/oranges/"], &[], &[]).await;
|
||||||
|
|
||||||
filterer.dir_doesnt_pass("/a/folder");
|
filterer.dir_doesnt_pass("/a/folder");
|
||||||
filterer.file_doesnt_pass("apples/carrots/oranges");
|
filterer.file_doesnt_pass("apples/carrots/oranges");
|
||||||
@ -150,9 +150,9 @@ fn glob_double_star_trailing_slash() {
|
|||||||
filterer.unk_doesnt_pass("apples/carrots/cauliflowers/artichokes/oranges");
|
filterer.unk_doesnt_pass("apples/carrots/cauliflowers/artichokes/oranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_exact_filename() {
|
async fn ignore_exact_filename() {
|
||||||
let filterer = filt(&[], &["Cargo.toml"], &[]);
|
let filterer = filt(&[], &["Cargo.toml"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
||||||
@ -163,9 +163,9 @@ fn ignore_exact_filename() {
|
|||||||
filterer.dir_doesnt_pass("/test/Cargo.toml");
|
filterer.dir_doesnt_pass("/test/Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_exact_filenames_multiple() {
|
async fn ignore_exact_filenames_multiple() {
|
||||||
let filterer = filt(&[], &["Cargo.toml", "package.json"], &[]);
|
let filterer = filt(&[], &["Cargo.toml", "package.json"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
||||||
@ -180,9 +180,9 @@ fn ignore_exact_filenames_multiple() {
|
|||||||
filterer.dir_doesnt_pass("/test/package.json");
|
filterer.dir_doesnt_pass("/test/package.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_single_final_ext_star() {
|
async fn ignore_glob_single_final_ext_star() {
|
||||||
let filterer = filt(&[], &["Cargo.*"], &[]);
|
let filterer = filt(&[], &["Cargo.*"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("Cargo.json");
|
filterer.file_doesnt_pass("Cargo.json");
|
||||||
@ -192,9 +192,9 @@ fn ignore_glob_single_final_ext_star() {
|
|||||||
filterer.dir_doesnt_pass("Cargo.toml");
|
filterer.dir_doesnt_pass("Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_star_trailing_slash() {
|
async fn ignore_glob_star_trailing_slash() {
|
||||||
let filterer = filt(&[], &["Cargo.*/"], &[]);
|
let filterer = filt(&[], &["Cargo.*/"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("Cargo.toml");
|
filterer.file_does_pass("Cargo.toml");
|
||||||
filterer.file_does_pass("Cargo.json");
|
filterer.file_does_pass("Cargo.json");
|
||||||
@ -205,9 +205,9 @@ fn ignore_glob_star_trailing_slash() {
|
|||||||
filterer.unk_does_pass("Cargo.toml");
|
filterer.unk_does_pass("Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_star_leading_slash() {
|
async fn ignore_glob_star_leading_slash() {
|
||||||
let filterer = filt(&[], &["/Cargo.*"], &[]);
|
let filterer = filt(&[], &["/Cargo.*"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("Cargo.json");
|
filterer.file_doesnt_pass("Cargo.json");
|
||||||
@ -217,9 +217,9 @@ fn ignore_glob_star_leading_slash() {
|
|||||||
filterer.dir_does_pass("foo/Cargo.toml");
|
filterer.dir_does_pass("foo/Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_leading_double_star() {
|
async fn ignore_glob_leading_double_star() {
|
||||||
let filterer = filt(&[], &["**/possum"], &[]);
|
let filterer = filt(&[], &["**/possum"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("possum");
|
filterer.file_doesnt_pass("possum");
|
||||||
filterer.file_doesnt_pass("foo/bar/possum");
|
filterer.file_doesnt_pass("foo/bar/possum");
|
||||||
@ -232,9 +232,9 @@ fn ignore_glob_leading_double_star() {
|
|||||||
filterer.file_does_pass("/foo/bar/rat");
|
filterer.file_does_pass("/foo/bar/rat");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_trailing_double_star() {
|
async fn ignore_glob_trailing_double_star() {
|
||||||
let filterer = filt(&[], &["possum/**"], &[]);
|
let filterer = filt(&[], &["possum/**"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("possum");
|
filterer.file_does_pass("possum");
|
||||||
filterer.file_doesnt_pass("possum/foo/bar");
|
filterer.file_doesnt_pass("possum/foo/bar");
|
||||||
@ -251,9 +251,9 @@ fn ignore_glob_trailing_double_star() {
|
|||||||
filterer.file_does_pass("/foo/bar/rat");
|
filterer.file_does_pass("/foo/bar/rat");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_middle_double_star() {
|
async fn ignore_glob_middle_double_star() {
|
||||||
let filterer = filt(&[], &["apples/**/oranges"], &[]);
|
let filterer = filt(&[], &["apples/**/oranges"], &[]).await;
|
||||||
|
|
||||||
filterer.dir_does_pass("/a/folder");
|
filterer.dir_does_pass("/a/folder");
|
||||||
filterer.file_doesnt_pass("apples/carrots/oranges");
|
filterer.file_doesnt_pass("apples/carrots/oranges");
|
||||||
@ -266,9 +266,9 @@ fn ignore_glob_middle_double_star() {
|
|||||||
filterer.dir_does_pass("apples/oranges/bananas");
|
filterer.dir_does_pass("apples/oranges/bananas");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_glob_double_star_trailing_slash() {
|
async fn ignore_glob_double_star_trailing_slash() {
|
||||||
let filterer = filt(&[], &["apples/**/oranges/"], &[]);
|
let filterer = filt(&[], &["apples/**/oranges/"], &[]).await;
|
||||||
|
|
||||||
filterer.dir_does_pass("/a/folder");
|
filterer.dir_does_pass("/a/folder");
|
||||||
filterer.file_does_pass("apples/carrots/oranges");
|
filterer.file_does_pass("apples/carrots/oranges");
|
||||||
@ -284,9 +284,9 @@ fn ignore_glob_double_star_trailing_slash() {
|
|||||||
filterer.unk_does_pass("apples/carrots/cauliflowers/artichokes/oranges");
|
filterer.unk_does_pass("apples/carrots/cauliflowers/artichokes/oranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignores_take_precedence() {
|
async fn ignores_take_precedence() {
|
||||||
let filterer = filt(&["*.docx", "*.toml", "*.json"], &["*.toml", "*.json"], &[]);
|
let filterer = filt(&["*.docx", "*.toml", "*.json"], &["*.toml", "*.json"], &[]).await;
|
||||||
|
|
||||||
filterer.file_doesnt_pass("Cargo.toml");
|
filterer.file_doesnt_pass("Cargo.toml");
|
||||||
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
filterer.file_doesnt_pass("/test/foo/bar/Cargo.toml");
|
||||||
@ -299,9 +299,9 @@ fn ignores_take_precedence() {
|
|||||||
|
|
||||||
// The following tests replicate the "buggy"/"confusing" watchexec v1 behaviour.
|
// The following tests replicate the "buggy"/"confusing" watchexec v1 behaviour.
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_folder_incorrectly_with_bare_match() {
|
async fn ignore_folder_incorrectly_with_bare_match() {
|
||||||
let filterer = filt(&[], &["prunes"], &[]);
|
let filterer = filt(&[], &["prunes"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("apples");
|
filterer.file_does_pass("apples");
|
||||||
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
||||||
@ -330,9 +330,9 @@ fn ignore_folder_incorrectly_with_bare_match() {
|
|||||||
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_folder_incorrectly_with_bare_and_leading_slash() {
|
async fn ignore_folder_incorrectly_with_bare_and_leading_slash() {
|
||||||
let filterer = filt(&[], &["/prunes"], &[]);
|
let filterer = filt(&[], &["/prunes"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("apples");
|
filterer.file_does_pass("apples");
|
||||||
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
||||||
@ -361,9 +361,9 @@ fn ignore_folder_incorrectly_with_bare_and_leading_slash() {
|
|||||||
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_folder_incorrectly_with_bare_and_trailing_slash() {
|
async fn ignore_folder_incorrectly_with_bare_and_trailing_slash() {
|
||||||
let filterer = filt(&[], &["prunes/"], &[]);
|
let filterer = filt(&[], &["prunes/"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("apples");
|
filterer.file_does_pass("apples");
|
||||||
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
||||||
@ -392,9 +392,9 @@ fn ignore_folder_incorrectly_with_bare_and_trailing_slash() {
|
|||||||
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
filterer.dir_does_pass("prunes/carrots/cauliflowers/artichokes/oranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_folder_incorrectly_with_only_double_double_glob() {
|
async fn ignore_folder_incorrectly_with_only_double_double_glob() {
|
||||||
let filterer = filt(&[], &["**/prunes/**"], &[]);
|
let filterer = filt(&[], &["**/prunes/**"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("apples");
|
filterer.file_does_pass("apples");
|
||||||
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
||||||
@ -423,9 +423,9 @@ fn ignore_folder_incorrectly_with_only_double_double_glob() {
|
|||||||
filterer.dir_does_pass("prunes");
|
filterer.dir_does_pass("prunes");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn ignore_folder_correctly_with_double_and_double_double_globs() {
|
async fn ignore_folder_correctly_with_double_and_double_double_globs() {
|
||||||
let filterer = filt(&[], &["**/prunes", "**/prunes/**"], &[]);
|
let filterer = filt(&[], &["**/prunes", "**/prunes/**"], &[]).await;
|
||||||
|
|
||||||
filterer.file_does_pass("apples");
|
filterer.file_does_pass("apples");
|
||||||
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
filterer.file_does_pass("apples/carrots/cauliflowers/oranges");
|
||||||
|
@ -213,32 +213,24 @@ fn tracing_init() {
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn globset_filt(filters: &[&str], ignores: &[&str], extensions: &[&str]) -> GlobsetFilterer {
|
pub async fn globset_filt(filters: &[&str], ignores: &[&str], extensions: &[&str]) -> GlobsetFilterer {
|
||||||
let origin = dunce::canonicalize(".").unwrap();
|
let origin = dunce::canonicalize(".").unwrap();
|
||||||
tracing_init();
|
tracing_init();
|
||||||
GlobsetFilterer::new(
|
GlobsetFilterer::new(
|
||||||
origin,
|
origin,
|
||||||
filters.iter().map(|s| (s.to_string(), None)),
|
filters.iter().map(|s| (s.to_string(), None)),
|
||||||
ignores.iter().map(|s| (s.to_string(), None)),
|
ignores.iter().map(|s| (s.to_string(), None)),
|
||||||
|
vec![],
|
||||||
extensions.iter().map(OsString::from),
|
extensions.iter().map(OsString::from),
|
||||||
)
|
)
|
||||||
|
.await
|
||||||
.expect("making filterer")
|
.expect("making filterer")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn globset_igfilt(origin: &str, ignore_files: &[IgnoreFile]) -> GlobsetFilterer {
|
pub async fn globset_igfilt(origin: &str, ignore_files: &[IgnoreFile]) -> GlobsetFilterer {
|
||||||
tracing_init();
|
tracing_init();
|
||||||
let mut ignores = Vec::new();
|
|
||||||
for file in ignore_files {
|
|
||||||
tracing::info!(?file, "loading ignore file");
|
|
||||||
ignores.extend(
|
|
||||||
GlobsetFilterer::list_from_ignore_file(file)
|
|
||||||
.await
|
|
||||||
.expect("adding ignorefile"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let origin = dunce::canonicalize(".").unwrap().join(origin);
|
let origin = dunce::canonicalize(".").unwrap().join(origin);
|
||||||
GlobsetFilterer::new(origin, vec![], ignores, vec![]).expect("making filterer")
|
GlobsetFilterer::new(origin, vec![], vec![], ignore_files.iter().cloned(), vec![]).await.expect("making filterer")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn ignore_filt(origin: &str, ignore_files: &[IgnoreFile]) -> IgnoreFilterer {
|
pub async fn ignore_filt(origin: &str, ignore_files: &[IgnoreFile]) -> IgnoreFilterer {
|
||||||
|
Loading…
Reference in New Issue
Block a user