watchexec/src/notification_filter.rs

117 lines
2.9 KiB
Rust
Raw Normal View History

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-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>,
2016-10-12 04:43:53 +02:00
ignores: Vec<Pattern>,
2016-10-12 15:06:01 +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)]
pub enum NotificationError {
BadPattern(PatternError),
Io(io::Error)
}
2016-09-23 21:52:50 +02:00
impl NotificationFilter {
2016-10-12 15:06:01 +02:00
pub fn new(current_dir: &Path, ignore_file: Option<gitignore::PatternSet>) -> Result<NotificationFilter, io::Error> {
2016-09-27 15:43:28 +02:00
let canonicalized = try!(current_dir.canonicalize());
Ok(NotificationFilter {
cwd: canonicalized,
2016-09-21 23:02:20 +02:00
filters: vec![],
2016-10-12 04:43:53 +02:00
ignores: vec![],
ignore_file: ignore_file
2016-09-27 15:43:28 +02:00
})
2016-09-21 23:02:20 +02:00
}
2016-10-14 01:47:04 +02:00
pub fn add_extension(&mut self, extensions: &str) -> Result<(), NotificationError> {
let patterns: Vec<String> = extensions
.split(",")
.filter(|ext| !ext.is_empty())
.map(|ext| format!("*.{}", ext.replace(".", "")))
.collect();
2016-10-14 01:47:04 +02:00
for pattern in patterns {
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-10-14 01:47:04 +02:00
debug!("Adding filter: {}", pattern);
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-10-14 01:47:04 +02:00
debug!("Adding ignore: {}", pattern);
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;
}
}
2016-10-12 04:43:53 +02:00
if let Some(ref ignore_file) = self.ignore_file {
if ignore_file.is_excluded(path) {
return true;
}
}
2016-09-21 23:02:20 +02:00
self.filters.len() > 0
}
}
2016-10-14 01:47:04 +02:00
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)
}
}