watchexec/src/notification_filter.rs

133 lines
3.6 KiB
Rust
Raw Normal View History

2016-09-21 23:02:20 +02:00
extern crate glob;
2016-09-27 15:43:28 +02:00
use std::io;
use std::path::Path;
2016-09-21 23:02:20 +02:00
use globset;
use globset::{Glob, GlobSet, GlobSetBuilder};
use gitignore;
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,
ignore_files: gitignore::Gitignore,
2016-09-21 23:02:20 +02:00
}
2016-09-27 15:43:28 +02:00
#[derive(Debug)]
2016-10-27 14:27:16 +02:00
pub enum Error {
Glob(globset::Error),
Io(io::Error),
2016-09-27 15:43:28 +02:00
}
2016-09-23 21:52:50 +02:00
impl NotificationFilter {
pub fn new(filters: Vec<String>,
2016-10-27 14:27:16 +02:00
ignores: Vec<String>,
ignore_files: gitignore::Gitignore)
2016-10-27 14:27:16 +02:00
-> Result<NotificationFilter, Error> {
let mut filter_set_builder = GlobSetBuilder::new();
for f in &filters {
filter_set_builder.add(try!(Glob::new(f)));
2016-10-28 14:46:35 +02:00
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 {
ignore_set_builder.add(try!(Glob::new(i)));
debug!("Adding ignore: \"{}\"", i);
2016-10-27 14:27:16 +02:00
}
2016-10-14 01:47:04 +02:00
let filter_set = try!(filter_set_builder.build());
let ignore_set = try!(ignore_set_builder.build());
2016-10-27 14:27:16 +02:00
Ok(NotificationFilter {
2017-03-23 23:39:38 +01:00
filters: filter_set,
filter_count: filters.len(),
ignores: ignore_set,
ignore_files: ignore_files,
})
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 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-27 14:27:16 +02:00
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::Io(err)
2016-10-14 01:47:04 +02:00
}
}
impl From<globset::Error> for Error {
fn from(err: globset::Error) -> Error {
Error::Glob(err)
2016-10-14 01:47:04 +02:00
}
}
2016-10-29 15:37:50 +02:00
#[cfg(test)]
mod tests {
use gitignore;
2016-10-29 15:37:50 +02:00
use super::NotificationFilter;
use std::path::Path;
#[test]
fn test_allows_everything_by_default() {
2017-02-04 22:18:02 +01:00
let filter = NotificationFilter::new(vec![], vec![], gitignore::load(&vec![])).unwrap();
2016-10-29 15:37:50 +02:00
assert!(!filter.is_excluded(&Path::new("foo")));
}
#[test]
fn test_multiple_filters() {
let filters = vec![String::from("*.rs"), String::from("*.toml")];
2017-02-04 22:18:02 +01:00
let filter = NotificationFilter::new(filters, vec![], gitignore::load(&vec![])).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 = vec![String::from("*.rs"), String::from("*.toml")];
2017-02-04 22:18:02 +01:00
let filter = NotificationFilter::new(vec![], ignores, gitignore::load(&vec![])).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 = vec![String::from("*.rs"), String::from("*.toml")];
2017-02-04 22:18:02 +01:00
let filter = NotificationFilter::new(ignores.clone(), ignores, gitignore::load(&vec![]))
.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
}
}