watchexec/src/notification_filter.rs

139 lines
4.1 KiB
Rust
Raw Normal View History

2019-10-27 11:58:00 +01:00
use crate::error;
use crate::gitignore::Gitignore;
use globset::{Glob, GlobSet, GlobSetBuilder};
2019-10-27 11:58:00 +01:00
use crate::ignore::Ignore;
use std::path::Path;
2016-09-21 23:02:20 +02:00
2016-09-23 21:52:50 +02:00
pub struct NotificationFilter {
filters: GlobSet,
filter_count: usize,
ignores: GlobSet,
gitignore_files: Gitignore,
ignore_files: Ignore,
2016-09-27 15:43:28 +02:00
}
2016-09-23 21:52:50 +02:00
impl NotificationFilter {
2018-09-08 10:08:36 +02:00
pub fn new(
filters: &[String],
ignores: &[String],
gitignore_files: Gitignore,
ignore_files: Ignore,
) -> error::Result<NotificationFilter> {
let mut filter_set_builder = GlobSetBuilder::new();
for f in filters {
filter_set_builder.add(Glob::new(f)?);
debug!("Adding filter: \"{}\"", f);
2016-10-27 14:27:16 +02:00
}
2016-09-21 23:02:20 +02:00
let mut ignore_set_builder = GlobSetBuilder::new();
for i in ignores {
2017-10-07 21:50:47 +02:00
let mut ignore_path = Path::new(i).to_path_buf();
2019-10-27 11:47:35 +01:00
if ignore_path.is_relative() && !i.starts_with('*') {
2017-10-07 21:50:47 +02:00
ignore_path = Path::new("**").join(&ignore_path);
}
let pattern = ignore_path.to_str().unwrap();
ignore_set_builder.add(Glob::new(pattern)?);
2017-10-07 21:50:47 +02:00
debug!("Adding ignore: \"{}\"", pattern);
2016-10-27 14:27:16 +02:00
}
2016-10-14 01:47:04 +02:00
2016-10-27 14:27:16 +02:00
Ok(NotificationFilter {
filters: filter_set_builder.build()?,
2018-09-08 10:08:36 +02:00
filter_count: filters.len(),
ignores: ignore_set_builder.build()?,
2019-10-27 11:47:35 +01:00
gitignore_files,
ignore_files,
2018-09-08 10:08:36 +02:00
})
2016-09-21 23:02:20 +02:00
}
pub fn is_excluded(&self, path: &Path) -> bool {
if self.ignores.is_match(path) {
debug!("Ignoring {:?}: matched ignore filter", path);
return true;
2016-09-21 23:02:20 +02:00
}
if self.filters.is_match(path) {
return false;
2016-09-21 23:02:20 +02:00
}
if self.ignore_files.is_excluded(path) {
debug!("Ignoring {:?}: matched ignore file", path);
return true;
}
if self.gitignore_files.is_excluded(path) {
debug!("Ignoring {:?}: matched gitignore file", path);
return true;
2016-10-12 04:43:53 +02:00
}
if self.filter_count > 0 {
debug!("Ignoring {:?}: did not match any given filters", path);
}
self.filter_count > 0
2016-09-21 23:02:20 +02:00
}
}
2016-10-14 01:47:04 +02:00
2016-10-29 15:37:50 +02:00
#[cfg(test)]
mod tests {
use super::NotificationFilter;
2018-09-08 10:08:36 +02:00
use gitignore;
use ignore;
2016-10-29 15:37:50 +02:00
use std::path::Path;
#[test]
fn test_allows_everything_by_default() {
let filter =
NotificationFilter::new(&[], &[], gitignore::load(&[]), ignore::load(&[])).unwrap();
2016-10-29 15:37:50 +02:00
assert!(!filter.is_excluded(&Path::new("foo")));
}
2017-10-07 21:50:47 +02:00
#[test]
fn test_filename() {
let filter = NotificationFilter::new(
&[],
&["test.json".into()],
gitignore::load(&[]),
ignore::load(&[]),
)
.unwrap();
2017-10-07 21:50:47 +02:00
assert!(filter.is_excluded(&Path::new("/path/to/test.json")));
assert!(filter.is_excluded(&Path::new("test.json")));
}
2016-10-29 15:37:50 +02:00
#[test]
fn test_multiple_filters() {
let filters = &["*.rs".into(), "*.toml".into()];
let filter =
NotificationFilter::new(filters, &[], gitignore::load(&[]), ignore::load(&[])).unwrap();
2016-10-29 15:37:50 +02:00
assert!(!filter.is_excluded(&Path::new("hello.rs")));
assert!(!filter.is_excluded(&Path::new("Cargo.toml")));
assert!(filter.is_excluded(&Path::new("README.md")));
2016-10-29 15:37:50 +02:00
}
#[test]
fn test_multiple_ignores() {
let ignores = &["*.rs".into(), "*.toml".into()];
let filter =
NotificationFilter::new(&[], ignores, gitignore::load(&[]), ignore::load(&[])).unwrap();
2016-10-29 15:37:50 +02:00
assert!(filter.is_excluded(&Path::new("hello.rs")));
assert!(filter.is_excluded(&Path::new("Cargo.toml")));
assert!(!filter.is_excluded(&Path::new("README.md")));
2016-10-29 15:37:50 +02:00
}
#[test]
fn test_ignores_take_precedence() {
let ignores = &["*.rs".into(), "*.toml".into()];
let filter =
NotificationFilter::new(ignores, ignores, gitignore::load(&[]), ignore::load(&[]))
.unwrap();
2016-10-29 15:37:50 +02:00
assert!(filter.is_excluded(&Path::new("hello.rs")));
assert!(filter.is_excluded(&Path::new("Cargo.toml")));
assert!(filter.is_excluded(&Path::new("README.md")));
2016-10-29 15:37:50 +02:00
}
}