forked from extern/nushell
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:
@ -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(
|
||||
|
Reference in New Issue
Block a user