diff --git a/README.md b/README.md index 34cde749..85849f30 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ fn watch() -> notify::Result<()> { // Automatically select the best implementation for your platform. // You can also access each implementation directly e.g. INotifyWatcher. - let mut watcher: RecommendedWatcher = try!(Watcher::new(tx)); + let mut watcher: RecommendedWatcher = try!(Watcher::new_raw(tx)); // Add a path to be watched. All files and directories at that path and // below will be monitored for changes. @@ -43,7 +43,7 @@ fn watch() -> notify::Result<()> { // for example to handle I/O. loop { match rx.recv() { - Ok(notify::Event{ path: Some(path),op:Ok(op) }) => { + Ok(notify::RawEvent{ path: Some(path),op:Ok(op) }) => { println!("{:?} {:?}", op, path); }, Err(e) => println!("watch error {}", e), @@ -63,9 +63,11 @@ fn main() { ### From v2.x to v3.x +* `notify` now provides two APIs, a _raw_ and a _debounced_ API. In order to keep the old behavior, use the _raw_ API. +Replace every occurrence of `Watcher::new` with `Watcher::new_raw` and `Event` with `RawEvent`. Or see the docs for how to use the _debounced_ API. * The watch(..) function used to watch a file or a directory now takes an additional argument. -In order to use that argument you first need to import notify::RecursiveMode via the `use` keyword. -To keep the old behavior, use RecursiveMode::Recursive, for more information see the docs. +In order to use that argument you first need to import `RecursiveMode` via the `use` keyword. +To keep the old behavior, use `RecursiveMode::Recursive`, for more information see the docs. * The inotify back-end used to add watches recursively to a directory but it wouldn't remove them recursively. From v3.0.0 on inotify removes watches recursively if they were added recursively. * The inotify back-end didn't use to watch newly created directories. diff --git a/examples/debounced.rs b/examples/monitor_debounced.rs similarity index 86% rename from examples/debounced.rs rename to examples/monitor_debounced.rs index b5c3c692..1f57ad4e 100644 --- a/examples/debounced.rs +++ b/examples/monitor_debounced.rs @@ -11,7 +11,7 @@ fn watch>(path: P) -> notify::Result<()> { // Automatically select the best implementation for your platform. // You can also access each implementation directly e.g. INotifyWatcher. - let mut watcher: RecommendedWatcher = try!(Watcher::debounced(tx, Duration::from_secs(2))); + let mut watcher: RecommendedWatcher = try!(Watcher::new_debounced(tx, Duration::from_secs(2))); // Add a path to be watched. All files and directories at that path and // below will be monitored for changes. @@ -22,7 +22,7 @@ fn watch>(path: P) -> notify::Result<()> { loop { match rx.recv() { Ok(event) => println!("{:?}", event), - Err(e) => println!("watch error: {}", e), + Err(e) => println!("watch error: {:?}", e), } } } diff --git a/examples/monitor.rs b/examples/monitor_raw.rs similarity index 75% rename from examples/monitor.rs rename to examples/monitor_raw.rs index ae479dbb..c3f6caf5 100644 --- a/examples/monitor.rs +++ b/examples/monitor_raw.rs @@ -10,7 +10,7 @@ fn watch>(path: P) -> notify::Result<()> { // Automatically select the best implementation for your platform. // You can also access each implementation directly e.g. INotifyWatcher. - let mut watcher: RecommendedWatcher = try!(Watcher::new(tx)); + let mut watcher: RecommendedWatcher = try!(Watcher::new_raw(tx)); // Add a path to be watched. All files and directories at that path and // below will be monitored for changes. @@ -20,9 +20,9 @@ fn watch>(path: P) -> notify::Result<()> { // for example to handle I/O. loop { match rx.recv() { - Ok(notify::Event{path: Some(path), op: Ok(op), cookie}) => println!("{:?} {:?} ({:?})", op, path, cookie), - Ok(event) => println!("broken event: {:?}", event), - Err(e) => println!("watch error: {:?}", e), + Ok(notify::RawEvent{path: Some(path), op: Ok(op), cookie}) => println!("{:?} {:?} ({:?})", op, path, cookie), + Ok(event) => println!("broken event: {:?}", event), + Err(e) => println!("watch error: {:?}", e), } } } diff --git a/src/debounce/mod.rs b/src/debounce/mod.rs index d2a8fc4f..d14880f3 100644 --- a/src/debounce/mod.rs +++ b/src/debounce/mod.rs @@ -2,7 +2,7 @@ mod timer; -use super::{op, Error, Event as NotifyEvent}; +use super::{op, RawEvent, DebouncedEvent}; use self::timer::WatchTimer; @@ -14,78 +14,21 @@ use std::time::Duration; pub type OperationsBuffer = Arc, Option, Option)>>>; -#[derive(Debug)] -/// Events emitted by `notify` in _debounced_ mode. -pub enum Event { - /// `NoticeWrite` is emitted imediatelly after the first write event for the path. - /// - /// If you are reading from that file, you should probably close it imediatelly and discard all data you read from it. - NoticeWrite(PathBuf), - /// `NoticeRemove` is emitted imediatelly after a remove or rename event for the path. - /// - /// The file will continue to exist until its last file handle is closed. - NoticeRemove(PathBuf), - /// `Create` is emitted when a file or directory has been created and no events were detected for the path within the specified time frame. - /// - /// `Create` events have a higher priority than `Write` and `Chmod`. - /// These events will not be emitted if they are detected before the `Create` event has been emitted. - Create(PathBuf), - /// `Write` is emitted when a file has been written to and no events were detected for the path within the specified time frame. - /// - /// `Write` events have a higher priority than `Chmod`. - /// `Chmod` will not be emitted if it's detected before the `Write` event has been emitted. - /// - /// Upon receiving a `Create` event for a directory, it is necessary to scan the newly created directory for contents. - /// The directory can contain files or directories if those contents were created before the directory could be watched, - /// or if the directory was moved into the watched directory. - Write(PathBuf), - /// `Chmod` is emitted when attributes have been changed and no events were detected for the path within the specified time frame. - Chmod(PathBuf), - /// `Remove` is emitted when a file or directory has been removed and no events were detected for the path within the specified time frame. - Remove(PathBuf), - /// `Rename` is emitted when a file or directory has been moved within a watched directory and no events were detected for the new path within the specified time frame. - /// - /// The first path contains the source, the second path the destination. - Rename(PathBuf, PathBuf), - /// `Rescan` is emitted imediatelly after a problem has been detected that makes it necessary to re-scan the watched directories. - Rescan, - /// `Error` is emitted imediatelly after a error has been detected. - /// - /// This event may contain a path for which the error was detected. - Error(Error, Option), -} - -impl PartialEq for Event { - fn eq(&self, other: &Event) -> bool { - match (self, other) { - (&Event::NoticeWrite(ref a), &Event::NoticeWrite(ref b)) | - (&Event::NoticeRemove(ref a), &Event::NoticeRemove(ref b)) | - (&Event::Create(ref a), &Event::Create(ref b)) | - (&Event::Write(ref a), &Event::Write(ref b)) | - (&Event::Chmod(ref a), &Event::Chmod(ref b)) | - (&Event::Remove(ref a), &Event::Remove(ref b)) => a == b, - (&Event::Rename(ref a1, ref a2), &Event::Rename(ref b1, ref b2)) => (a1 == b1 && a2 == b2), - (&Event::Rescan, &Event::Rescan) => true, - _ => false, - } - } -} - pub enum EventTx { Raw { - tx: mpsc::Sender, + tx: mpsc::Sender, }, Debounced { - tx: mpsc::Sender, + tx: mpsc::Sender, debounce: Debounce, }, DebouncedTx { - tx: mpsc::Sender, + tx: mpsc::Sender, }, } impl EventTx { - pub fn send(&mut self, event: NotifyEvent) { + pub fn send(&mut self, event: RawEvent) { match *self { EventTx::Raw { ref tx } => { let _ = tx.send(event); @@ -93,7 +36,7 @@ impl EventTx { EventTx::Debounced { ref tx, ref mut debounce } => { match (event.path, event.op, event.cookie) { (None, Ok(op::RESCAN), None) => { - let _ = tx.send(Event::Rescan); + let _ = tx.send(DebouncedEvent::Rescan); } (Some(path), Ok(op), cookie) => { debounce.event(path, op, cookie); @@ -102,14 +45,14 @@ impl EventTx { // TODO panic!("path is None: {:?} ({:?})", _op, _cookie); } (path, Err(e), _) => { - let _ = tx.send(Event::Error(e, path)); + let _ = tx.send(DebouncedEvent::Error(e, path)); } } } EventTx::DebouncedTx { ref tx } => { match (event.path, event.op, event.cookie) { (None, Ok(op::RESCAN), None) => { - let _ = tx.send(Event::Rescan); + let _ = tx.send(DebouncedEvent::Rescan); } (Some(_path), Ok(_op), _cookie) => { // TODO debounce.event(_path, _op, _cookie); @@ -118,7 +61,7 @@ impl EventTx { // TODO panic!("path is None: {:?} ({:?})", _op, _cookie); } (path, Err(e), _) => { - let _ = tx.send(Event::Error(e, path)); + let _ = tx.send(DebouncedEvent::Error(e, path)); } } } @@ -127,7 +70,7 @@ impl EventTx { } pub struct Debounce { - tx: mpsc::Sender, + tx: mpsc::Sender, operations_buffer: OperationsBuffer, rename_path: Option, rename_cookie: Option, @@ -135,7 +78,7 @@ pub struct Debounce { } impl Debounce { - pub fn new(delay: Duration, tx: mpsc::Sender) -> Debounce { + pub fn new(delay: Duration, tx: mpsc::Sender) -> Debounce { let operations_buffer: OperationsBuffer = Arc::new(Mutex::new(HashMap::new())); // spawns new thread @@ -187,7 +130,7 @@ impl Debounce { Some(op::WRITE) | // change to remove event Some(op::CHMOD) => { // change to remove event *operation = Some(op::REMOVE); - let _ = self.tx.send(Event::NoticeRemove(path.clone())); + let _ = self.tx.send(DebouncedEvent::NoticeRemove(path.clone())); restart_timer(timer_id, path, &mut self.timer); } Some(op::RENAME) => { @@ -212,7 +155,7 @@ impl Debounce { pub fn event(&mut self, path: PathBuf, mut op: op::Op, cookie: Option) { if op.contains(op::RESCAN) { - let _ = self.tx.send(Event::Rescan); + let _ = self.tx.send(DebouncedEvent::Rescan); } if self.rename_path.is_some() { @@ -265,7 +208,7 @@ impl Debounce { Some(op::RENAME) | // file has been renamed before, upgrade to write event None => { // operations_buffer entry didn't exist *operation = Some(op::WRITE); - let _ = self.tx.send(Event::NoticeWrite(path.clone())); + let _ = self.tx.send(DebouncedEvent::NoticeWrite(path.clone())); restart_timer(timer_id, path.clone(), &mut self.timer); } // writing to a deleted file is impossible @@ -339,13 +282,13 @@ impl Debounce { } Some(op::WRITE) | // keep write event Some(op::CHMOD) => { // keep chmod event - let _ = self.tx.send(Event::NoticeRemove(path.clone())); + let _ = self.tx.send(DebouncedEvent::NoticeRemove(path.clone())); restart_timer(timer_id, path.clone(), &mut self.timer); } None => { // operations_buffer entry didn't exist *operation = Some(op::RENAME); - let _ = self.tx.send(Event::NoticeRemove(path.clone())); + let _ = self.tx.send(DebouncedEvent::NoticeRemove(path.clone())); restart_timer(timer_id, path.clone(), &mut self.timer); } // renaming a deleted file is impossible @@ -373,7 +316,7 @@ impl Debounce { Some(op::CHMOD) | // change to remove event None => { // operations_buffer entry didn't exist *operation = Some(op::REMOVE); - let _ = self.tx.send(Event::NoticeRemove(path.clone())); + let _ = self.tx.send(DebouncedEvent::NoticeRemove(path.clone())); restart_timer(timer_id, path.clone(), &mut self.timer); } Some(op::RENAME) => { diff --git a/src/debounce/timer.rs b/src/debounce/timer.rs index 6b6c52b7..935998a2 100644 --- a/src/debounce/timer.rs +++ b/src/debounce/timer.rs @@ -1,4 +1,4 @@ -use super::super::op; +use super::super::{op, DebouncedEvent}; use std::sync::mpsc; use std::thread; @@ -8,7 +8,7 @@ use std::collections::{BinaryHeap, HashSet}; use std::path::PathBuf; use std::cmp::Ordering; -use debounce::{self, OperationsBuffer}; +use debounce::OperationsBuffer; enum Action { Schedule(ScheduledEvent), @@ -39,12 +39,12 @@ struct ScheduleWorker { request_source: mpsc::Receiver, schedule: BinaryHeap, ignore: HashSet, - tx: mpsc::Sender, + tx: mpsc::Sender, operations_buffer: OperationsBuffer, } impl ScheduleWorker { - fn new(trigger: Arc, request_source: mpsc::Receiver, tx: mpsc::Sender, operations_buffer: OperationsBuffer) -> ScheduleWorker { + fn new(trigger: Arc, request_source: mpsc::Receiver, tx: mpsc::Sender, operations_buffer: OperationsBuffer) -> ScheduleWorker { ScheduleWorker{ trigger: trigger, request_source: request_source, @@ -86,18 +86,18 @@ impl ScheduleWorker { if let Some((op, from_path, _)) = op_buf.remove(&path) { let is_partial_rename = from_path.is_none(); if let Some(from_path) = from_path { - self.tx.send(debounce::Event::Rename(from_path, path.clone())).unwrap(); + self.tx.send(DebouncedEvent::Rename(from_path, path.clone())).unwrap(); } let message = match op { - Some(op::CREATE) => Some(debounce::Event::Create(path)), - Some(op::WRITE) => Some(debounce::Event::Write(path)), - Some(op::CHMOD) => Some(debounce::Event::Chmod(path)), - Some(op::REMOVE) => Some(debounce::Event::Remove(path)), + Some(op::CREATE) => Some(DebouncedEvent::Create(path)), + Some(op::WRITE) => Some(DebouncedEvent::Write(path)), + Some(op::CHMOD) => Some(DebouncedEvent::Chmod(path)), + Some(op::REMOVE) => Some(DebouncedEvent::Remove(path)), Some(op::RENAME) if is_partial_rename => { if path.exists() { - Some(debounce::Event::Create(path)) + Some(DebouncedEvent::Create(path)) } else { - Some(debounce::Event::Remove(path)) + Some(DebouncedEvent::Remove(path)) } }, _ => None @@ -155,7 +155,7 @@ pub struct WatchTimer { } impl WatchTimer { - pub fn new(tx: mpsc::Sender, operations_buffer: OperationsBuffer, delay: Duration) -> WatchTimer { + pub fn new(tx: mpsc::Sender, operations_buffer: OperationsBuffer, delay: Duration) -> WatchTimer { let (schedule_tx, schedule_rx) = mpsc::channel(); let trigger = Arc::new(Condvar::new()); diff --git a/src/fsevent.rs b/src/fsevent.rs index 9ce63403..ecb7b317 100644 --- a/src/fsevent.rs +++ b/src/fsevent.rs @@ -24,11 +24,11 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use std::sync::mpsc::{channel, Sender, Receiver}; -use super::{Error, Event, op, Result, Watcher, RecursiveMode}; +use super::{Error, RawEvent, DebouncedEvent, op, Result, Watcher, RecursiveMode}; use std::path::{Path, PathBuf}; use libc; -use super::debounce::{self, Debounce, EventTx}; +use super::debounce::{Debounce, EventTx}; /// FSEvents-based `Watcher` implementation pub struct FsEventWatcher { @@ -69,9 +69,9 @@ fn translate_flags(flags: fse::StreamFlags) -> op::Op { ret } -fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { +fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { if let Some(e) = event { - event_tx.send(Event { + event_tx.send(RawEvent { path: e.path, op: e.op, cookie: None, @@ -242,7 +242,7 @@ pub unsafe extern "C" fn callback( let ids = slice::from_raw_parts_mut(i_ptr, num); if let Ok(mut event_tx) = (*info).event_tx.lock() { - let mut rename_event: Option = None; + let mut rename_event: Option = None; for p in 0..num { let i = CStr::from_ptr(paths[p]).to_bytes(); @@ -269,7 +269,7 @@ pub unsafe extern "C" fn callback( } if flag.contains(fse::MUST_SCAN_SUBDIRS) { - event_tx.send(Event { + event_tx.send(RawEvent { path: None, op: Ok(op::RESCAN), cookie: None, @@ -281,7 +281,7 @@ pub unsafe extern "C" fn callback( if let Some(e) = rename_event { if e.cookie == Some((id - 1) as u32) { event_tx.send(e); - event_tx.send(Event { + event_tx.send(RawEvent { op: Ok(translate_flags(flag)), path: Some(path), cookie: Some((id - 1) as u32), @@ -289,14 +289,14 @@ pub unsafe extern "C" fn callback( rename_event = None; } else { send_pending_rename_event(Some(e), &mut event_tx); - rename_event = Some(Event { + rename_event = Some(RawEvent { path: Some(path), op: Ok(translate_flags(flag)), cookie: Some(id as u32), }); } } else { - rename_event = Some(Event { + rename_event = Some(RawEvent { path: Some(path), op: Ok(translate_flags(flag)), cookie: Some(id as u32), @@ -306,7 +306,7 @@ pub unsafe extern "C" fn callback( send_pending_rename_event(rename_event, &mut event_tx); rename_event = None; - event_tx.send(Event { + event_tx.send(RawEvent { op: Ok(translate_flags(flag)), path: Some(path), cookie: None, @@ -321,7 +321,7 @@ pub unsafe extern "C" fn callback( impl Watcher for FsEventWatcher { - fn new(tx: Sender) -> Result { + fn new_raw(tx: Sender) -> Result { Ok(FsEventWatcher { paths: unsafe { cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks) @@ -338,7 +338,7 @@ impl Watcher for FsEventWatcher { }) } - fn debounced(tx: Sender, delay: Duration) -> Result { + fn new_debounced(tx: Sender, delay: Duration) -> Result { Ok(FsEventWatcher { paths: unsafe { cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks) @@ -388,7 +388,7 @@ fn test_fsevent_watcher_drop() { let (tx, rx) = channel(); { - let mut watcher: RecommendedWatcher = Watcher::new(tx).unwrap(); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).unwrap(); watcher.watch("../../", RecursiveMode::Recursive).unwrap(); thread::sleep(Duration::from_millis(2000)); println!("is running -> {}", watcher.is_running()); diff --git a/src/inotify/mod.rs b/src/inotify/mod.rs index 276ce64c..cd1e2699 100644 --- a/src/inotify/mod.rs +++ b/src/inotify/mod.rs @@ -16,7 +16,7 @@ use std::fs::metadata; use std::path::{Path, PathBuf}; use std::sync::mpsc::{self, Sender}; use std::thread::Builder as ThreadBuilder; -use super::{Error, Event, op, Op, Result, Watcher, RecursiveMode}; +use super::{Error, RawEvent, DebouncedEvent, op, Op, Result, Watcher, RecursiveMode}; use std::time::Duration; use std::env; // test inotify_queue_overflow @@ -24,7 +24,7 @@ use std::env; mod flags; -use super::debounce::{self, Debounce, EventTx}; +use super::debounce::{Debounce, EventTx}; const INOTIFY: mio::Token = mio::Token(0); @@ -45,9 +45,9 @@ enum EventLoopMsg { } #[inline] -fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { +fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { if let Some(e) = event { - event_tx.send(Event { + event_tx.send(RawEvent { path: e.path, op: Ok(op::REMOVE), cookie: None, @@ -106,7 +106,7 @@ impl mio::Handler for INotifyHandler { for event in events { if event.is_queue_overflow() { - self.event_tx.send(Event { + self.event_tx.send(RawEvent { path: None, op: Ok(op::RESCAN), cookie: None, @@ -125,7 +125,7 @@ impl mio::Handler for INotifyHandler { if event.is_moved_from() { send_pending_rename_event(rename_event, &mut self.event_tx); remove_watch_by_event(&path, &self.watches, &mut remove_watches); - rename_event = Some(Event { + rename_event = Some(RawEvent { path: path, op: Ok(op::RENAME), cookie: Some(event.cookie), @@ -173,7 +173,7 @@ impl mio::Handler for INotifyHandler { send_pending_rename_event(rename_event, &mut self.event_tx); rename_event = None; - self.event_tx.send(Event { + self.event_tx.send(RawEvent { path: path, op: Ok(o), cookie: c, @@ -185,7 +185,7 @@ impl mio::Handler for INotifyHandler { send_pending_rename_event(rename_event, &mut self.event_tx); } Err(e) => { - self.event_tx.send(Event { + self.event_tx.send(RawEvent { path: None, op: Err(Error::Io(e)), cookie: None, @@ -325,7 +325,7 @@ impl INotifyHandler { } impl Watcher for INotifyWatcher { - fn new(tx: Sender) -> Result { + fn new_raw(tx: Sender) -> Result { INotify::init() .and_then(|inotify| EventLoop::new().map(|l| (inotify, l))) .and_then(|(inotify, mut event_loop)| { @@ -360,7 +360,7 @@ impl Watcher for INotifyWatcher { .map_err(Error::Io) } - fn debounced(tx: Sender, delay: Duration) -> Result { + fn new_debounced(tx: Sender, delay: Duration) -> Result { INotify::init() .and_then(|inotify| EventLoop::new().map(|l| (inotify, l))) .and_then(|(inotify, mut event_loop)| { diff --git a/src/lib.rs b/src/lib.rs index 7804a842..bd34ea24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,39 +13,78 @@ //! //! # Examples //! -//! Basic usage +//! `notify` provides two APIs, a _raw_ and a _debounced_ API. +//! The _raw_ API emits file changes as soon as they happen, while the _debounced_ API has a delay and tries to prevent duplicate events and simplifies transactions like _safe-saves_. +//! For more details, see [`Watcher::new_raw`](trait.Watcher.html#tymethod.new_raw) and [`Watcher::new_debounced`](trait.Watcher.html#tymethod.new_debounced). +//! +//! Debounced API +//! +//! ```no_run +//! extern crate notify; +//! +//! use notify::{Watcher, RecursiveMode, debounced_watcher}; +//! use std::sync::mpsc::channel; +//! use std::time::Duration; +//! +//! fn main() { +//! // Create a channel to receive the events. +//! let (tx, rx) = channel(); +//! +//! // Create a watcher object, delivering debounced events. +//! // The notification back-end is selected based on the platform. +//! let mut watcher = debounced_watcher(tx, Duration::from_secs(10)).unwrap(); +//! +//! // Add a path to be watched. All files and directories at that path and +//! // below will be monitored for changes. +//! watcher.watch("/home/test/notify", RecursiveMode::Recursive).unwrap(); +//! +//! loop { +//! match rx.recv() { +//! Ok(event) => println!("{:?}", event), +//! Err(e) => println!("watch error: {:?}", e), +//! } +//! } +//! } +//! ``` +//! +//! Using the _debounced_ API is easy, all possible events are described in the [`DebouncedEvent`](enum.DebouncedEvent.html) documentation. +//! But in order to understand the subtleties of the event delivery, you should read the [`op`](op/index.html) documentation as well. +//! +//! Raw API //! //! ```no_run //! extern crate notify; //! -//! use notify::{RecommendedWatcher, Error, Watcher, RecursiveMode}; +//! use notify::{Watcher, RecursiveMode, RawEvent, raw_watcher}; //! use std::sync::mpsc::channel; //! //! fn main() { -//! // Create a channel to receive the events. -//! let (tx, rx) = channel(); -//! -//! // Automatically select the best implementation for your platform. -//! // You can also access each implementation directly e.g. INotifyWatcher. -//! let w: Result = Watcher::new(tx); -//! -//! match w { -//! Ok(mut watcher) => { -//! // Add a path to be watched. All files and directories at that path and -//! // below will be monitored for changes. -//! watcher.watch("/home/test/notify", RecursiveMode::Recursive); -//! -//! // You'll probably want to do that in a loop. The type to match for is -//! // notify::Event, look at src/lib.rs for details. -//! match rx.recv() { -//! _ => println!("Recv.") -//! } -//! }, -//! Err(_) => println!("Error") -//! } +//! // Create a channel to receive the events. +//! let (tx, rx) = channel(); +//! +//! // Create a watcher object, delivering raw events. +//! // The notification back-end is selected based on the platform. +//! let mut watcher = raw_watcher(tx).unwrap(); +//! +//! // Add a path to be watched. All files and directories at that path and +//! // below will be monitored for changes. +//! watcher.watch("/home/test/notify", RecursiveMode::Recursive).unwrap(); +//! +//! loop { +//! match rx.recv() { +//! Ok(RawEvent{path: Some(path), op: Ok(op), cookie}) => { +//! println!("{:?} {:?} ({:?})", op, path, cookie) +//! }, +//! Ok(event) => println!("broken event: {:?}", event), +//! Err(e) => println!("watch error: {:?}", e), +//! } +//! } //! } //! ``` //! +//! The event structure is described in the [`RawEvent`](struct.RawEvent.html) documentation, +//! all possible operations delivered in an event are described in the [`op`](op/index.html) documentation. +//! //! ## Platforms //! //! - Linux / Android: inotify @@ -121,7 +160,7 @@ pub mod windows; pub mod null; pub mod poll; -pub mod debounce; +mod debounce; /// Contains the `Op` type which describes the actions for an event. /// @@ -309,9 +348,9 @@ pub mod op { } } -/// Event delivered when action occurs on a watched path +/// Event delivered when action occurs on a watched path in _raw_ mode #[derive(Debug)] -pub struct Event { +pub struct RawEvent { /// Path where the event originated. /// /// `path` is always abolute, even if a relative path is used to _watch_ a file or directory. @@ -338,7 +377,64 @@ pub struct Event { pub cookie: Option, } -unsafe impl Send for Event {} +unsafe impl Send for RawEvent {} + +#[derive(Debug)] +/// Event delivered when action occurs on a watched path in _debounced_ mode +pub enum DebouncedEvent { + /// `NoticeWrite` is emitted imediatelly after the first write event for the path. + /// + /// If you are reading from that file, you should probably close it imediatelly and discard all data you read from it. + NoticeWrite(PathBuf), + /// `NoticeRemove` is emitted imediatelly after a remove or rename event for the path. + /// + /// The file will continue to exist until its last file handle is closed. + NoticeRemove(PathBuf), + /// `Create` is emitted when a file or directory has been created and no events were detected for the path within the specified time frame. + /// + /// `Create` events have a higher priority than `Write` and `Chmod`. + /// These events will not be emitted if they are detected before the `Create` event has been emitted. + Create(PathBuf), + /// `Write` is emitted when a file has been written to and no events were detected for the path within the specified time frame. + /// + /// `Write` events have a higher priority than `Chmod`. + /// `Chmod` will not be emitted if it's detected before the `Write` event has been emitted. + /// + /// Upon receiving a `Create` event for a directory, it is necessary to scan the newly created directory for contents. + /// The directory can contain files or directories if those contents were created before the directory could be watched, + /// or if the directory was moved into the watched directory. + Write(PathBuf), + /// `Chmod` is emitted when attributes have been changed and no events were detected for the path within the specified time frame. + Chmod(PathBuf), + /// `Remove` is emitted when a file or directory has been removed and no events were detected for the path within the specified time frame. + Remove(PathBuf), + /// `Rename` is emitted when a file or directory has been moved within a watched directory and no events were detected for the new path within the specified time frame. + /// + /// The first path contains the source, the second path the destination. + Rename(PathBuf, PathBuf), + /// `Rescan` is emitted imediatelly after a problem has been detected that makes it necessary to re-scan the watched directories. + Rescan, + /// `Error` is emitted imediatelly after a error has been detected. + /// + /// This event may contain a path for which the error was detected. + Error(Error, Option), +} + +impl PartialEq for DebouncedEvent { + fn eq(&self, other: &DebouncedEvent) -> bool { + match (self, other) { + (&DebouncedEvent::NoticeWrite(ref a), &DebouncedEvent::NoticeWrite(ref b)) | + (&DebouncedEvent::NoticeRemove(ref a), &DebouncedEvent::NoticeRemove(ref b)) | + (&DebouncedEvent::Create(ref a), &DebouncedEvent::Create(ref b)) | + (&DebouncedEvent::Write(ref a), &DebouncedEvent::Write(ref b)) | + (&DebouncedEvent::Chmod(ref a), &DebouncedEvent::Chmod(ref b)) | + (&DebouncedEvent::Remove(ref a), &DebouncedEvent::Remove(ref b)) => a == b, + (&DebouncedEvent::Rename(ref a1, ref a2), &DebouncedEvent::Rename(ref b1, ref b2)) => (a1 == b1 && a2 == b2), + (&DebouncedEvent::Rescan, &DebouncedEvent::Rescan) => true, + _ => false, + } + } +} /// Errors generated from the `notify` crate #[derive(Debug)] @@ -417,12 +513,12 @@ impl RecursiveMode { /// addition to such event driven implementations, a polling implementation is also provided that /// should work on any platform. pub trait Watcher: Sized { - /// Create a new Watcher. + /// Create a new watcher in _raw_ mode. /// - /// Events will be sent using the provided `tx`. - fn new(tx: Sender) -> Result; + /// Events will be sent using the provided `tx` immediately after they occurred. + fn new_raw(tx: Sender) -> Result; - /// Create a new _debounced_ Watcher with a `delay`. + /// Create a new _debounced_ watcher with a `delay`. /// /// Events won't be sent immediately but after the specified delay. /// @@ -448,7 +544,7 @@ pub trait Watcher: Sized { /// Your application might not feel as responsive. /// /// If a file is saved very slowly, you might receive a `Write` event even though the file is still being written to. - fn debounced(tx: Sender, delay: Duration) -> Result; + fn new_debounced(tx: Sender, delay: Duration) -> Result; /// Begin watching a new path. /// @@ -480,11 +576,18 @@ pub type RecommendedWatcher = ReadDirectoryChangesWatcher; #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] pub type RecommendedWatcher = PollWatcher; -/// Convenience method for creating the `RecommendedWatcher` for the current platform. +/// Convenience method for creating the `RecommendedWatcher` for the current platform in _raw_ mode. +/// +/// See [`Watcher::new_raw`](trait.Watcher.html#tymethod.new_raw). +pub fn raw_watcher(tx: Sender) -> Result { + Watcher::new_raw(tx) +} + +/// Convenience method for creating the `RecommendedWatcher` for the current platform in _debounced_ mode. /// -/// Events will be sent using the provided `tx`. -pub fn new(tx: Sender) -> Result { - Watcher::new(tx) +/// See [`Watcher::new_debounced`](trait.Watcher.html#tymethod.new_debounced). +pub fn debounced_watcher(tx: Sender, delay: Duration) -> Result { + Watcher::new_debounced(tx, delay) } diff --git a/src/null.rs b/src/null.rs index 27ca8003..b45723d0 100644 --- a/src/null.rs +++ b/src/null.rs @@ -5,7 +5,7 @@ use std::sync::mpsc::Sender; use std::path::Path; use std::time::Duration; -use super::{Event, Result, Watcher, RecursiveMode, debounce}; +use super::{RawEvent, DebouncedEvent, Result, Watcher, RecursiveMode}; /// Stub `Watcher` implementation /// @@ -13,11 +13,11 @@ use super::{Event, Result, Watcher, RecursiveMode, debounce}; pub struct NullWatcher; impl Watcher for NullWatcher { - fn new(tx: Sender) -> Result { + fn new_raw(tx: Sender) -> Result { Ok(NullWatcher) } - fn debounced(tx: Sender, delay: Duration) -> Result { + fn new_debounced(tx: Sender, delay: Duration) -> Result { Ok(NullWatcher) } diff --git a/src/poll.rs b/src/poll.rs index 7ecd2226..3ccc67b3 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -8,8 +8,8 @@ use std::sync::{Arc, RwLock, Mutex}; use std::sync::mpsc::Sender; use std::fs; use std::thread; -use super::{Error, Event, op, Result, Watcher, RecursiveMode}; -use super::debounce::{self, Debounce, EventTx}; +use super::{Error, RawEvent, DebouncedEvent, op, Result, Watcher, RecursiveMode}; +use super::debounce::{Debounce, EventTx}; use std::path::{Path, PathBuf}; use std::time::Duration; use self::walkdir::WalkDir; @@ -38,7 +38,7 @@ pub struct PollWatcher { impl PollWatcher { /// Create a PollWatcher which polls every `delay` milliseconds - pub fn with_delay_ms(tx: Sender, delay: u32) -> Result { + pub fn with_delay_ms(tx: Sender, delay: u32) -> Result { let mut p = PollWatcher { event_tx: EventTx::Raw { tx: tx.clone(), @@ -74,7 +74,7 @@ impl PollWatcher { for (watch, &mut WatchData{is_recursive, ref mut paths}) in watches.iter_mut() { match fs::metadata(watch) { Err(e) => { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(watch.clone()), op: Err(Error::Io(e)), cookie: None, @@ -90,7 +90,7 @@ impl PollWatcher { } Some(PathData{mtime: old_mtime, ..}) => { if mtime > old_mtime { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(watch.clone()), op: Ok(op::WRITE), cookie: None, @@ -113,7 +113,7 @@ impl PollWatcher { match entry.metadata() { Err(e) => { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path.to_path_buf()), op: Err(Error::Io(e.into())), cookie: None, @@ -123,7 +123,7 @@ impl PollWatcher { let mtime = FileTime::from_last_modification_time(&m).seconds(); match paths.insert(path.to_path_buf(), PathData{mtime: mtime, last_check: current_time}) { None => { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path.to_path_buf()), op: Ok(op::CREATE), cookie: None, @@ -131,7 +131,7 @@ impl PollWatcher { } Some(PathData{mtime: old_mtime, ..}) => { if mtime > old_mtime { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path.to_path_buf()), op: Ok(op::WRITE), cookie: None, @@ -151,7 +151,7 @@ impl PollWatcher { let mut removed = Vec::new(); for (path, &PathData{last_check, ..}) in paths.iter() { if last_check < current_time { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path.clone()), op: Ok(op::REMOVE), cookie: None, @@ -172,11 +172,11 @@ impl PollWatcher { } impl Watcher for PollWatcher { - fn new(tx: Sender) -> Result { + fn new_raw(tx: Sender) -> Result { PollWatcher::with_delay_ms(tx, 30_000) } - fn debounced(tx: Sender, delay: Duration) -> Result { + fn new_debounced(tx: Sender, delay: Duration) -> Result { let mut p = PollWatcher { event_tx: EventTx::DebouncedTx { tx: tx.clone(), @@ -200,7 +200,7 @@ impl Watcher for PollWatcher { match fs::metadata(path) { Err(e) => { - self.event_tx.send(Event { + self.event_tx.send(RawEvent { path: Some(watch.clone()), op: Err(Error::Io(e)), cookie: None, @@ -228,7 +228,7 @@ impl Watcher for PollWatcher { match entry.metadata() { Err(e) => { - self.event_tx.send(Event { + self.event_tx.send(RawEvent { path: Some(path.to_path_buf()), op: Err(Error::Io(e.into())), cookie: None, diff --git a/src/windows.rs b/src/windows.rs index 406876c4..e71540d7 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -23,9 +23,9 @@ use std::os::raw::c_void; use std::time::Duration; use std::sync::{Arc, Mutex}; -use super::{Event, Error, op, Op, Result, Watcher, RecursiveMode}; +use super::{RawEvent, DebouncedEvent, Error, op, Op, Result, Watcher, RecursiveMode}; -use super::debounce::{self, Debounce, EventTx}; +use super::debounce::{Debounce, EventTx}; const BUF_SIZE: u32 = 16384; @@ -283,9 +283,9 @@ fn start_read(rd: &ReadData, event_tx: Arc>, handle: HANDLE) { } } -fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { +fn send_pending_rename_event(event: Option, event_tx: &mut EventTx) { if let Some(e) = event { - event_tx.send(Event { + event_tx.send(RawEvent { path: e.path, op: Ok(op::REMOVE), cookie: None, @@ -335,7 +335,7 @@ unsafe extern "system" fn handle_event(error_code: u32, if (*cur_entry).Action == winnt::FILE_ACTION_RENAMED_OLD_NAME { send_pending_rename_event(rename_event, &mut event_tx); if request.data.file.is_some() { - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path), op: Ok(op::RENAME), cookie: None, @@ -343,7 +343,7 @@ unsafe extern "system" fn handle_event(error_code: u32, rename_event = None; } else { COOKIE_COUNTER = COOKIE_COUNTER.wrapping_add(1); - rename_event = Some(Event { + rename_event = Some(RawEvent { path: Some(path), op: Ok(op::RENAME), cookie: Some(COOKIE_COUNTER), @@ -377,7 +377,7 @@ unsafe extern "system" fn handle_event(error_code: u32, send_pending_rename_event(rename_event, &mut event_tx); rename_event = None; - event_tx.send(Event { + event_tx.send(RawEvent { path: Some(path), op: Ok(o), cookie: c, @@ -403,7 +403,7 @@ pub struct ReadDirectoryChangesWatcher { } impl ReadDirectoryChangesWatcher { - pub fn create(tx: Sender, + pub fn create(tx: Sender, meta_tx: Sender) -> Result { let (cmd_tx, cmd_rx) = channel(); @@ -428,7 +428,7 @@ impl ReadDirectoryChangesWatcher { }) } - pub fn create_debounced(tx: Sender, + pub fn create_debounced(tx: Sender, meta_tx: Sender, delay: Duration) -> Result { @@ -497,13 +497,13 @@ impl ReadDirectoryChangesWatcher { } impl Watcher for ReadDirectoryChangesWatcher { - fn new(tx: Sender) -> Result { + fn new_raw(tx: Sender) -> Result { // create dummy channel for meta event let (meta_tx, _) = channel(); ReadDirectoryChangesWatcher::create(tx, meta_tx) } - fn debounced(tx: Sender, delay: Duration) -> Result { + fn new_debounced(tx: Sender, delay: Duration) -> Result { // create dummy channel for meta event let (meta_tx, _) = channel(); ReadDirectoryChangesWatcher::create_debounced(tx, meta_tx, delay) diff --git a/tests/debounce.rs b/tests/debounce.rs index 6665e1c5..57f0af63 100644 --- a/tests/debounce.rs +++ b/tests/debounce.rs @@ -19,7 +19,7 @@ use std::thread; const DELAY_S: u64 = 1; const TIMEOUT_S: f64 = 1.0; -fn recv_events_debounced(rx: &mpsc::Receiver) -> Vec { +fn recv_events_debounced(rx: &mpsc::Receiver) -> Vec { let deadline = time::precise_time_s() + DELAY_S as f64 + TIMEOUT_S; let mut events = Vec::new(); @@ -42,13 +42,13 @@ fn create_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("file1")), + DebouncedEvent::Create(tdir.mkpath("file1")), ]); } @@ -63,14 +63,14 @@ fn write_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.write("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::Write(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::Write(tdir.mkpath("file1")), ]); } @@ -85,7 +85,7 @@ fn write_long_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); let wait = Duration::from_millis(DELAY_S * 500); @@ -98,11 +98,14 @@ fn write_long_file() { tdir.write("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::Write(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::Write(tdir.mkpath("file1")), ]); } +// Linux: +// thread 'write_long_file' panicked at 'assertion failed: `(left == right)` (left: `[NoticeWrite("/tmp/temp_dir.fZov9D5M7lQ6/file1"), Write("/tmp/temp_dir.fZov9D5M7lQ6/file1"), NoticeWrite("/tmp/temp_dir.fZov9D5M7lQ6/file1"), Write("/tmp/temp_dir.fZov9D5M7lQ6/file1")]`, right: `[NoticeWrite("/tmp/temp_dir.fZov9D5M7lQ6/file1"), Write("/tmp/temp_dir.fZov9D5M7lQ6/file1")]`)', tests/debounce.rs:100 + #[test] fn modify_file() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); @@ -114,7 +117,7 @@ fn modify_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.chmod("file1"); @@ -122,12 +125,12 @@ fn modify_file() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::Write(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::Write(tdir.mkpath("file1")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Chmod(tdir.mkpath("file1")), + DebouncedEvent::Chmod(tdir.mkpath("file1")), ]); } } @@ -143,14 +146,14 @@ fn delete_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.remove("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Remove(tdir.mkpath("file1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Remove(tdir.mkpath("file1")), ]); } @@ -165,14 +168,14 @@ fn rename_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1", "file2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), ]); } @@ -183,7 +186,7 @@ fn create_write_modify_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -191,7 +194,7 @@ fn create_write_modify_file() { tdir.chmod("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("file1")), + DebouncedEvent::Create(tdir.mkpath("file1")), ]); } @@ -202,7 +205,7 @@ fn create_delete_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -223,7 +226,7 @@ fn delete_create_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.remove("file1"); @@ -231,8 +234,8 @@ fn delete_create_file() { tdir.create("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Write(tdir.mkpath("file1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Write(tdir.mkpath("file1")), ]); } @@ -243,14 +246,14 @@ fn create_rename_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); tdir.rename("file1", "file2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("file2")), + DebouncedEvent::Create(tdir.mkpath("file2")), ]); } @@ -261,7 +264,7 @@ fn create_rename_delete_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -273,6 +276,11 @@ fn create_rename_delete_file() { assert_eq!(recv_events_debounced(&rx), vec![]); } +// ---- create_rename_delete_file stdout ---- + +// Mac OS +// thread 'create_rename_delete_file' panicked at 'assertion failed: `(left == right)` (left: `[NoticeRemove("/private/var/folders/gw/_2jq29095y7b__wtby9dg_5h0000gn/T/temp_dir.MJM4fvovN8qg/file2"), Remove("/private/var/folders/gw/_2jq29095y7b__wtby9dg_5h0000gn/T/temp_dir.MJM4fvovN8qg/file2")]`, right: `[]`)', tests/debounce.rs:273 + #[test] fn create_rename_overwrite_file() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); @@ -284,7 +292,7 @@ fn create_rename_overwrite_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -293,17 +301,17 @@ fn create_rename_overwrite_file() { if cfg!(target_os="windows") { // Windows interprets a move that overwrites a file as a delete of the source file and a write to the file that is being overwritten assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file2")), - debounce::Event::Write(tdir.mkpath("file2")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file2")), + DebouncedEvent::Write(tdir.mkpath("file2")), ]); } else if cfg!(target_os="macos") { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file2")), - debounce::Event::Create(tdir.mkpath("file2")), // even though the file is being overwritten, that can't be detected + DebouncedEvent::NoticeRemove(tdir.mkpath("file2")), + DebouncedEvent::Create(tdir.mkpath("file2")), // even though the file is being overwritten, that can't be detected ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("file2")), // even though the file is being overwritten, that can't be detected + DebouncedEvent::Create(tdir.mkpath("file2")), // even though the file is being overwritten, that can't be detected ]); } } @@ -319,17 +327,17 @@ fn write_rename_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.write("file1"); tdir.rename("file1", "file2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Write(tdir.mkpath("file2")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Write(tdir.mkpath("file2")), ]); } @@ -344,7 +352,7 @@ fn rename_write_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1", "file2"); @@ -352,10 +360,10 @@ fn rename_write_file() { tdir.write("file2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::NoticeWrite(tdir.mkpath("file2")), // TODO not necessary - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Write(tdir.mkpath("file2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file2")), // TODO not necessary + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Write(tdir.mkpath("file2")), ]); } @@ -370,7 +378,7 @@ fn modify_rename_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.chmod("file1"); @@ -379,16 +387,16 @@ fn modify_rename_file() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Write(tdir.mkpath("file2")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Write(tdir.mkpath("file2")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Chmod(tdir.mkpath("file2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Chmod(tdir.mkpath("file2")), ]); } } @@ -404,7 +412,7 @@ fn rename_modify_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1", "file2"); @@ -414,16 +422,16 @@ fn rename_modify_file() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::NoticeWrite(tdir.mkpath("file2")), // TODO unnecessary - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Write(tdir.mkpath("file2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file2")), // TODO unnecessary + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Write(tdir.mkpath("file2")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), - debounce::Event::Chmod(tdir.mkpath("file2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file2")), + DebouncedEvent::Chmod(tdir.mkpath("file2")), ]); } } @@ -439,7 +447,7 @@ fn rename_rename_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1", "file2"); @@ -447,8 +455,8 @@ fn rename_rename_file() { tdir.rename("file2", "file3"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Rename(tdir.mkpath("file1"), tdir.mkpath("file3")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Rename(tdir.mkpath("file1"), tdir.mkpath("file3")), ]); } @@ -463,16 +471,16 @@ fn write_delete_file() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.write("file1"); tdir.remove("file1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("file1")), - debounce::Event::NoticeRemove(tdir.mkpath("file1")), - debounce::Event::Remove(tdir.mkpath("file1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("file1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("file1")), + DebouncedEvent::Remove(tdir.mkpath("file1")), ]); } @@ -483,13 +491,13 @@ fn create_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("dir1")), + DebouncedEvent::Create(tdir.mkpath("dir1")), ]); } @@ -504,7 +512,7 @@ fn modify_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.chmod("dir1"); @@ -512,12 +520,12 @@ fn modify_directory() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("dir1")), - debounce::Event::Write(tdir.mkpath("dir1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("dir1")), + DebouncedEvent::Write(tdir.mkpath("dir1")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Chmod(tdir.mkpath("dir1")), + DebouncedEvent::Chmod(tdir.mkpath("dir1")), ]); } } @@ -533,14 +541,14 @@ fn delete_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.remove("dir1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Remove(tdir.mkpath("dir1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Remove(tdir.mkpath("dir1")), ]); } @@ -555,14 +563,14 @@ fn rename_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("dir1", "dir2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), ]); } @@ -573,14 +581,14 @@ fn create_modify_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); tdir.chmod("dir1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("dir1")), + DebouncedEvent::Create(tdir.mkpath("dir1")), ]); } @@ -591,7 +599,7 @@ fn create_delete_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); @@ -612,7 +620,7 @@ fn delete_create_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.remove("dir1"); @@ -620,8 +628,8 @@ fn delete_create_directory() { tdir.create("dir1"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Write(tdir.mkpath("dir1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Write(tdir.mkpath("dir1")), ]); } @@ -632,14 +640,14 @@ fn create_rename_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); tdir.rename("dir1", "dir2"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("dir2")), + DebouncedEvent::Create(tdir.mkpath("dir2")), ]); } @@ -650,7 +658,7 @@ fn create_rename_delete_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); @@ -679,7 +687,7 @@ fn create_rename_overwrite_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("dir1"); @@ -687,12 +695,12 @@ fn create_rename_overwrite_directory() { if cfg!(target_os="macos") { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected - debounce::Event::Create(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected + DebouncedEvent::NoticeRemove(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected + DebouncedEvent::Create(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::Create(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected + DebouncedEvent::Create(tdir.mkpath("dir2")), // even though the directory is being overwritten, that can't be detected ]); } } @@ -708,7 +716,7 @@ fn modify_rename_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.chmod("dir1"); @@ -718,16 +726,16 @@ fn modify_rename_directory() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("dir1")), - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Write(tdir.mkpath("dir2")), + DebouncedEvent::NoticeWrite(tdir.mkpath("dir1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Write(tdir.mkpath("dir2")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Chmod(tdir.mkpath("dir2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Chmod(tdir.mkpath("dir2")), ]); } } @@ -743,7 +751,7 @@ fn rename_modify_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("dir1", "dir2"); @@ -755,27 +763,27 @@ fn rename_modify_directory() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(actual, vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::NoticeWrite(tdir.mkpath("dir2")), // TODO unnecessary - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Write(tdir.mkpath("dir2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("dir2")), // TODO unnecessary + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Write(tdir.mkpath("dir2")), ]); } else if cfg!(target_os="linux") { assert_eq_any!(actual, vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Chmod(tdir.mkpath("dir2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Chmod(tdir.mkpath("dir2")), ], vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Chmod(tdir.mkpath("dir2")), - debounce::Event::Chmod(tdir.mkpath("dir1")), // excessive chmod event + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Chmod(tdir.mkpath("dir2")), + DebouncedEvent::Chmod(tdir.mkpath("dir1")), // excessive chmod event ]); } else { assert_eq!(actual, vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), - debounce::Event::Chmod(tdir.mkpath("dir2")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir2")), + DebouncedEvent::Chmod(tdir.mkpath("dir2")), ]); } } @@ -791,7 +799,7 @@ fn rename_rename_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("dir1", "dir2"); @@ -799,8 +807,8 @@ fn rename_rename_directory() { tdir.rename("dir2", "dir3"); assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir3")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Rename(tdir.mkpath("dir1"), tdir.mkpath("dir3")), ]); } @@ -815,7 +823,7 @@ fn modify_delete_directory() { sleep_macos(35_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_debounced(tx, Duration::from_secs(DELAY_S)).expect("failed to create debounced watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.chmod("dir1"); @@ -825,14 +833,14 @@ fn modify_delete_directory() { if cfg!(target_os="windows") { // windows cannot distinguish between chmod and write assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeWrite(tdir.mkpath("dir1")), - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Remove(tdir.mkpath("dir1")), + DebouncedEvent::NoticeWrite(tdir.mkpath("dir1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Remove(tdir.mkpath("dir1")), ]); } else { assert_eq!(recv_events_debounced(&rx), vec![ - debounce::Event::NoticeRemove(tdir.mkpath("dir1")), - debounce::Event::Remove(tdir.mkpath("dir1")), + DebouncedEvent::NoticeRemove(tdir.mkpath("dir1")), + DebouncedEvent::Remove(tdir.mkpath("dir1")), ]); } } diff --git a/tests/event_path.rs b/tests/event_path.rs index abb16bb4..c9afcd2d 100644 --- a/tests/event_path.rs +++ b/tests/event_path.rs @@ -16,12 +16,12 @@ use utils::*; const NETWORK_PATH: &'static str = ""; // eg.: \\\\MY-PC\\Users\\MyName #[cfg(target_os = "windows")] -fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { +fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { recv_events(&rx) } #[cfg(target_os = "macos")] -fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { +fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { let mut events = Vec::new(); for (path, op, cookie) in inflate_events(recv_events(&rx)) { if op == (op::CREATE | op::WRITE) { @@ -34,7 +34,7 @@ fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> } #[cfg(target_os = "linux")] -fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { +fn recv_events_simple(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { let mut events = recv_events(&rx); events.retain(|&(_, op, _)| op != op::CLOSE_WRITE); events @@ -52,7 +52,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("dir1", RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -76,7 +76,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("file1", RecursiveMode::Recursive).expect("failed to watch file"); sleep_windows(100); @@ -101,7 +101,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("dir1", RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -120,7 +120,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("file1", RecursiveMode::Recursive).expect("failed to watch file"); sleep_windows(100); @@ -142,7 +142,7 @@ fn watch_absolute_directory() { let watch_path = tdir.path().join("dir1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -167,7 +167,7 @@ fn watch_absolute_file() { let watch_path = tdir.path().join("file1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -197,7 +197,7 @@ fn watch_absolute_network_directory() { let watch_path = tdir.path().join("dir1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -221,7 +221,7 @@ fn watch_absolute_network_file() { let watch_path = tdir.path().join("file1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -242,7 +242,7 @@ fn watch_canonicalized_directory() { let watch_path = tdir.path().canonicalize().expect("failed to canonicalize path").join("dir1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -261,7 +261,7 @@ fn watch_canonicalized_file() { let watch_path = tdir.path().canonicalize().expect("failed to canonicalize path").join("file1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -285,7 +285,7 @@ fn watch_canonicalized_network_directory() { let watch_path = tdir.path().canonicalize().expect("failed to canonicalize path").join("dir1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -309,7 +309,7 @@ fn watch_canonicalized_network_file() { let watch_path = tdir.path().canonicalize().expect("failed to canonicalize path").join("file1"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&watch_path, RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); diff --git a/tests/fsevents.rs b/tests/fsevents.rs index b337def7..612d4613 100644 --- a/tests/fsevents.rs +++ b/tests/fsevents.rs @@ -23,7 +23,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -47,7 +47,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -75,7 +75,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -103,7 +103,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -131,7 +131,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -159,7 +159,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -187,7 +187,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -215,7 +215,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.create("file1"); @@ -247,7 +247,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -274,7 +274,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -303,7 +303,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -332,7 +332,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -358,7 +358,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -387,7 +387,7 @@ mod timing_tests { sleep(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); @@ -416,7 +416,7 @@ mod timing_tests { sleep(40_000); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("file1a", "file1b"); diff --git a/tests/notify.rs b/tests/notify.rs index d91c14d5..8da1db1e 100644 --- a/tests/notify.rs +++ b/tests/notify.rs @@ -37,7 +37,7 @@ fn create_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -71,7 +71,7 @@ fn write_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -106,7 +106,7 @@ fn modify_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -143,7 +143,7 @@ fn delete_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -172,7 +172,7 @@ fn rename_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -210,7 +210,7 @@ fn move_out_create_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -245,7 +245,7 @@ fn create_write_modify_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -288,7 +288,7 @@ fn create_rename_overwrite_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -333,7 +333,7 @@ fn rename_rename_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -370,7 +370,7 @@ fn create_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -400,7 +400,7 @@ fn modify_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -438,7 +438,7 @@ fn delete_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -467,7 +467,7 @@ fn rename_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -505,7 +505,7 @@ fn move_out_create_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -543,7 +543,7 @@ fn create_rename_overwrite_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -582,7 +582,7 @@ fn rename_rename_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 392e9d7e..3e27174c 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -17,18 +17,18 @@ const TIMEOUT_S: f64 = 0.1; #[cfg(target_os="windows")] const TIMEOUT_S: f64 = 3.0; // windows can take a while -pub fn recv_events_with_timeout(rx: &Receiver, timeout: f64) -> Vec<(PathBuf, Op, Option)> { +pub fn recv_events_with_timeout(rx: &Receiver, timeout: f64) -> Vec<(PathBuf, Op, Option)> { let deadline = time::precise_time_s() + timeout; let mut evs = Vec::new(); while time::precise_time_s() < deadline { match rx.try_recv() { - Ok(Event{path: Some(path), op: Ok(op), cookie}) => { + Ok(RawEvent{path: Some(path), op: Ok(op), cookie}) => { evs.push((path, op, cookie)); }, - Ok(Event{path: None, ..}) => (), - Ok(Event{op: Err(e), ..}) => panic!("unexpected event err: {:?}", e), + Ok(RawEvent{path: None, ..}) => (), + Ok(RawEvent{op: Err(e), ..}) => panic!("unexpected event err: {:?}", e), Err(TryRecvError::Empty) => (), Err(e) => panic!("unexpected channel err: {:?}", e) } @@ -37,7 +37,7 @@ pub fn recv_events_with_timeout(rx: &Receiver, timeout: f64) -> Vec<(Pat evs } -pub fn recv_events(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { +pub fn recv_events(rx: &Receiver) -> Vec<(PathBuf, Op, Option)> { recv_events_with_timeout(rx, TIMEOUT_S) } diff --git a/tests/watcher.rs b/tests/watcher.rs index 57e71464..82ba862b 100644 --- a/tests/watcher.rs +++ b/tests/watcher.rs @@ -25,7 +25,7 @@ const NETWORK_PATH: &'static str = ""; // eg.: \\\\MY-PC\\Users\\MyName #[test] fn new_inotify() { let (tx, _) = mpsc::channel(); - let w: Result = Watcher::new(tx); + let w: Result = Watcher::new_raw(tx); assert!(w.is_ok()); } @@ -33,28 +33,28 @@ fn new_inotify() { #[test] fn new_fsevent() { let (tx, _) = mpsc::channel(); - let w: Result = Watcher::new(tx); + let w: Result = Watcher::new_raw(tx); assert!(w.is_ok()); } #[test] fn new_null() { let (tx, _) = mpsc::channel(); - let w: Result = Watcher::new(tx); + let w: Result = Watcher::new_raw(tx); assert!(w.is_ok()); } #[test] fn new_poll() { let (tx, _) = mpsc::channel(); - let w: Result = Watcher::new(tx); + let w: Result = Watcher::new_raw(tx); assert!(w.is_ok()); } #[test] fn new_recommended() { let (tx, _) = mpsc::channel(); - let w: Result = Watcher::new(tx); + let w: Result = Watcher::new_raw(tx); assert!(w.is_ok()); } @@ -63,7 +63,7 @@ fn new_recommended() { fn test_watcher_send() { let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).unwrap(); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).unwrap(); thread::spawn(move || { watcher.watch(".", RecursiveMode::Recursive).unwrap(); @@ -77,7 +77,7 @@ fn test_watcher_sync() { let (tx, _) = mpsc::channel(); - let watcher: RecommendedWatcher = Watcher::new(tx).unwrap(); + let watcher: RecommendedWatcher = Watcher::new_raw(tx).unwrap(); let watcher = Arc::new(RwLock::new(watcher)); thread::spawn(move || { @@ -96,7 +96,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("dir1", RecursiveMode::Recursive).expect("failed to watch directory"); watcher.unwatch("dir1").expect("failed to unwatch directory"); @@ -116,7 +116,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("file1", RecursiveMode::Recursive).expect("failed to watch file"); watcher.unwatch("file1").expect("failed to unwatch file"); @@ -137,7 +137,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("dir1", RecursiveMode::Recursive).expect("failed to watch directory"); watcher.unwatch("dir1").expect("failed to unwatch directory"); @@ -158,7 +158,7 @@ fn watch_relative() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch("file1", RecursiveMode::Recursive).expect("failed to watch file"); watcher.unwatch("file1").expect("failed to unwatch file"); @@ -184,7 +184,7 @@ fn watch_absolute_network_directory() { tdir.create("dir1"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("dir1"), RecursiveMode::Recursive).expect("failed to watch directory"); watcher.unwatch(tdir.mkpath("dir1")).expect("failed to unwatch directory"); @@ -211,7 +211,7 @@ fn watch_absolute_network_file() { env::set_current_dir(tdir.path()).expect("failed to change working directory"); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch file"); watcher.unwatch(tdir.mkpath("file1")).expect("failed to unwatch file"); @@ -239,7 +239,7 @@ fn inotify_queue_overflow() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); for i in 0..20 { @@ -255,8 +255,8 @@ fn inotify_queue_overflow() { let mut rescan_found = false; while !rescan_found && time::precise_time_s() < deadline { match rx.try_recv() { - Ok(Event{op: Ok(op::RESCAN), ..}) => rescan_found = true, - Ok(Event{op: Err(e), ..}) => panic!("unexpected event err: {:?}", e), + Ok(RawEvent{op: Ok(op::RESCAN), ..}) => rescan_found = true, + Ok(RawEvent{op: Err(e), ..}) => panic!("unexpected event err: {:?}", e), Ok(e) => (), Err(mpsc::TryRecvError::Empty) => (), Err(e) => panic!("unexpected channel err: {:?}", e) @@ -274,7 +274,7 @@ fn watch_recursive_create_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -327,7 +327,7 @@ fn watch_recursive_move() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -393,7 +393,7 @@ fn watch_recursive_move_in() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -445,7 +445,7 @@ fn watch_recursive_move_out() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -497,7 +497,7 @@ fn watch_nonrecursive() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("."), RecursiveMode::NonRecursive).expect("failed to watch directory"); sleep_windows(100); @@ -535,7 +535,7 @@ fn watch_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -641,6 +641,12 @@ fn poll_watch_recursive_move() { } } +// Windows: +// thread 'poll_watch_recursive_move' panicked at 'assertion failed: `(left == right)` (left: `[("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1a", REMOVE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1a\\file1", REMOVE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b\\file1", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b\\file2", CREATE, None)]`, right: `[("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1a", REMOVE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1a\\file1", REMOVE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b\\file1", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.wgdpV6G3MTdr\\dir1b\\file2", CREATE, None)]`)', tests\watcher.rs:623 + +// Windows: +// thread 'poll_watch_recursive_move' panicked at 'unexpected event err: Io(Error { repr: Os { code: 3, message: "The system cannot find the path specified." } })', tests\utils/mod.rs:31 + #[test] fn poll_watch_recursive_move_in() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); @@ -680,6 +686,9 @@ fn poll_watch_recursive_move_in() { } } +// Windows (2x): +// thread 'poll_watch_recursive_move_in' panicked at 'assertion failed: `(left == right)` (left: `[("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b\\dir1", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b\\dir1\\file1", CREATE, None)]`, right: `[("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b\\dir1", CREATE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b\\dir1", WRITE, None), ("\\\\?\\C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\temp_dir.4kipVVht1gD2\\watch_dir\\dir1b\\dir1\\file1", CREATE, None)]`)', tests\watcher.rs:666 + #[test] fn poll_watch_recursive_move_out() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); @@ -720,6 +729,9 @@ fn poll_watch_recursive_move_out() { ]); } +// Windows: +// thread 'poll_watch_recursive_move_out' panicked at 'failed to rename file or directory: Error { repr: Os { code: 5, message: "Access is denied." } }', ../src/libcore\result.rs:788 + #[test] fn poll_watch_nonrecursive() { let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); @@ -781,7 +793,7 @@ fn watch_nonexisting() { sleep_macos(10); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch file"); } @@ -796,7 +808,7 @@ fn unwatch_file() { sleep_macos(10); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch file"); match watcher.unwatch(&tdir.mkpath("file1")) { @@ -816,7 +828,7 @@ fn unwatch_directory() { sleep_macos(10); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("dir1"), RecursiveMode::Recursive).expect("failed to watch directory"); match watcher.unwatch(&tdir.mkpath("dir1")) { @@ -833,7 +845,7 @@ fn unwatch_nonexisting() { sleep_macos(10); let (tx, _) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); match watcher.unwatch(&tdir.mkpath("file1")) { Err(Error::WatchNotFound) => (), @@ -853,7 +865,7 @@ fn self_delete_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch file"); sleep_windows(100); @@ -906,7 +918,7 @@ fn self_delete_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("dir1"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -970,7 +982,7 @@ fn self_rename_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch file"); sleep_windows(100); @@ -1050,7 +1062,7 @@ fn self_rename_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("dir1"), RecursiveMode::Recursive).expect("failed to watch directory"); sleep_windows(100); @@ -1142,7 +1154,7 @@ fn parent_rename_file() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("dir1/file1"), RecursiveMode::Recursive).expect("failed to watch file"); sleep_windows(100); @@ -1218,7 +1230,7 @@ fn parent_rename_directory() { sleep_macos(10); let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); + let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).expect("failed to create recommended watcher"); watcher.watch(&tdir.mkpath("dir1/watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); tdir.rename("dir1", "dir2"); diff --git a/tests/windows.rs b/tests/windows.rs index 604f3646..1bbbe793 100644 --- a/tests/windows.rs +++ b/tests/windows.rs @@ -13,7 +13,7 @@ mod windows_tests { use std::time::Duration; use std::sync::mpsc; - fn wait_for_disconnect(rx: &mpsc::Receiver) { + fn wait_for_disconnect(rx: &mpsc::Receiver) { loop { match rx.try_recv() { Err(mpsc::TryRecvError::Disconnected) => break,