From 146b1bd5794e4bd53b112863283f434f63b9a953 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Mon, 26 Aug 2024 18:25:44 +0100 Subject: [PATCH] preservev IO errors in PollWatcher --- notify-types/src/event.rs | 15 ++++++++++++--- notify/src/poll.rs | 37 ++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/notify-types/src/event.rs b/notify-types/src/event.rs index 13159813..43bb07fb 100644 --- a/notify-types/src/event.rs +++ b/notify-types/src/event.rs @@ -195,7 +195,10 @@ pub enum RemoveKind { #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] -#[cfg_attr(all(feature = "serde", not(feature = "serialization-compat-6")), serde(tag = "type"))] +#[cfg_attr( + all(feature = "serde", not(feature = "serialization-compat-6")), + serde(tag = "type") +)] pub enum EventKind { /// The catch-all event kind, for unsupported/unknown events. /// @@ -300,7 +303,10 @@ pub struct Event { /// The `EventKind::Any` variant should be used as the "else" case when mapping native kernel /// bitmasks or bitmaps, such that if the mask is ever extended with new event types the /// backend will not gain bugs due to not matching new unknown event types. - #[cfg_attr(all(feature = "serde", not(feature = "serialization-compat-6")), serde(flatten))] + #[cfg_attr( + all(feature = "serde", not(feature = "serialization-compat-6")), + serde(flatten) + )] pub kind: EventKind, /// Paths the event is about, if known. @@ -478,7 +484,10 @@ impl EventAttributes { /// particular ways. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serde", not(feature = "serialization-compat-6")), serde(rename_all = "camelCase"))] +#[cfg_attr( + all(feature = "serde", not(feature = "serialization-compat-6")), + serde(rename_all = "camelCase") +)] pub enum Flag { /// Rescan notices are emitted by some platforms (and may also be emitted by Notify itself). /// They indicate either a lapse in the events or a change in the filesystem such that events diff --git a/notify/src/poll.rs b/notify/src/poll.rs index 007c178a..830b1ee1 100644 --- a/notify/src/poll.rs +++ b/notify/src/poll.rs @@ -182,7 +182,7 @@ mod data { // FIXME: Can we always allow to watch a path, even file not // found at this path? if let Err(e) = fs::metadata(&root) { - data_builder.emitter.emit_io_err(e, &root); + data_builder.emitter.emit_io_err(e, Some(&root)); return None; } @@ -259,25 +259,19 @@ mod data { .follow_links(true) .max_depth(Self::dir_scan_depth(is_recursive)) .into_iter() - // - // QUESTION: should we ignore IO Error? - // - // current implementation ignore some IO error, e.g., - // - // - `.filter_map(|entry| entry.ok())` - // - all read error when hashing - // - // but the code also interest with `fs::metadata()` error and - // propagate to event handler. It may not consistent. - // - // FIXME: Should we emit all IO error events? Or ignore them all? .filter_map(|entry_res| match entry_res { Ok(entry) => Some(entry), Err(err) => { log::warn!("walkdir error scanning {err:?}"); - let crate_err = - crate::Error::new(crate::ErrorKind::Generic(err.to_string())); - data_builder.emitter.emit(Err(crate_err)); + if let Some(io_error) = err.io_error() { + // clone an io::Error, so we have to create a new one. + let new_io_error = io::Error::new(io_error.kind(), err.to_string()); + data_builder.emitter.emit_io_err(new_io_error, err.path()); + } else { + let crate_err = + crate::Error::new(crate::ErrorKind::Generic(err.to_string())); + data_builder.emitter.emit(Err(crate_err)); + } None } }) @@ -298,7 +292,7 @@ mod data { Err(e) => { // emit event. let path = entry.into_path(); - data_builder.emitter.emit_io_err(e, path); + data_builder.emitter.emit_io_err(e, Some(path)); None } @@ -455,12 +449,17 @@ mod data { } /// Emit io error event. - fn emit_io_err(&self, err: E, path: P) + fn emit_io_err(&self, err: E, path: Option

) where E: Into, P: Into, { - self.emit(Err(crate::Error::io(err.into()).add_path(path.into()))) + let e = crate::Error::io(err.into()); + if let Some(path) = path { + self.emit(Err(e.add_path(path.into()))); + } else { + self.emit(Err(e)); + } } } }