Skip to content

Commit

Permalink
add PollWatcher scan events
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpr03 committed Jul 13, 2023
1 parent 7da85a9 commit 569692f
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions notify/src/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::{
use data::{DataBuilder, WatchData};
mod data {
use crate::{
event::{CreateKind, DataChange, Event, EventKind, MetadataKind, ModifyKind, RemoveKind},
event::{CreateKind, DataChange, Event, EventKind, MetadataKind, ModifyKind, RemoveKind, EventAttributes},
EventHandler,
};
use filetime::FileTime;
Expand All @@ -37,6 +37,7 @@ mod data {
/// Builder for [`WatchData`] & [`PathData`].
pub(super) struct DataBuilder {
emitter: EventEmitter,
scan_emitter: Option<EventEmitter>,

// TODO: May allow user setup their custom BuildHasher / BuildHasherDefault
// in future.
Expand All @@ -47,12 +48,13 @@ mod data {
}

impl DataBuilder {
pub(super) fn new<F>(event_handler: F, compare_content: bool) -> Self
pub(super) fn new<F>(event_handler: F, compare_content: bool, scan_emitter: Option<F>) -> Self
where
F: EventHandler,
{
Self {
emitter: EventEmitter::new(event_handler),
scan_emitter: scan_emitter.map(EventEmitter::new),
build_hasher: compare_content.then(RandomState::default),
now: Instant::now(),
}
Expand Down Expand Up @@ -192,6 +194,7 @@ mod data {
root: PathBuf,
is_recursive: bool,
) -> impl Iterator<Item = (PathBuf, PathData)> + '_ {
log::trace!("rescanning {root:?}");
// WalkDir return only one entry if root is a file (not a folder),
// so we can use single logic to do the both file & dir's jobs.
//
Expand All @@ -212,11 +215,26 @@ mod data {
// propagate to event handler. It may not consistent.
//
// FIXME: Should we emit all IO error events? Or ignore them all?
.filter_map(|entry| entry.ok())
.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));
None
}
}
})
.filter_map(|entry| match entry.metadata() {
Ok(metadata) => {
let path = entry.into_path();

// emit initial scans
if let Some(emitter) = &data_builder.scan_emitter {
emitter.emit(Ok(Event { kind: EventKind::Create(CreateKind::File), paths: vec![path.clone()], attrs: EventAttributes::new() }));
}
let meta_path = MetaPath::from_parts_unchecked(path, metadata);
let data_path = data_builder.build_path_data(&meta_path);

Expand Down Expand Up @@ -409,7 +427,14 @@ pub struct PollWatcher {
impl PollWatcher {
/// Create a new [PollWatcher], configured as needed.
pub fn new<F: EventHandler>(event_handler: F, config: Config) -> crate::Result<PollWatcher> {
let data_builder = DataBuilder::new(event_handler, config.compare_contents());
Self::with_initial_scan::<_,>(event_handler, config, None)
}

/// Crate a new [PollWatcher] with an event handler called on the initial scan with all files seen by the pollwatcher.
///
/// `scan_fallback` is called on the initial scan and rescans
pub fn with_initial_scan<F: EventHandler>(event_handler: F, config: Config, scan_callback: Option<F>) -> crate::Result<PollWatcher> {
let data_builder = DataBuilder::new(event_handler, config.compare_contents(), scan_callback);

let poll_watcher = PollWatcher {
watches: Default::default(),
Expand Down

0 comments on commit 569692f

Please sign in to comment.