dependency: use notify-debouncer-full(based on notify v6) instead of notify v4 (#9606)

# Description

Closes: #9324

I have done some manually test locally on MacOS, and it seems fine for
me.

cc: @rgwood
This commit is contained in:
WindSoilder
2023-07-05 20:14:55 +08:00
committed by GitHub
parent 168e7f7b16
commit 406b606398
3 changed files with 158 additions and 217 deletions

View File

@ -2,7 +2,13 @@ use std::path::PathBuf;
use std::sync::mpsc::{channel, RecvTimeoutError};
use std::time::Duration;
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use notify_debouncer_full::{
new_debouncer,
notify::{
event::{DataChange, ModifyKind, RenameMode},
EventKind, RecursiveMode, Watcher,
},
};
use nu_engine::{current_dir, eval_block, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Closure, Command, EngineState, Stack, StateWorkingSet};
@ -144,18 +150,21 @@ impl Command for Watch {
let ctrlc_ref = &engine_state.ctrlc.clone();
let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = match Watcher::new(tx, debounce_duration) {
Ok(w) => w,
let mut debouncer = match new_debouncer(debounce_duration, None, tx) {
Ok(d) => d,
Err(e) => {
return Err(ShellError::IOError(format!(
"Failed to create watcher: {e}"
)))
}
};
if let Err(e) = watcher.watch(path.clone(), recursive_mode) {
return Err(ShellError::IOError(format!("Failed to start watcher: {e}")));
if let Err(e) = debouncer.watcher().watch(&path, recursive_mode) {
return Err(ShellError::IOError(format!(
"Failed to create watcher: {e}"
)));
}
// need to cache to make sure that rename event works.
debouncer.cache().add_root(&path, recursive_mode);
eprintln!("Now watching files at {path:?}. Press ctrl+c to abort.");
@ -225,30 +234,48 @@ impl Command for Watch {
loop {
match rx.recv_timeout(CHECK_CTRL_C_FREQUENCY) {
Ok(event) => {
Ok(Ok(events)) => {
if verbose {
eprintln!("{event:?}");
eprintln!("{events:?}");
}
let handler_result = match event {
DebouncedEvent::Create(path) => event_handler("Create", path, None),
DebouncedEvent::Write(path) => event_handler("Write", path, None),
DebouncedEvent::Remove(path) => event_handler("Remove", path, None),
DebouncedEvent::Rename(path, new_path) => {
event_handler("Rename", path, Some(new_path))
}
DebouncedEvent::Error(err, path) => match path {
Some(path) => Err(ShellError::IOError(format!(
"Error detected for {path:?}: {err:?}"
))),
None => Err(ShellError::IOError(format!("Error detected: {err:?}"))),
},
// These are less likely to be interesting events
DebouncedEvent::Chmod(_)
| DebouncedEvent::NoticeRemove(_)
| DebouncedEvent::NoticeWrite(_)
| DebouncedEvent::Rescan => Ok(()),
};
handler_result?;
for mut one_event in events {
let handle_result = match one_event.event.kind {
// only want to handle event if relative path exists.
EventKind::Create(_) => one_event
.paths
.pop()
.map(|path| event_handler("Create", path, None))
.unwrap_or(Ok(())),
EventKind::Remove(_) => one_event
.paths
.pop()
.map(|path| event_handler("Remove", path, None))
.unwrap_or(Ok(())),
EventKind::Modify(ModifyKind::Data(DataChange::Content)) => one_event
.paths
.pop()
.map(|path| event_handler("Write", path, None))
.unwrap_or(Ok(())),
EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => one_event
.paths
.pop()
.map(|to| {
one_event
.paths
.pop()
.map(|from| event_handler("Rename", from, Some(to)))
.unwrap_or(Ok(()))
})
.unwrap_or(Ok(())),
_ => Ok(()),
};
handle_result?;
}
}
Ok(Err(_)) => {
return Err(ShellError::IOError(
"Unexpected errors when receiving events".into(),
))
}
Err(RecvTimeoutError::Disconnected) => {
return Err(ShellError::IOError(