2016-09-21 23:02:20 +02:00
|
|
|
extern crate glob;
|
|
|
|
|
2016-10-12 04:43:53 +02:00
|
|
|
use gitignore;
|
2016-09-27 15:43:28 +02:00
|
|
|
use std::io;
|
2016-10-24 02:12:48 +02:00
|
|
|
use std::path::{Path, PathBuf};
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-10-24 02:12:48 +02:00
|
|
|
use self::glob::{Pattern, PatternError};
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-09-23 21:52:50 +02:00
|
|
|
pub struct NotificationFilter {
|
2016-09-21 23:02:20 +02:00
|
|
|
filters: Vec<Pattern>,
|
2016-10-12 04:43:53 +02:00
|
|
|
ignores: Vec<Pattern>,
|
2016-10-24 02:12:48 +02:00
|
|
|
ignore_file: Option<gitignore::PatternSet>,
|
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 {
|
2016-09-27 15:43:28 +02:00
|
|
|
BadPattern(PatternError),
|
2016-10-24 02:12:48 +02:00
|
|
|
Io(io::Error),
|
2016-09-27 15:43:28 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 21:52:50 +02:00
|
|
|
impl NotificationFilter {
|
2016-10-24 02:12:48 +02:00
|
|
|
pub fn new(current_dir: &Path,
|
2016-10-27 14:27:16 +02:00
|
|
|
filters: Vec<String>,
|
|
|
|
ignores: Vec<String>,
|
2016-10-24 02:12:48 +02:00
|
|
|
ignore_file: Option<gitignore::PatternSet>)
|
2016-10-27 14:27:16 +02:00
|
|
|
-> Result<NotificationFilter, Error> {
|
|
|
|
let cwd = try!(current_dir.canonicalize());
|
2016-09-27 15:43:28 +02:00
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
let compiled_filters = try!(filters.iter()
|
|
|
|
.map(|p| NotificationFilter::pattern_for(&cwd, p))
|
|
|
|
.collect());
|
2016-10-14 01:47:04 +02:00
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
for compiled_filter in &compiled_filters {
|
|
|
|
debug!("Adding filter: {}", compiled_filter);
|
|
|
|
}
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
let compiled_ignores = try!(ignores.iter()
|
|
|
|
.map(|p| NotificationFilter::pattern_for(&cwd, p))
|
|
|
|
.collect());
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
for compiled_ignore in &compiled_ignores {
|
|
|
|
debug!("Adding ignore: {}", compiled_ignore);
|
|
|
|
}
|
2016-10-14 01:47:04 +02:00
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
Ok(NotificationFilter {
|
|
|
|
filters: compiled_filters,
|
|
|
|
ignores: compiled_ignores,
|
|
|
|
ignore_file: ignore_file,
|
|
|
|
})
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
fn pattern_for(cwd: &PathBuf, p: &str) -> Result<Pattern, PatternError> {
|
2016-09-21 23:02:20 +02:00
|
|
|
let mut path = PathBuf::from(p);
|
|
|
|
if path.is_relative() {
|
2016-10-27 14:27:16 +02:00
|
|
|
path = cwd.join(path.as_path());
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Ok(metadata) = path.metadata() {
|
|
|
|
if metadata.is_dir() {
|
|
|
|
path = path.join("*");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Pattern::new(path.to_str().unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_excluded(&self, path: &Path) -> bool {
|
|
|
|
let path_as_str = path.to_str().unwrap();
|
|
|
|
|
|
|
|
for pattern in &self.ignores {
|
|
|
|
if pattern.matches(path_as_str) {
|
2016-10-14 02:21:29 +02:00
|
|
|
debug!("Ignoring {:?}: matched ignore filter", path);
|
2016-09-21 23:02:20 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for pattern in &self.filters {
|
|
|
|
if pattern.matches(path_as_str) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-12 04:43:53 +02:00
|
|
|
if let Some(ref ignore_file) = self.ignore_file {
|
|
|
|
if ignore_file.is_excluded(path) {
|
2016-10-14 02:21:29 +02:00
|
|
|
debug!("Ignoring {:?}: matched gitignore file", path);
|
2016-10-12 04:43:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 15:39:40 +02:00
|
|
|
if !self.filters.is_empty() {
|
2016-10-14 02:21:29 +02:00
|
|
|
debug!("Ignoring {:?}: did not match any given filters", path);
|
|
|
|
}
|
|
|
|
|
2016-10-18 15:39:40 +02:00
|
|
|
!self.filters.is_empty()
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-27 14:27:16 +02:00
|
|
|
impl From<PatternError> for Error {
|
|
|
|
fn from(err: PatternError) -> Error {
|
|
|
|
Error::BadPattern(err)
|
2016-10-14 01:47:04 +02:00
|
|
|
}
|
|
|
|
}
|