2016-09-21 23:02:20 +02:00
|
|
|
extern crate glob;
|
|
|
|
|
2018-09-08 13:51:44 +02:00
|
|
|
use error;
|
|
|
|
use gitignore::Gitignore;
|
2016-11-03 22:04:39 +01:00
|
|
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
2018-09-08 13:51:44 +02:00
|
|
|
use std::path::Path;
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-09-23 21:52:50 +02:00
|
|
|
pub struct NotificationFilter {
|
2016-11-03 22:04:39 +01:00
|
|
|
filters: GlobSet,
|
|
|
|
filter_count: usize,
|
|
|
|
ignores: GlobSet,
|
2018-09-08 13:51:44 +02:00
|
|
|
ignore_files: Gitignore,
|
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(
|
2019-01-26 02:45:08 +01:00
|
|
|
filters: &[String],
|
|
|
|
ignores: &[String],
|
2018-09-08 13:51:44 +02:00
|
|
|
ignore_files: Gitignore,
|
|
|
|
) -> error::Result<NotificationFilter> {
|
2016-11-03 22:04:39 +01:00
|
|
|
let mut filter_set_builder = GlobSetBuilder::new();
|
2019-01-26 02:45:08 +01:00
|
|
|
for f in filters {
|
2018-09-08 13:51:44 +02:00
|
|
|
filter_set_builder.add(Glob::new(f)?);
|
2016-11-03 22:04:39 +01:00
|
|
|
debug!("Adding filter: \"{}\"", f);
|
2016-10-27 14:27:16 +02:00
|
|
|
}
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-11-03 22:04:39 +01:00
|
|
|
let mut ignore_set_builder = GlobSetBuilder::new();
|
2019-01-26 02:45:08 +01:00
|
|
|
for i in ignores {
|
2017-10-07 21:50:47 +02:00
|
|
|
let mut ignore_path = Path::new(i).to_path_buf();
|
|
|
|
if ignore_path.is_relative() && !i.starts_with("*") {
|
|
|
|
ignore_path = Path::new("**").join(&ignore_path);
|
|
|
|
}
|
|
|
|
let pattern = ignore_path.to_str().unwrap();
|
2018-09-08 13:51:44 +02:00
|
|
|
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 {
|
2018-09-08 13:51:44 +02:00
|
|
|
filters: filter_set_builder.build()?,
|
2018-09-08 10:08:36 +02:00
|
|
|
filter_count: filters.len(),
|
2018-09-08 13:51:44 +02:00
|
|
|
ignores: ignore_set_builder.build()?,
|
2018-09-08 10:08:36 +02:00
|
|
|
ignore_files: ignore_files,
|
|
|
|
})
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_excluded(&self, path: &Path) -> bool {
|
2016-11-03 22:04:39 +01:00
|
|
|
if self.ignores.is_match(path) {
|
|
|
|
debug!("Ignoring {:?}: matched ignore filter", path);
|
|
|
|
return true;
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
2016-11-03 22:04:39 +01:00
|
|
|
if self.filters.is_match(path) {
|
|
|
|
return false;
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
2017-02-04 20:52:38 +01:00
|
|
|
if self.ignore_files.is_excluded(path) {
|
|
|
|
debug!("Ignoring {:?}: matched gitignore file", path);
|
|
|
|
return true;
|
2016-10-12 04:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-11-03 22:04:39 +01:00
|
|
|
if self.filter_count > 0 {
|
2016-10-14 02:21:29 +02:00
|
|
|
debug!("Ignoring {:?}: did not match any given filters", path);
|
|
|
|
}
|
|
|
|
|
2016-11-03 22:04:39 +01:00
|
|
|
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;
|
2016-10-29 15:37:50 +02:00
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_allows_everything_by_default() {
|
2019-01-26 02:45:08 +01:00
|
|
|
let filter = NotificationFilter::new(&[], &[], gitignore::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() {
|
2018-09-08 10:08:36 +02:00
|
|
|
let filter = NotificationFilter::new(
|
2019-01-26 02:45:08 +01:00
|
|
|
&[],
|
|
|
|
&["test.json".into()],
|
|
|
|
gitignore::load(&[]),
|
2018-09-08 10:08:36 +02:00
|
|
|
).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() {
|
2019-01-26 02:45:08 +01:00
|
|
|
let filters = &["*.rs".into(), "*.toml".into()];
|
|
|
|
let filter = NotificationFilter::new(filters, &[], gitignore::load(&[])).unwrap();
|
2016-10-29 15:37:50 +02:00
|
|
|
|
2016-10-29 16:24:31 +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() {
|
2019-01-26 02:45:08 +01:00
|
|
|
let ignores = &["*.rs".into(), "*.toml".into()];
|
|
|
|
let filter = NotificationFilter::new(&[], ignores, gitignore::load(&vec![])).unwrap();
|
2016-10-29 15:37:50 +02:00
|
|
|
|
2016-10-29 16:24:31 +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() {
|
2019-01-26 02:45:08 +01:00
|
|
|
let ignores = &["*.rs".into(), "*.toml".into()];
|
2018-09-08 10:08:36 +02:00
|
|
|
let filter =
|
2019-01-26 02:45:08 +01:00
|
|
|
NotificationFilter::new(ignores, ignores, gitignore::load(&[])).unwrap();
|
2016-10-29 15:37:50 +02:00
|
|
|
|
2016-10-29 16:24:31 +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
|
|
|
}
|
|
|
|
}
|