Skip to content

Commit

Permalink
replace old config and allow initialization configuration
Browse files Browse the repository at this point in the history
This also allows correct configuration of PollWatcher via notify-debouncer-mini
  • Loading branch information
0xpr03 committed Aug 10, 2022
1 parent ae9134c commit 9dc36f4
Show file tree
Hide file tree
Showing 17 changed files with 128 additions and 115 deletions.
4 changes: 4 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ path = "monitor_raw.rs"
name = "debounced"
path = "debounced.rs"

[[example]]
name = "debounced_custom"
path = "debounced_full_custom.rs"

[[example]]
name = "poll_sysfs"
path = "poll_sysfs.rs"
Expand Down
4 changes: 2 additions & 2 deletions examples/async_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use futures::{
channel::mpsc::{channel, Receiver},
SinkExt, StreamExt,
};
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher};
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher, Config};
use std::path::Path;

/// Async, futures channel based event watching
Expand All @@ -28,7 +28,7 @@ fn async_watcher() -> notify::Result<(RecommendedWatcher, Receiver<notify::Resul
futures::executor::block_on(async {
tx.send(res).await.unwrap();
})
})?;
}, Config::default())?;

Ok((watcher, rx))
}
Expand Down
2 changes: 1 addition & 1 deletion examples/debounced.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{path::Path, time::Duration};

use notify::{RecursiveMode, Watcher};
use notify::{RecursiveMode};
use notify_debouncer_mini::new_debouncer;

/// Example for debouncer
Expand Down
6 changes: 3 additions & 3 deletions examples/debounced_full_custom.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{path::Path, time::Duration};

use notify::{RecursiveMode, Watcher};
use notify_debouncer_mini::new_debouncer;
use notify::{RecursiveMode, Config};
use notify_debouncer_mini::new_debouncer_opt;

/// Debouncer with custom backend and waiting for exit
fn main() {
Expand All @@ -18,7 +18,7 @@ fn main() {
// setup debouncer
let (tx, rx) = std::sync::mpsc::channel();
// select backend via fish operator, here PollWatcher backend
let mut debouncer = new_debouncer_opt::<_,notify::PollWatcher>(Duration::from_secs(2), None, tx).unwrap();
let mut debouncer = new_debouncer_opt::<_,notify::PollWatcher>(Duration::from_secs(2), None, tx, Config::default()).unwrap();

debouncer
.watcher()
Expand Down
2 changes: 1 addition & 1 deletion examples/hot_reload_tide/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async fn main() -> tide::Result<()> {
Err(error) => println!("Error reloading config: {:?}", error),
}
}
})?;
},notify::Config::default())?;

watcher.watch(Path::new(CONFIG_PATH), RecursiveMode::Recursive)?;

Expand Down
4 changes: 2 additions & 2 deletions examples/monitor_raw.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use notify::{RecommendedWatcher, RecursiveMode, Watcher, Config};
use std::path::Path;

