mirror of
https://github.com/watchexec/watchexec.git
synced 2024-11-13 07:41:11 +01:00
Redo and sketch new filter adding process
This commit is contained in:
parent
cd7d5f1fcb
commit
f16ba2dff1
3 changed files with 88 additions and 28 deletions
|
@ -29,23 +29,26 @@ async fn main() -> Result<()> {
|
|||
.ok();
|
||||
}
|
||||
|
||||
let (init, runtime, filterer) = config::new(&args)?;
|
||||
let mut filters = Vec::new();
|
||||
|
||||
// TODO: move into config?
|
||||
for filter in args.values_of("filter").unwrap_or_default() {
|
||||
filterer.add_filter(filter.parse()?).await?;
|
||||
filters.push(filter.parse()?);
|
||||
}
|
||||
|
||||
for ext in args.values_of("extensions").unwrap_or_default().map(|s| s.split(',').map(|s| s.trim())).flatten() {
|
||||
filterer.add_filter(Filter {
|
||||
filters.push(Filter {
|
||||
in_path: None,
|
||||
on: Matcher::Path,
|
||||
op: Op::Glob,
|
||||
pat: TaggedFilterer::glob(&format!("**/*.{}", ext))?,
|
||||
negate: false,
|
||||
}).await?;
|
||||
});
|
||||
}
|
||||
|
||||
let (init, runtime, filterer) = config::new(&args)?;
|
||||
filterer.add_filters(&filters).await?;
|
||||
|
||||
let wx = Watchexec::new(init, runtime)?;
|
||||
|
||||
if !args.is_present("postpone") {
|
||||
|
|
|
@ -20,3 +20,10 @@ impl<T: Filterer> Filterer for Arc<T> {
|
|||
Arc::as_ref(self).check_event(event)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience function to check a glob pattern from a string.
|
||||
///
|
||||
/// This parses the glob and wraps any error with nice [miette] diagnostics.
|
||||
pub fn check_glob(s: &str) -> Result<&str, ()> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::PathBuf;
|
|||
use std::sync::Arc;
|
||||
|
||||
use dunce::canonicalize;
|
||||
use tokio::fs::read_to_string;
|
||||
use tracing::{debug, trace, warn};
|
||||
use unicase::UniCase;
|
||||
|
||||
|
@ -162,32 +163,74 @@ impl TaggedFilterer {
|
|||
.map(Some)
|
||||
}
|
||||
|
||||
pub async fn add_filter(&self, mut filter: Filter) -> Result<(), error::TaggedFiltererError> {
|
||||
debug!(?filter, "adding filter to filterer");
|
||||
pub async fn add_filters(&self, filters: &[Filter]) -> Result<(), error::TaggedFiltererError> {
|
||||
debug!(?filters, "adding filters to filterer");
|
||||
|
||||
if let Some(ctx) = &mut filter.in_path {
|
||||
*ctx = canonicalize(&ctx)?;
|
||||
trace!(canon=?ctx, "canonicalised in_path");
|
||||
}
|
||||
let mut recompile_globs = false;
|
||||
let mut recompile_not_globs = false;
|
||||
|
||||
let filters = filters
|
||||
.iter()
|
||||
.cloned()
|
||||
.inspect(|f| match f.op {
|
||||
Op::Glob => {
|
||||
recompile_globs = true;
|
||||
}
|
||||
Op::NotGlob => {
|
||||
recompile_not_globs = true;
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.map(Filter::canonicalised)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
// TODO: use miette's related and issue canonicalisation errors for all of them
|
||||
|
||||
self.filters
|
||||
.change(|filters| {
|
||||
filters.entry(filter.on).or_default().push(filter);
|
||||
.change(|fs| {
|
||||
for filter in filters {
|
||||
fs.entry(filter.on).or_default().push(filter);
|
||||
}
|
||||
})
|
||||
.await
|
||||
.map_err(|err| error::TaggedFiltererError::FilterChange { action: "add", err })?;
|
||||
|
||||
if recompile_globs {
|
||||
self.recompile_globs(Op::Glob).await?;
|
||||
}
|
||||
|
||||
if recompile_not_globs {
|
||||
self.recompile_globs(Op::NotGlob).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_glob_ignore(&self, glob: &str) -> Result<(), error::TaggedFiltererError> {
|
||||
async fn recompile_globs(&self, op_filter: Op) -> Result<(), error::TaggedFiltererError> {
|
||||
todo!()
|
||||
|
||||
// globs:
|
||||
// - use ignore's impl
|
||||
// - after adding some filters, recompile by making a gitignorebuilder and storing the gitignore
|
||||
// - use two gitignores: one for NotGlob (which is used for gitignores) and one for Glob (invert results from its matches)
|
||||
}
|
||||
|
||||
pub async fn add_ignore_file(
|
||||
&self,
|
||||
file: &IgnoreFile,
|
||||
) -> Result<(), error::TaggedFiltererError> {
|
||||
todo!()
|
||||
let content = read_to_string(&file.path).await?;
|
||||
let lines = content.lines();
|
||||
let mut ignores = Vec::with_capacity(lines.size_hint().0);
|
||||
|
||||
for line in lines {
|
||||
if line.is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
ignores.push(Filter::from_glob_ignore(file.applies_in.clone(), line));
|
||||
}
|
||||
|
||||
self.add_filters(&ignores).await
|
||||
}
|
||||
|
||||
pub async fn clear_filters(&self) -> Result<(), error::TaggedFiltererError> {
|
||||
|
@ -201,14 +244,6 @@ impl TaggedFilterer {
|
|||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convenience function to check a glob pattern from a string.
|
||||
///
|
||||
/// This parses the glob and wraps any error with nice [miette] diagnostics.
|
||||
pub fn glob(s: &str) -> Result<Pattern, error::TaggedFiltererError> {
|
||||
Glob::new(s).map_err(error::TaggedFiltererError::GlobParse)?;
|
||||
Ok(Pattern::Glob(s.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -257,6 +292,27 @@ impl Filter {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_glob_ignore(in_path: Option<PathBuf>, glob: &str) -> Self {
|
||||
let (glob, negate) = glob.strip_prefix('!').map_or((glob, false), |g| (g, true));
|
||||
|
||||
Self {
|
||||
in_path,
|
||||
on: Matcher::Path,
|
||||
op: Op::NotGlob,
|
||||
pat: Pattern::Glob(glob.to_string()),
|
||||
negate,
|
||||
}
|
||||
}
|
||||
|
||||
fn canonicalised(mut self) -> Result<Self, error::TaggedFiltererError> {
|
||||
if let Some(ctx) = self.in_path {
|
||||
self.in_path = Some(canonicalize(&ctx)?);
|
||||
trace!(canon=?ctx, "canonicalised in_path");
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
|
@ -298,12 +354,6 @@ pub enum Op {
|
|||
NotInSet, // :!
|
||||
}
|
||||
|
||||
// globs:
|
||||
// - use ignore's impl
|
||||
// - on adding a filter, compile the gitignorebuilder and store the gitignore
|
||||
// - use two gitignores: one for NotGlob (which is used for gitignores) and one for Glob (invert results from its matches)
|
||||
// - store the globs as strings
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum Pattern {
|
||||
|
|
Loading…
Reference in a new issue