diff --git a/Cargo.lock b/Cargo.lock index 64c461b..3754984 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,15 @@ dependencies = [ "instant", ] +[[package]] +name = "file-id" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13be71e6ca82e91bc0cb862bebaac0b2d1924a5a1d970c822b2f98b63fda8c3" +dependencies = [ + "winapi-util", +] + [[package]] name = "filetime" version = "0.2.20" @@ -1246,9 +1255,9 @@ dependencies = [ [[package]] name = "notify" -version = "5.1.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51" dependencies = [ "bitflags", "crossbeam-channel", @@ -1259,7 +1268,20 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys 0.42.0", + "windows-sys 0.45.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416969970ec751a5d702a88c6cd19ac1332abe997fce43f96db0418550426241" +dependencies = [ + "crossbeam-channel", + "file-id", + "notify", + "parking_lot", + "walkdir", ] [[package]] @@ -1500,7 +1522,7 @@ dependencies = [ "itertools", "log", "nom", - "notify", + "notify-debouncer-full", "rust_search", "scopeguard", "serde", diff --git a/Cargo.toml b/Cargo.toml index 6e76d30..e1bf002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ ignore = "0.4.20" itertools = "0.10.5" log = { version = "0.4.17", features = ["serde"] } nom = "7.1.3" -notify = "5.1.0" +notify-debouncer-full = "0.2.0" rust_search = "2.1.0" scopeguard = "1.1.0" serde = { version = "1.0.158", features = ["derive"] } diff --git a/src/external_event/refresh.rs b/src/external_event/refresh.rs index 0c7e82c..9f78f2e 100644 --- a/src/external_event/refresh.rs +++ b/src/external_event/refresh.rs @@ -1,7 +1,11 @@ use super::{ExternalEvent, RefreshData}; use anyhow::Result; use crossbeam_channel::{unbounded, Sender}; -use notify::{recommended_watcher, Config, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; +use notify_debouncer_full::{ + new_debouncer, + notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher}, + DebounceEventResult, Debouncer, FileIdMap, +}; use std::{ path::{Path, PathBuf}, sync::{ @@ -65,49 +69,56 @@ impl ChangeBuffer { pub fn fs_watch( path: &Path, event_sender: Sender, - refresh_time: u64, + _refresh_time: u64, is_suspended: Arc, -) -> Result<(RecommendedWatcher, ChangeBuffer)> { +) -> Result<(Debouncer, ChangeBuffer)> { let (tx, rx) = unbounded(); - let mut watcher = recommended_watcher(tx)?; - watcher.configure(Config::default().with_poll_interval(Duration::from_millis(refresh_time)))?; - watcher.watch(path, RecursiveMode::Recursive)?; + let mut watcher = { + let event_sender = event_sender.clone(); + new_debouncer( + Duration::from_secs(2), + None, + move |result: DebounceEventResult| match result { + Ok(events) => { + for event in events { + tx.send(event.event).unwrap(); + } + } + Err(errs) => { + for err in errs { + event_sender.send(ExternalEvent::Error(err.into())).unwrap(); + } + } + }, + )? + }; + watcher.watcher().watch(path, RecursiveMode::Recursive)?; let buffer = ChangeBuffer::new(); let mut thread_buffer = buffer.clone(); thread::spawn(move || { - for res in rx { - let send_result: Result<()> = match res { - Ok(event) => match event.kind { - EventKind::Create(_) => { - if is_suspended.load(Ordering::Acquire) { - thread_buffer.add_created(event.paths); - Ok(()) - } else { - let data = ExternalEvent::PartialRefresh( - event.paths.into_iter().map(RefreshData::Add).collect(), - ); - event_sender.send(data).map_err(Into::into) - } + for event in rx { + match event.kind { + EventKind::Create(_) => { + if is_suspended.load(Ordering::Acquire) { + thread_buffer.add_created(event.paths); + } else { + let data = ExternalEvent::PartialRefresh( + event.paths.into_iter().map(RefreshData::Add).collect(), + ); + event_sender.send(data).unwrap(); } - EventKind::Remove(_) => { - if is_suspended.load(Ordering::Acquire) { - thread_buffer.add_removed(event.paths); - Ok(()) - } else { - let data = ExternalEvent::PartialRefresh( - event.paths.into_iter().map(RefreshData::Delete).collect(), - ); - event_sender.send(data).map_err(Into::into) - } + } + EventKind::Remove(_) => { + if is_suspended.load(Ordering::Acquire) { + thread_buffer.add_removed(event.paths); + } else { + let data = ExternalEvent::PartialRefresh( + event.paths.into_iter().map(RefreshData::Delete).collect(), + ); + event_sender.send(data).unwrap(); } - _ => Ok(()), - }, - Err(e) => Err(e.into()), - }; - if let Err(err) = send_result { - event_sender - .send(ExternalEvent::Error(err)) - .expect("sender should not have deallocated"); + } + _ => {} } } });