fn main() {
Expand All @@ -16,7 +16,7 @@ fn watch<P: AsRef<Path>>(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::new(tx)?;
let mut watcher = RecommendedWatcher::new(tx, Config::default())?;

// Add a path to be watched. All files and directories at that path and
// below will be monitored for changes.
Expand Down
12 changes: 5 additions & 7 deletions examples/poll_sysfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
/// This example can't be demonstrated under windows, it might be relevant for network shares
#[cfg(not(target_os = "windows"))]
fn not_windows_main() -> notify::Result<()> {
use notify::poll::PollWatcherConfig;
use notify::{PollWatcher, RecursiveMode, Watcher};
use notify::{PollWatcher, RecursiveMode, Watcher, Config};
use std::path::Path;
use std::time::Duration;

Expand All @@ -27,13 +26,12 @@ fn not_windows_main() -> notify::Result<()> {

println!("watching {:?}...", paths);
// configure pollwatcher backend
let config = PollWatcherConfig {
compare_contents: true, // crucial part for pseudo filesystems
poll_interval: Duration::from_secs(2),
};
let config = Config::default()
.with_compare_contents(true) // crucial part for pseudo filesystems
.with_poll_interval(Duration::from_secs(2));
let (tx, rx) = std::sync::mpsc::channel();
// create pollwatcher backend
let mut watcher = PollWatcher::with_config(tx, config)?;
let mut watcher = PollWatcher::new(tx, config)?;
for path in paths {
// watch all paths
watcher.watch(&path, RecursiveMode::Recursive)?;
Expand Down
16 changes: 9 additions & 7 deletions examples/watcher_kind.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use std::{path::Path, time::Duration};
use notify::*;

use notify::{poll::PollWatcherConfig, *};
// exampale of detecting the recommended watcher kind
fn main() {
let (tx, rx) = std::sync::mpsc::channel();
// This example is a little bit misleading as you can just create one Config and use it for all watchers.
// That way the pollwatcher specific stuff is still configured, if it should be used.
let mut watcher: Box<dyn Watcher> = if RecommendedWatcher::kind() == WatcherKind::PollWatcher {
// custom config for PollWatcher kind
let config = PollWatcherConfig {
poll_interval: Duration::from_secs(1),
..Default::default()
};
Box::new(PollWatcher::with_config(tx, config).unwrap())
// you
let config = Config::default()
.with_poll_interval(Duration::from_secs(1));
Box::new(PollWatcher::new(tx, config).unwrap())
} else {
// use default config for everything else
Box::new(RecommendedWatcher::new(tx).unwrap())
Box::new(RecommendedWatcher::new(tx, Config::default()).unwrap())
};

// watch some stuff
Expand Down
17 changes: 10 additions & 7 deletions notify-debouncer-mini/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//!
//! ```toml
//! [dependencies]
//! notify = "5.0.0-pre.15"
//! notify-debouncer-mini = "0.1"
//! ```
//!
Expand All @@ -13,18 +12,20 @@
//! ```rust,no_run
//! # use std::path::Path;
//! # use std::time::Duration;
//! use notify::{Watcher, RecursiveMode, Result};
//! use notify_debouncer_mini::{new_debouncer,DebounceEventResult};
//! use notify_debouncer_mini::{notify:*,new_debouncer,DebounceEventResult};
//!
//! # fn main() {
//! // setup initial watcher backend config
//! let config = Config::default();
//!
//! // Select recommended watcher for debouncer.
//! // Using a callback here, could also be a channel.
//! let mut debouncer = new_debouncer(Duration::from_secs(2), None, |res: DebounceEventResult| {
//! match res {
//! Ok(events) => events.iter().for_each(|e|println!("Event {:?} for {:?}",e.kind,e.path)),
//! Err(errors) => errors.iter().for_each(|e|println!("Error {:?}",e)),
//! }
//! }).unwrap();
//! },config).unwrap();
//!
//! // Add a path to be watched. All files and directories at that path and
//! // below will be monitored for changes.
Expand All @@ -50,6 +51,7 @@ use std::{
time::{Duration, Instant},
};

pub use notify;
use notify::{Error, ErrorKind, Event, RecommendedWatcher, Watcher};

/// The set of requirements for watcher debounce event handling functions.
Expand Down Expand Up @@ -259,6 +261,7 @@ pub fn new_debouncer_opt<F: DebounceEventHandler, T: Watcher>(
timeout: Duration,
tick_rate: Option<Duration>,
mut event_handler: F,
config: notify::Config
) -> Result<Debouncer<T>, Error> {
let data = DebounceData::default();

Expand Down Expand Up @@ -320,7 +323,7 @@ pub fn new_debouncer_opt<F: DebounceEventHandler, T: Watcher>(
// can't have multiple TX, so we need to pipe that through our debouncer
Err(e) => lock.add_error(e),
}
})?;
}, config)?;

let guard = Debouncer {
watcher,
Expand All @@ -339,7 +342,7 @@ pub fn new_debouncer_opt<F: DebounceEventHandler, T: Watcher>(
pub fn new_debouncer<F: DebounceEventHandler>(
timeout: Duration,
tick_rate: Option<Duration>,
event_handler: F,
event_handler: F
) -> Result<Debouncer<RecommendedWatcher>, Error> {
new_debouncer_opt::<F, RecommendedWatcher>(timeout, tick_rate, event_handler)
new_debouncer_opt::<F, RecommendedWatcher>(timeout, tick_rate, event_handler, notify::Config::default())
}
105 changes: 67 additions & 38 deletions notify/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,71 @@ impl RecursiveMode {
}
}

/// Runtime configuration items for watchers.
///
/// See the [`Watcher::configure`](../trait.Watcher.html#tymethod.configure) method for usage.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Config {
/// Enable or disable emitting precise event classification.
///
/// Applicable to all watchers.
///
/// When enabled, events are emitted with a `kind` set to as much precision about what kind of
/// event they are as the backend is capable of providing. When disabled (default), events are
/// instead emitted as `EventKind::Any`. `EventKind::Other` meta-events are left alone.
PreciseEvents(bool),

/// Enable or disable emitting `Notice` events.
///
/// Applicable to debounced watchers only.
///
/// When enabled, the first modify or remove event for a path is emitted immediately with a
/// [`Flag::Notice`](../event/enum.Flag.html) attribute within a debouncing period, enabling
/// applications to respond more quickly.
NoticeEvents(bool),

/// Enable or disable emitting `Ongoing` events.
///
/// Applicable to debounced watchers only.
///
/// When enabled, partial write events that are received after a `Modify(Data)` Notice but
/// before the end of a debouncing period (and the emission of a `Modify(Data)` event) are
/// passed through as `Modify(Data)` events with an `Ongoing` flag. These events are still
/// debounced, but at a lower (configurable) interval than the debouncing interval.
///
/// To enable, provide `Some(Duration)`. To disable, provide `None`.
///
/// # Errors
///
/// - `InvalidConfigValue` if the interval provided is higher than the debounce interval.
OngoingEvents(Option<Duration>),
/// Backend configuration
///
/// This contains multiple settings that may relate to only one specific backend,
/// such as to correctly configure each backend regardless of what is selected during runtime.
///
/// ```rust
/// # use std::time::Duration;
/// let config = BackendConfig::default()
/// .with_poll_intervall(Duration::from_secs(2))
/// .with_compare_contents(true);
/// ```
///
/// Some options can be changed during runtime, others have to be set when creating the watcher backend.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Config {
/// See [BackendConfig::with_poll_interval]
poll_interval: Duration,

/// See [BackendConfig::with_compare_contents]
compare_contents: bool,
}

impl Config {
/// For [crate::PollWatcher]
///
/// Interval between each rescan attempt. This can be extremely expensive for large
/// file trees so it is recommended to measure and tune accordingly.
///
/// The default poll frequency is 30 seconds.
pub fn with_poll_interval(mut self, dur: Duration) -> Self {
self.poll_interval = dur;
self
}

/// Returns current setting
pub fn poll_interval(&self) -> Duration {
self.poll_interval
}

/// For [crate::PollWatcher]
///
/// Optional feature that will evaluate the contents of changed files to determine if
/// they have indeed changed using a fast hashing algorithm. This is especially important
/// for pseudo filesystems like those on Linux under /sys and /proc which are not obligated
/// to respect any other filesystem norms such as modification timestamps, file sizes, etc.
/// By enabling this feature, performance will be significantly impacted as all files will
/// need to be read and hashed at each `poll_interval`.
///
/// This can't be changed during runtime. Off by default.
pub fn with_compare_contents(mut self, compare_contents: bool) -> Self {
self.compare_contents = compare_contents;
self
}

/// Returns current setting
pub fn compare_contents(&self) -> bool {
self.compare_contents
}
}

impl Default for Config {
fn default() -> Self {
Self {
poll_interval: Duration::from_secs(30),
compare_contents: false
}
}
}
2 changes: 1 addition & 1 deletion notify/src/fsevent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ unsafe fn callback_impl(

impl Watcher for FsEventWatcher {
/// Create a new watcher.
fn new<F: EventHandler>(event_handler: F) -> Result<Self> {
fn new<F: EventHandler>(event_handler: F, _config: Config) -> Result<Self> {
Self::from_event_handler(Arc::new(Mutex::new(event_handler)))
}

Expand Down
2 changes: 1 addition & 1 deletion notify/src/inotify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ impl INotifyWatcher {

impl Watcher for INotifyWatcher {
/// Create a new watcher.
fn new<F: EventHandler>(event_handler: F) -> Result<Self> {
fn new<F: EventHandler>(event_handler: F, _config: Config) -> Result<Self> {
Self::from_event_handler(Box::new(event_handler))
}

Expand Down
4 changes: 2 additions & 2 deletions notify/src/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! pieces of kernel code termed filters.

use super::event::*;
use super::{Error, EventHandler, RecursiveMode, Result, Watcher};
use super::{Error, EventHandler, RecursiveMode, Result, Watcher, Config};
use crate::{unbounded, Receiver, Sender};
use kqueue::{EventData, EventFilter, FilterFlag, Ident};
use std::collections::HashMap;
Expand Down Expand Up @@ -405,7 +405,7 @@ impl KqueueWatcher {

impl Watcher for KqueueWatcher {
/// Create a new watcher.
fn new<F: EventHandler>(event_handler: F) -> Result<Self> {
fn new<F: EventHandler>(event_handler: F, _config: Config) -> Result<Self> {
Self::from_event_handler(Box::new(event_handler))
}

Expand Down
6 changes: 3 additions & 3 deletions notify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ pub enum WatcherKind {
/// In addition to such event driven implementations, a polling implementation is also provided
/// that should work on any platform.
pub trait Watcher {
/// Create a new watcher.
fn new<F: EventHandler>(event_handler: F) -> Result<Self>
/// Create a new watcher with an initial Config.
fn new<F: EventHandler>(event_handler: F, config: config::Config) -> Result<Self>
where
Self: Sized;
/// Begin watching a new path.
Expand Down Expand Up @@ -377,7 +377,7 @@ where
F: EventHandler,
{
// All recommended watchers currently implement `new`, so just call that.
RecommendedWatcher::new(event_handler)
RecommendedWatcher::new(event_handler, Config::default())
}

#[cfg(test)]
Expand Down
8 changes: 7 additions & 1 deletion notify/src/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#![allow(unused_variables)]

use crate::Config;

use super::{RecursiveMode, Result, Watcher};
use std::path::Path;

Expand All @@ -20,13 +22,17 @@ impl Watcher for NullWatcher {
Ok(())
}

fn new<F: crate::EventHandler>(event_handler: F) -> Result<Self>
fn new<F: crate::EventHandler>(event_handler: F, config: Config) -> Result<Self>
where
Self: Sized,
{
Ok(NullWatcher)
}

fn configure(&mut self, config: Config) -> Result<bool> {
Ok(false)
}

fn kind() -> crate::WatcherKind {
crate::WatcherKind::NullWatcher
}
Expand Down
Loading

0 comments on commit 9dc36f4

Please sign in to comment.