mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 15:14:32 +00:00
handle recursive watching ourselves
This commit is contained in:
parent
e69b620f0d
commit
f181e36a44
4 changed files with 78 additions and 16 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -446,6 +446,18 @@ name = "glob"
|
|||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
|
@ -469,6 +481,23 @@ dependencies = [
|
|||
"unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "im"
|
||||
version = "12.3.0"
|
||||
|
@ -1010,6 +1039,7 @@ dependencies = [
|
|||
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flexi_logger 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 4.0.6 (git+https://github.com/vemoo/notify/?branch=v4-legacy)",
|
||||
"ra_arena 0.1.0",
|
||||
|
@ -1868,9 +1898,11 @@ dependencies = [
|
|||
"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
|
||||
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
|
||||
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
|
||||
"checksum ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ad03ca67dc12474ecd91fdb94d758cbd20cb4e7a78ebe831df26a9b7511e1162"
|
||||
"checksum im 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0627d417829c1d763d602687634869f254fc79f7e22dea6c824dab993db857e4"
|
||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
|
||||
|
|
|
@ -12,6 +12,7 @@ crossbeam-channel = "0.3.5"
|
|||
log = "0.4.6"
|
||||
# until https://github.com/passcod/notify/issues/169 is fixed
|
||||
notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" }
|
||||
ignore = "0.4"
|
||||
drop_bomb = "0.1.0"
|
||||
|
||||
thread_worker = { path = "../thread_worker" }
|
||||
|
|
|
@ -141,9 +141,7 @@ impl Vfs {
|
|||
};
|
||||
res.worker.inp.send(task).unwrap();
|
||||
if let Some(ref mut watcher) = res.watcher {
|
||||
if let Err(e) = watcher.watch(path) {
|
||||
log::warn!("could not watch \"{}\": {}", path.display(), e);
|
||||
}
|
||||
watcher.watch(path);
|
||||
}
|
||||
}
|
||||
let roots = res.roots.iter().map(|(id, _)| id).collect();
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use crate::io;
|
||||
use crossbeam_channel::Sender;
|
||||
use drop_bomb::DropBomb;
|
||||
use ignore;
|
||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc,
|
||||
sync::{mpsc, Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::io;
|
||||
use crossbeam_channel::Sender;
|
||||
use drop_bomb::DropBomb;
|
||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
|
||||
|
||||
pub struct Watcher {
|
||||
watcher: RecommendedWatcher,
|
||||
watcher: Arc<Mutex<RecommendedWatcher>>,
|
||||
thread: thread::JoinHandle<()>,
|
||||
bomb: DropBomb,
|
||||
}
|
||||
|
@ -24,9 +24,10 @@ pub enum WatcherChange {
|
|||
Rescan,
|
||||
}
|
||||
|
||||
fn send_change_events(
|
||||
fn handle_change_event(
|
||||
ev: DebouncedEvent,
|
||||
sender: &Sender<io::Task>,
|
||||
watcher: &Arc<Mutex<RecommendedWatcher>>,
|
||||
) -> Result<(), Box<std::error::Error>> {
|
||||
match ev {
|
||||
DebouncedEvent::NoticeWrite(_)
|
||||
|
@ -38,6 +39,9 @@ fn send_change_events(
|
|||
sender.send(io::Task::HandleChange(WatcherChange::Rescan))?;
|
||||
}
|
||||
DebouncedEvent::Create(path) => {
|
||||
if path.is_dir() {
|
||||
watch_recursive(watcher, &path);
|
||||
}
|
||||
sender.send(io::Task::HandleChange(WatcherChange::Create(path)))?;
|
||||
}
|
||||
DebouncedEvent::Write(path) => {
|
||||
|
@ -58,17 +62,45 @@ fn send_change_events(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn watch_one(watcher: &mut RecommendedWatcher, path: &Path) {
|
||||
match watcher.watch(path, RecursiveMode::NonRecursive) {
|
||||
Ok(()) => log::debug!("watching \"{}\"", path.display()),
|
||||
Err(e) => log::warn!("could not watch \"{}\": {}", path.display(), e),
|
||||
}
|
||||
}
|
||||
|
||||
fn watch_recursive(watcher: &Arc<Mutex<RecommendedWatcher>>, path: &Path) {
|
||||
log::debug!("watch_recursive \"{}\"", path.display());
|
||||
let mut w = watcher.lock().unwrap();
|
||||
// TODO it seems path itself isn't checked against ignores
|
||||
// check if path should be ignored before walking it
|
||||
for res in ignore::Walk::new(path) {
|
||||
match res {
|
||||
Ok(entry) => {
|
||||
if entry.path().is_dir() {
|
||||
watch_one(&mut w, entry.path());
|
||||
}
|
||||
}
|
||||
Err(e) => log::warn!("watcher error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Watcher {
|
||||
pub(crate) fn start(
|
||||
output_sender: Sender<io::Task>,
|
||||
) -> Result<Watcher, Box<std::error::Error>> {
|
||||
let (input_sender, input_receiver) = mpsc::channel();
|
||||
let watcher = notify::watcher(input_sender, Duration::from_millis(250))?;
|
||||
let watcher = Arc::new(Mutex::new(notify::watcher(
|
||||
input_sender,
|
||||
Duration::from_millis(250),
|
||||
)?));
|
||||
let w = watcher.clone();
|
||||
let thread = thread::spawn(move || {
|
||||
input_receiver
|
||||
.into_iter()
|
||||
// forward relevant events only
|
||||
.try_for_each(|change| send_change_events(change, &output_sender))
|
||||
.try_for_each(|change| handle_change_event(change, &output_sender, &w))
|
||||
.unwrap()
|
||||
});
|
||||
Ok(Watcher {
|
||||
|
@ -78,9 +110,8 @@ impl Watcher {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn watch(&mut self, root: impl AsRef<Path>) -> Result<(), Box<std::error::Error>> {
|
||||
self.watcher.watch(root, RecursiveMode::Recursive)?;
|
||||
Ok(())
|
||||
pub fn watch(&mut self, root: impl AsRef<Path>) {
|
||||
watch_recursive(&self.watcher, root.as_ref());
|
||||
}
|
||||
|
||||
pub fn shutdown(mut self) -> thread::Result<()> {
|
||||
|
|
Loading…
Reference in a new issue