use std::path::PathBuf;
use std::sync::mpsc;
use std::time::Duration;
use notify::RecommendedWatcher;
use notify::RecursiveMode;
use notify_debouncer_full::{DebounceEventResult, Debouncer, RecommendedCache, new_debouncer};
use crate::error::RuntimeError;
#[derive(Debug, Clone)]
pub enum FsEvent {
Added(PathBuf),
Modified(PathBuf),
Removed(PathBuf),
}
pub struct WatchHandle {
_debouncer: Debouncer<RecommendedWatcher, RecommendedCache>,
}
pub fn watch(paths: &[PathBuf]) -> Result<(mpsc::Receiver<FsEvent>, WatchHandle), RuntimeError> {
let (tx, rx) = mpsc::channel();
let mut debouncer = new_debouncer(
Duration::from_millis(500),
None,
move |res: DebounceEventResult| {
if let Ok(events) = res {
for ev in events {
for p in &ev.event.paths {
let out = match ev.event.kind {
notify::EventKind::Create(_) => FsEvent::Added(p.clone()),
notify::EventKind::Modify(_) => FsEvent::Modified(p.clone()),
notify::EventKind::Remove(_) => FsEvent::Removed(p.clone()),
_ => continue,
};
let _ = tx.send(out);
}
}
}
},
)
.map_err(|e| RuntimeError::Watcher(e.to_string()))?;
for p in paths {
if p.exists() {
debouncer
.watch(p, RecursiveMode::Recursive)
.map_err(|e| RuntimeError::Watcher(e.to_string()))?;
}
}
Ok((
rx,
WatchHandle {
_debouncer: debouncer,
},
))
}