2016-09-21 23:02:20 +02:00
|
|
|
extern crate glob;
|
|
|
|
|
2016-09-27 15:43:28 +02:00
|
|
|
use std::io;
|
2016-09-21 23:02:20 +02:00
|
|
|
use std::path::{Path,PathBuf};
|
|
|
|
|
|
|
|
use self::glob::{Pattern,PatternError};
|
|
|
|
|
2016-09-23 21:52:50 +02:00
|
|
|
pub struct NotificationFilter {
|
2016-09-21 23:02:20 +02:00
|
|
|
cwd: PathBuf,
|
|
|
|
filters: Vec<Pattern>,
|
|
|
|
ignores: Vec<Pattern>
|
|
|
|
}
|
|
|
|
|
2016-09-27 15:43:28 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum NotificationError {
|
|
|
|
BadPattern(PatternError),
|
|
|
|
Io(io::Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<io::Error> for NotificationError {
|
|
|
|
fn from(err: io::Error) -> NotificationError {
|
|
|
|
NotificationError::Io(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PatternError> for NotificationError {
|
|
|
|
fn from(err: PatternError) -> NotificationError {
|
|
|
|
NotificationError::BadPattern(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-23 21:52:50 +02:00
|
|
|
impl NotificationFilter {
|
2016-09-27 15:43:28 +02:00
|
|
|
pub fn new(current_dir: &Path) -> Result<NotificationFilter, io::Error> {
|
|
|
|
let canonicalized = try!(current_dir.canonicalize());
|
|
|
|
|
|
|
|
Ok(NotificationFilter {
|
|
|
|
cwd: canonicalized,
|
2016-09-21 23:02:20 +02:00
|
|
|
filters: vec![],
|
|
|
|
ignores: vec![]
|
2016-09-27 15:43:28 +02:00
|
|
|
})
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:43:28 +02:00
|
|
|
pub fn add_extension(&mut self, extension: &str) -> Result<(), NotificationError> {
|
2016-09-23 19:59:57 +02:00
|
|
|
let mut pattern = String::new();
|
|
|
|
|
|
|
|
for ext in extension.split(",") {
|
|
|
|
pattern.clear();
|
|
|
|
pattern.push_str("*");
|
|
|
|
|
|
|
|
if !ext.starts_with(".") {
|
|
|
|
pattern.push_str(".");
|
|
|
|
}
|
|
|
|
pattern.push_str(ext);
|
|
|
|
|
|
|
|
try!(self.add_filter(&pattern));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-09-27 15:43:28 +02:00
|
|
|
pub fn add_filter(&mut self, pattern: &str) -> Result<(), NotificationError> {
|
2016-09-21 23:02:20 +02:00
|
|
|
let compiled = try!(self.pattern_for(pattern));
|
2016-09-23 22:04:19 +02:00
|
|
|
self.filters.push(compiled);
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-09-23 22:00:26 +02:00
|
|
|
Ok(())
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:43:28 +02:00
|
|
|
pub fn add_ignore(&mut self, pattern: &str) -> Result<(), NotificationError> {
|
2016-09-21 23:02:20 +02:00
|
|
|
let compiled = try!(self.pattern_for(pattern));
|
2016-09-23 22:04:19 +02:00
|
|
|
self.ignores.push(compiled);
|
2016-09-21 23:02:20 +02:00
|
|
|
|
2016-09-23 22:00:26 +02:00
|
|
|
Ok(())
|
2016-09-21 23:02:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pattern_for(&self, p: &str) -> Result<Pattern, PatternError> {
|
|
|
|
let mut path = PathBuf::from(p);
|
|
|
|
if path.is_relative() {
|
|
|
|
path = self.cwd.join(path.as_path());
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for pattern in &self.filters {
|
|
|
|
if pattern.matches(path_as_str) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.filters.len() > 0
|
|
|
|
}
|
|
|
|
}
|