diff --git a/notify/src/fsevent.rs b/notify/src/fsevent.rs index 01a87b6f..29135c74 100644 --- a/notify/src/fsevent.rs +++ b/notify/src/fsevent.rs @@ -16,7 +16,8 @@ use crate::event::*; use crate::{ - unbounded, Config, Error, EventHandler, PathsMut, RecursiveMode, Result, Sender, Watcher, + unbounded, Config, Error, EventHandler, PathsMut, RecursiveMode, Result, Sender, WatchFilter, + Watcher, }; use fsevent_sys as fs; use fsevent_sys::core_foundation as cf; @@ -68,7 +69,7 @@ pub struct FsEventWatcher { flags: fs::FSEventStreamCreateFlags, event_handler: Arc>, runloop: Option<(cf::CFRunLoopRef, thread::JoinHandle<()>)>, - recursive_info: HashMap, + recursive_info: HashMap, } impl fmt::Debug for FsEventWatcher { @@ -244,7 +245,7 @@ fn translate_flags(flags: StreamFlags, precise: bool) -> Vec { struct StreamContextInfo { event_handler: Arc>, - recursive_info: HashMap, + recursive_info: HashMap, } // Free the context when the stream created by `FSEventStreamCreate` is released. @@ -305,9 +306,14 @@ impl FsEventWatcher { }) } - fn watch_inner(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn watch_inner( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { self.stop(); - let result = self.append_path(path, recursive_mode); + let result = self.append_path(path, recursive_mode, watch_filter); // ignore return error: may be empty path list let _ = self.run(); result @@ -385,7 +391,12 @@ impl FsEventWatcher { } // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c - fn append_path(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn append_path( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { if !path.exists() { return Err(Error::path_not_found().add_path(path.into())); } @@ -403,8 +414,10 @@ impl FsEventWatcher { cf::CFArrayAppendValue(self.paths, cf_path); cf::CFRelease(cf_path); } - self.recursive_info - .insert(canonical_path, recursive_mode.is_recursive()); + self.recursive_info.insert( + canonical_path, + (recursive_mode.is_recursive(), watch_filter), + ); Ok(()) } @@ -547,8 +560,8 @@ unsafe fn callback_impl( }); let mut handle_event = false; - for (p, r) in &(*info).recursive_info { - if path.starts_with(p) { + for (p, (r, filt)) in &(*info).recursive_info { + if path.starts_with(p) && filt.should_watch(p) { if *r || &path == p { handle_event = true; break; @@ -582,8 +595,13 @@ impl Watcher for FsEventWatcher { Self::from_event_handler(Arc::new(Mutex::new(event_handler))) } - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.watch_inner(path, recursive_mode) + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { + self.watch_inner(path, recursive_mode, watch_filter) } fn paths_mut<'me>(&'me mut self) -> Box { diff --git a/notify/src/inotify.rs b/notify/src/inotify.rs index fd27a39a..3ce041a0 100644 --- a/notify/src/inotify.rs +++ b/notify/src/inotify.rs @@ -5,7 +5,7 @@ //! will return events for the directory itself, and for files inside the directory. use super::event::*; -use super::{Config, Error, ErrorKind, EventHandler, RecursiveMode, Result, Watcher}; +use super::{Config, Error, ErrorKind, EventHandler, RecursiveMode, Result, WatchFilter, Watcher}; use crate::{bounded, unbounded, BoundSender, Receiver, Sender}; use inotify as inotify_sys; use inotify_sys::{EventMask, Inotify, WatchDescriptor, WatchMask}; @@ -37,7 +37,7 @@ struct EventLoop { inotify: Option, event_handler: Box, /// PathBuf -> (WatchDescriptor, WatchMask, is_recursive, is_dir) - watches: HashMap, + watches: HashMap, paths: HashMap, rename_event: Option, follow_links: bool, @@ -51,7 +51,7 @@ pub struct INotifyWatcher { } enum EventLoopMsg { - AddWatch(PathBuf, RecursiveMode, Sender>), + AddWatch(PathBuf, RecursiveMode, WatchFilter, Sender>), RemoveWatch(PathBuf, Sender>), Shutdown, Configure(Config, BoundSender>), @@ -61,14 +61,14 @@ enum EventLoopMsg { fn add_watch_by_event( path: &PathBuf, event: &inotify_sys::Event<&OsStr>, - watches: &HashMap, - add_watches: &mut Vec, + watches: &HashMap, + add_watches: &mut Vec<(PathBuf, WatchFilter)>, ) { if event.mask.contains(EventMask::ISDIR) { if let Some(parent_path) = path.parent() { - if let Some(&(_, _, is_recursive, _)) = watches.get(parent_path) { + if let Some(&(_, _, is_recursive, _, ref filter)) = watches.get(parent_path) { if is_recursive { - add_watches.push(path.to_owned()); + add_watches.push((path.to_owned(), filter.clone())); } } } @@ -78,7 +78,7 @@ fn add_watch_by_event( #[inline] fn remove_watch_by_event( path: &PathBuf, - watches: &HashMap, + watches: &HashMap, remove_watches: &mut Vec, ) { if watches.contains_key(path) { @@ -168,8 +168,13 @@ impl EventLoop { fn handle_messages(&mut self) { while let Ok(msg) = self.event_loop_rx.try_recv() { match msg { - EventLoopMsg::AddWatch(path, recursive_mode, tx) => { - let _ = tx.send(self.add_watch(path, recursive_mode.is_recursive(), true)); + EventLoopMsg::AddWatch(path, recursive_mode, watch_filter, tx) => { + let _ = tx.send(self.add_watch( + path, + recursive_mode.is_recursive(), + true, + watch_filter, + )); } EventLoopMsg::RemoveWatch(path, tx) => { let _ = tx.send(self.remove_watch(path, false)); @@ -304,8 +309,8 @@ impl EventLoop { } if event.mask.contains(EventMask::DELETE_SELF) { let remove_kind = match self.watches.get(&path) { - Some(&(_, _, _, true)) => RemoveKind::Folder, - Some(&(_, _, _, false)) => RemoveKind::File, + Some(&(_, _, _, true, _)) => RemoveKind::Folder, + Some(&(_, _, _, false, _)) => RemoveKind::File, None => RemoveKind::Other, }; evs.push( @@ -380,8 +385,8 @@ impl EventLoop { self.remove_watch(path, true).ok(); } - for path in add_watches { - if let Err(add_watch_error) = self.add_watch(path, true, false) { + for (path, filter) in add_watches { + if let Err(add_watch_error) = self.add_watch(path, true, false, filter) { // The handler should be notified if we have reached the limit. // Otherwise, the user might expect that a recursive watch // is continuing to work correctly, but it's not. @@ -397,19 +402,35 @@ impl EventLoop { } } - fn add_watch(&mut self, path: PathBuf, is_recursive: bool, mut watch_self: bool) -> Result<()> { + fn add_watch( + &mut self, + path: PathBuf, + is_recursive: bool, + mut watch_self: bool, + watch_filter: WatchFilter, + ) -> Result<()> { + if !watch_filter.should_watch(&path) { + return Ok(()); + } + // If the watch is not recursive, or if we determine (by stat'ing the path to get its // metadata) that the watched path is not a directory, add a single path watch. if !is_recursive || !metadata(&path).map_err(Error::io_watch)?.is_dir() { - return self.add_single_watch(path, false, true); + return self.add_single_watch(path, false, true, WatchFilter::accept_all()); } for entry in WalkDir::new(path) .follow_links(self.follow_links) .into_iter() .filter_map(filter_dir) + .filter(|e| watch_filter.should_watch(e.path())) { - self.add_single_watch(entry.into_path(), is_recursive, watch_self)?; + self.add_single_watch( + entry.into_path(), + is_recursive, + watch_self, + watch_filter.clone(), + )?; watch_self = false; } @@ -421,6 +442,7 @@ impl EventLoop { path: PathBuf, is_recursive: bool, watch_self: bool, + watch_filter: WatchFilter, ) -> Result<()> { let mut watchmask = WatchMask::ATTRIB | WatchMask::CREATE @@ -436,7 +458,7 @@ impl EventLoop { watchmask.insert(WatchMask::MOVE_SELF); } - if let Some(&(_, old_watchmask, _, _)) = self.watches.get(&path) { + if let Some(&(_, old_watchmask, _, _, _)) = self.watches.get(&path) { watchmask.insert(old_watchmask); watchmask.insert(WatchMask::MASK_ADD); } @@ -459,8 +481,16 @@ impl EventLoop { Ok(w) => { watchmask.remove(WatchMask::MASK_ADD); let is_dir = metadata(&path).map_err(Error::io)?.is_dir(); - self.watches - .insert(path.clone(), (w.clone(), watchmask, is_recursive, is_dir)); + self.watches.insert( + path.clone(), + ( + w.clone(), + watchmask, + is_recursive, + is_dir, + watch_filter.clone(), + ), + ); self.paths.insert(w, path); Ok(()) } @@ -473,7 +503,7 @@ impl EventLoop { fn remove_watch(&mut self, path: PathBuf, remove_recursive: bool) -> Result<()> { match self.watches.remove(&path) { None => return Err(Error::watch_not_found().add_path(path)), - Some((w, _, is_recursive, _)) => { + Some((w, _, is_recursive, _, _)) => { if let Some(ref mut inotify) = self.inotify { let mut inotify_watches = inotify.watches(); log::trace!("removing inotify watch: {}", path.display()); @@ -544,7 +574,12 @@ impl INotifyWatcher { Ok(INotifyWatcher { channel, waker }) } - fn watch_inner(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn watch_inner( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { let pb = if path.is_absolute() { path.to_owned() } else { @@ -552,7 +587,7 @@ impl INotifyWatcher { p.join(path) }; let (tx, rx) = unbounded(); - let msg = EventLoopMsg::AddWatch(pb, recursive_mode, tx); + let msg = EventLoopMsg::AddWatch(pb, recursive_mode, watch_filter, tx); // we expect the event loop to live and reply => unwraps must not panic self.channel.send(msg).unwrap(); @@ -583,8 +618,13 @@ impl Watcher for INotifyWatcher { Self::from_event_handler(Box::new(event_handler), config.follow_symlinks()) } - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.watch_inner(path, recursive_mode) + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { + self.watch_inner(path, recursive_mode, watch_filter) } fn unwatch(&mut self, path: &Path) -> Result<()> { diff --git a/notify/src/kqueue.rs b/notify/src/kqueue.rs index 0f814b7a..d29684ec 100644 --- a/notify/src/kqueue.rs +++ b/notify/src/kqueue.rs @@ -5,7 +5,7 @@ //! pieces of kernel code termed filters. use super::event::*; -use super::{Config, Error, EventHandler, RecursiveMode, Result, Watcher}; +use super::{Config, Error, EventHandler, RecursiveMode, Result, Watcher, WatchFilter}; use crate::{unbounded, Receiver, Sender}; use kqueue::{EventData, EventFilter, FilterFlag, Ident}; use std::collections::HashMap; @@ -45,7 +45,7 @@ pub struct KqueueWatcher { } enum EventLoopMsg { - AddWatch(PathBuf, RecursiveMode, Sender>), + AddWatch(PathBuf, RecursiveMode, WatchFilter, Sender>), RemoveWatch(PathBuf, Sender>), Shutdown, } @@ -130,8 +130,9 @@ impl EventLoop { fn handle_messages(&mut self) { while let Ok(msg) = self.event_loop_rx.try_recv() { match msg { - EventLoopMsg::AddWatch(path, recursive_mode, tx) => { - let _ = tx.send(self.add_watch(path, recursive_mode.is_recursive())); + EventLoopMsg::AddWatch(path, recursive_mode, watch_filter, tx) => { + let _ = + tx.send(self.add_watch(path, recursive_mode.is_recursive(), watch_filter)); } EventLoopMsg::RemoveWatch(path, tx) => { let _ = tx.send(self.remove_watch(path, false)); @@ -288,11 +289,20 @@ impl EventLoop { } for path in add_watches { - self.add_watch(path, true).ok(); + self.add_watch(path, true, WatchFilter::accept_all()).ok(); } } - fn add_watch(&mut self, path: PathBuf, is_recursive: bool) -> Result<()> { + fn add_watch( + &mut self, + path: PathBuf, + is_recursive: bool, + watch_filter: WatchFilter, + ) -> Result<()> { + if !watch_filter.should_watch(&path) { + return Ok(()); + } + // If the watch is not recursive, or if we determine (by stat'ing the path to get its // metadata) that the watched path is not a directory, add a single path watch. if !is_recursive || !metadata(&path).map_err(Error::io)?.is_dir() { @@ -387,7 +397,12 @@ impl KqueueWatcher { Ok(KqueueWatcher { channel, waker }) } - fn watch_inner(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn watch_inner( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { let pb = if path.is_absolute() { path.to_owned() } else { @@ -395,7 +410,7 @@ impl KqueueWatcher { p.join(path) }; let (tx, rx) = unbounded(); - let msg = EventLoopMsg::AddWatch(pb, recursive_mode, tx); + let msg = EventLoopMsg::AddWatch(pb, recursive_mode, watch_filter, tx); self.channel .send(msg) @@ -436,8 +451,17 @@ impl Watcher for KqueueWatcher { Self::from_event_handler(Box::new(event_handler), config.follow_symlinks()) } + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { + self.watch_inner(path, recursive_mode, watch_filter) + } + fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.watch_inner(path, recursive_mode) + self.watch_inner(path, recursive_mode, WatchFilter::accept_all()) } fn unwatch(&mut self, path: &Path) -> Result<()> { diff --git a/notify/src/lib.rs b/notify/src/lib.rs index 0eb73c7b..890fa023 100644 --- a/notify/src/lib.rs +++ b/notify/src/lib.rs @@ -165,7 +165,7 @@ pub use config::{Config, RecursiveMode}; pub use error::{Error, ErrorKind, Result}; pub use notify_types::event::{self, Event, EventKind}; -use std::path::Path; +use std::{path::Path, sync::Arc}; pub(crate) type Receiver = std::sync::mpsc::Receiver; pub(crate) type Sender = std::sync::mpsc::Sender; @@ -293,6 +293,37 @@ pub enum WatcherKind { NullWatcher, } +type FilterFn = dyn Fn(&Path) -> bool + Send + Sync; +/// Path filter to limit what gets watched. +#[derive(Clone)] +pub struct WatchFilter(Option>); + +impl std::fmt::Debug for WatchFilter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("WatchFilterFn") + .field(&self.0.as_ref().map_or("no filter", |_| "filter fn")) + .finish() + } +} + +impl WatchFilter { + /// A filter that accepts any path, use to watch all paths. + pub fn accept_all() -> WatchFilter { + WatchFilter(None) + } + + /// A fitler to limit the paths that get watched. + /// + /// Only paths for which `filter` returns `true` will be watched. + pub fn with_filter(filter: Arc) -> WatchFilter { + WatchFilter(Some(filter)) + } + + fn should_watch(&self, path: &Path) -> bool { + self.0.as_ref().map_or(true, |f| f(path)) + } +} + /// Providing methods for adding and removing paths to watch. /// /// `Box` is created by [`Watcher::paths_mut`]. See its documentation for more. @@ -335,7 +366,31 @@ pub trait Watcher { /// /// [#165]: https://github.com/notify-rs/notify/issues/165 /// [#166]: https://github.com/notify-rs/notify/issues/166 - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()>; + fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + self.watch_filtered(path, recursive_mode, WatchFilter::accept_all()) + } + + /// Begin watching a new path, filtering out sub-paths by name. + /// + /// If the `path` is a directory, `recursive_mode` will be evaluated. If `recursive_mode` is + /// `RecursiveMode::Recursive` events will be delivered for all files in that tree. Otherwise + /// only the directory and its immediate children will be watched. + /// + /// If the `path` is a file, `recursive_mode` will be ignored and events will be delivered only + /// for the file. + /// + /// On some platforms, if the `path` is renamed or removed while being watched, behaviour may + /// be unexpected. See discussions in [#165] and [#166]. If less surprising behaviour is wanted + /// one may non-recursively watch the _parent_ directory as well and manage related events. + /// + /// [#165]: https://github.com/notify-rs/notify/issues/165 + /// [#166]: https://github.com/notify-rs/notify/issues/166 + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()>; /// Stop watching a path. /// diff --git a/notify/src/null.rs b/notify/src/null.rs index bbcd80d9..be227005 100644 --- a/notify/src/null.rs +++ b/notify/src/null.rs @@ -4,7 +4,7 @@ use crate::Config; -use super::{RecursiveMode, Result, Watcher}; +use super::{RecursiveMode, Result, WatchFilter, Watcher}; use std::path::Path; /// Stub `Watcher` implementation @@ -14,7 +14,12 @@ use std::path::Path; pub struct NullWatcher; impl Watcher for NullWatcher { - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { Ok(()) } diff --git a/notify/src/poll.rs b/notify/src/poll.rs index fecaf22e..27a87828 100644 --- a/notify/src/poll.rs +++ b/notify/src/poll.rs @@ -3,7 +3,9 @@ //! Checks the `watch`ed paths periodically to detect changes. This implementation only uses //! Rust stdlib APIs and should work on all of the platforms it supports. -use crate::{unbounded, Config, Error, EventHandler, Receiver, RecursiveMode, Sender, Watcher}; +use crate::{ + unbounded, Config, Error, EventHandler, Receiver, RecursiveMode, Sender, WatchFilter, Watcher, +}; use std::{ collections::HashMap, path::{Path, PathBuf}, @@ -648,7 +650,12 @@ impl Watcher for PollWatcher { Self::new(event_handler, config) } - fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> crate::Result<()> { + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + _watch_filter: WatchFilter, + ) -> crate::Result<()> { self.watch_inner(path, recursive_mode); Ok(()) diff --git a/notify/src/windows.rs b/notify/src/windows.rs index 797052ed..c1d057c7 100644 --- a/notify/src/windows.rs +++ b/notify/src/windows.rs @@ -5,7 +5,7 @@ //! //! [ref]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363950(v=vs.85).aspx -use crate::{bounded, unbounded, BoundSender, Config, Receiver, Sender}; +use crate::{bounded, unbounded, BoundSender, Config, Receiver, Sender, WatchFilter}; use crate::{event::*, WatcherKind}; use crate::{Error, EventHandler, RecursiveMode, Result, Watcher}; use std::alloc; @@ -62,7 +62,7 @@ impl ReadDirectoryRequest { } enum Action { - Watch(PathBuf, RecursiveMode), + Watch(PathBuf, RecursiveMode, WatchFilter), Unwatch(PathBuf), Stop, Configure(Config, BoundSender>), @@ -85,7 +85,7 @@ struct ReadDirectoryChangesServer { event_handler: Arc>, meta_tx: Sender, cmd_tx: Sender>, - watches: HashMap, + watches: HashMap, wakeup_sem: HANDLE, } @@ -127,14 +127,17 @@ impl ReadDirectoryChangesServer { while let Ok(action) = self.rx.try_recv() { match action { - Action::Watch(path, recursive_mode) => { - let res = self.add_watch(path, recursive_mode.is_recursive()); - let _ = self.cmd_tx.send(res); + Action::Watch(path, recursive_mode, watch_filter) => { + let res = self.add_watch(path, recursive_mode.is_recursive(), watch_filter); + let _ = match res { + None => Ok(()), + Some(res) => self.cmd_tx.send(res), + }; } Action::Unwatch(path) => self.remove_watch(path), Action::Stop => { stopped = true; - for ws in self.watches.values() { + for (ws, _) in self.watches.values() { stop_watch(ws, &self.meta_tx); } break; @@ -164,13 +167,22 @@ impl ReadDirectoryChangesServer { } } - fn add_watch(&mut self, path: PathBuf, is_recursive: bool) -> Result { + fn add_watch( + &mut self, + path: PathBuf, + is_recursive: bool, + watch_filter: WatchFilter, + ) -> Option> { + if !watch_filter.should_watch(&path) { + return None; + } + // path must exist and be either a file or directory if !path.is_dir() && !path.is_file() { - return Err( - Error::generic("Input watch path is neither a file nor a directory.") - .add_path(path), - ); + return Some(Err(Error::generic( + "Input watch path is neither a file nor a directory.", + ) + .add_path(path))); } let (watching_file, dir_target) = { @@ -200,7 +212,7 @@ impl ReadDirectoryChangesServer { ); if handle == INVALID_HANDLE_VALUE { - return Err(if watching_file { + return Some(Err(if watching_file { Error::generic( "You attempted to watch a single file, but parent \ directory could not be opened.", @@ -209,7 +221,7 @@ impl ReadDirectoryChangesServer { } else { // TODO: Call GetLastError for better error info? Error::path_not_found().add_path(path) - }); + })); } } let wf = if watching_file { @@ -223,7 +235,9 @@ impl ReadDirectoryChangesServer { unsafe { CloseHandle(handle); } - return Err(Error::generic("Failed to create semaphore for watch.").add_path(path)); + return Some(Err( + Error::generic("Failed to create semaphore for watch.").add_path(path) + )); } let rd = ReadData { dir: dir_target, @@ -235,13 +249,13 @@ impl ReadDirectoryChangesServer { dir_handle: handle, complete_sem: semaphore, }; - self.watches.insert(path.clone(), ws); + self.watches.insert(path.clone(), (ws, watch_filter)); start_read(&rd, self.event_handler.clone(), handle, self.tx.clone()); - Ok(path) + Some(Ok(path)) } fn remove_watch(&mut self, path: PathBuf) { - if let Some(ws) = self.watches.remove(&path) { + if let Some((ws, _)) = self.watches.remove(&path) { stop_watch(&ws, &self.meta_tx); } } @@ -527,7 +541,12 @@ impl ReadDirectoryChangesWatcher { } } - fn watch_inner(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { + fn watch_inner( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> Result<()> { let pb = if path.is_absolute() { path.to_owned() } else { @@ -540,7 +559,7 @@ impl ReadDirectoryChangesWatcher { "Input watch path is neither a file nor a directory.", )); } - self.send_action_require_ack(Action::Watch(pb.clone(), recursive_mode), &pb) + self.send_action_require_ack(Action::Watch(pb.clone(), recursive_mode, watch_filter), &pb) } fn unwatch_inner(&mut self, path: &Path) -> Result<()> { @@ -568,8 +587,17 @@ impl Watcher for ReadDirectoryChangesWatcher { Self::create(event_handler, meta_tx) } + fn watch_filtered( + &mut self, + path: &Path, + recursive_mode: RecursiveMode, + watch_filter: WatchFilter, + ) -> crate::Result<()> { + self.watch_inner(path, recursive_mode, watch_filter) + } + fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> { - self.watch_inner(path, recursive_mode) + self.watch_inner(path, recursive_mode, WatchFilter::accept_all()) } fn unwatch(&mut self, path: &Path) -> Result<()> {