aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernardo <[email protected]>2019-01-18 23:53:06 +0000
committerAleksey Kladov <[email protected]>2019-01-26 08:46:27 +0000
commitf181e36a44d1998d3239f09365b16bfea50288a4 (patch)
treeb93c2aca51c5498e9acab866d0fac04a4ef7c5d5
parente69b620f0d1e90afcc14dc7cf07ed0b828d8ec96 (diff)
handle recursive watching ourselves
-rw-r--r--Cargo.lock32
-rw-r--r--crates/ra_vfs/Cargo.toml1
-rw-r--r--crates/ra_vfs/src/lib.rs4
-rw-r--r--crates/ra_vfs/src/watcher.rs57
4 files changed, 78 insertions, 16 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d51146956..2d18122d8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -447,6 +447,18 @@ version = "0.2.11"
447source = "registry+https://github.com/rust-lang/crates.io-index" 447source = "registry+https://github.com/rust-lang/crates.io-index"
448 448
449[[package]] 449[[package]]
450name = "globset"
451version = "0.4.2"
452source = "registry+https://github.com/rust-lang/crates.io-index"
453dependencies = [
454 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
455 "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
456 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
457 "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
458 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
459]
460
461[[package]]
450name = "heck" 462name = "heck"
451version = "0.3.1" 463version = "0.3.1"
452source = "registry+https://github.com/rust-lang/crates.io-index" 464source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -470,6 +482,23 @@ dependencies = [
470] 482]
471 483
472[[package]] 484[[package]]
485name = "ignore"
486version = "0.4.6"
487source = "registry+https://github.com/rust-lang/crates.io-index"
488dependencies = [
489 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
490 "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
491 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
492 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
493 "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
494 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
495 "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
496 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
497 "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
498 "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
499]
500
501[[package]]
473name = "im" 502name = "im"
474version = "12.3.0" 503version = "12.3.0"
475source = "registry+https://github.com/rust-lang/crates.io-index" 504source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1010,6 +1039,7 @@ dependencies = [
1010 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1039 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
1011 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1040 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1012 "flexi_logger 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", 1041 "flexi_logger 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
1042 "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1013 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1043 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1014 "notify 4.0.6 (git+https://github.com/vemoo/notify/?branch=v4-legacy)", 1044 "notify 4.0.6 (git+https://github.com/vemoo/notify/?branch=v4-legacy)",
1015 "ra_arena 0.1.0", 1045 "ra_arena 0.1.0",
@@ -1868,9 +1898,11 @@ dependencies = [
1868"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" 1898"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
1869"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" 1899"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
1870"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" 1900"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
1901"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865"
1871"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 1902"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
1872"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" 1903"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
1873"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 1904"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
1905"checksum ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ad03ca67dc12474ecd91fdb94d758cbd20cb4e7a78ebe831df26a9b7511e1162"
1874"checksum im 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0627d417829c1d763d602687634869f254fc79f7e22dea6c824dab993db857e4" 1906"checksum im 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0627d417829c1d763d602687634869f254fc79f7e22dea6c824dab993db857e4"
1875"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" 1907"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
1876"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" 1908"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
diff --git a/crates/ra_vfs/Cargo.toml b/crates/ra_vfs/Cargo.toml
index 1a21557bf..58196555c 100644
--- a/crates/ra_vfs/Cargo.toml
+++ b/crates/ra_vfs/Cargo.toml
@@ -12,6 +12,7 @@ crossbeam-channel = "0.3.5"
12log = "0.4.6" 12log = "0.4.6"
13# until https://github.com/passcod/notify/issues/169 is fixed 13# until https://github.com/passcod/notify/issues/169 is fixed
14notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" } 14notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" }
15ignore = "0.4"
15drop_bomb = "0.1.0" 16drop_bomb = "0.1.0"
16 17
17thread_worker = { path = "../thread_worker" } 18thread_worker = { path = "../thread_worker" }
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs
index 48a46d210..ad40db340 100644
--- a/crates/ra_vfs/src/lib.rs
+++ b/crates/ra_vfs/src/lib.rs
@@ -141,9 +141,7 @@ impl Vfs {
141 }; 141 };
142 res.worker.inp.send(task).unwrap(); 142 res.worker.inp.send(task).unwrap();
143 if let Some(ref mut watcher) = res.watcher { 143 if let Some(ref mut watcher) = res.watcher {
144 if let Err(e) = watcher.watch(path) { 144 watcher.watch(path);
145 log::warn!("could not watch \"{}\": {}", path.display(), e);
146 }
147 } 145 }
148 } 146 }
149 let roots = res.roots.iter().map(|(id, _)| id).collect(); 147 let roots = res.roots.iter().map(|(id, _)| id).collect();
diff --git a/crates/ra_vfs/src/watcher.rs b/crates/ra_vfs/src/watcher.rs
index dfbbcbfe6..013611e1a 100644
--- a/crates/ra_vfs/src/watcher.rs
+++ b/crates/ra_vfs/src/watcher.rs
@@ -1,17 +1,17 @@
1use crate::io;
2use crossbeam_channel::Sender;
3use drop_bomb::DropBomb;
4use ignore;
5use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
1use std::{ 6use std::{
2 path::{Path, PathBuf}, 7 path::{Path, PathBuf},
3 sync::mpsc, 8 sync::{mpsc, Arc, Mutex},
4 thread, 9 thread,
5 time::Duration, 10 time::Duration,
6}; 11};
7 12
8use crate::io;
9use crossbeam_channel::Sender;
10use drop_bomb::DropBomb;
11use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
12
13pub struct Watcher { 13pub struct Watcher {
14 watcher: RecommendedWatcher, 14 watcher: Arc<Mutex<RecommendedWatcher>>,
15 thread: thread::JoinHandle<()>, 15 thread: thread::JoinHandle<()>,
16 bomb: DropBomb, 16 bomb: DropBomb,
17} 17}
@@ -24,9 +24,10 @@ pub enum WatcherChange {
24 Rescan, 24 Rescan,
25} 25}
26 26
27fn send_change_events( 27fn handle_change_event(
28 ev: DebouncedEvent, 28 ev: DebouncedEvent,
29 sender: &Sender<io::Task>, 29 sender: &Sender<io::Task>,
30 watcher: &Arc<Mutex<RecommendedWatcher>>,
30) -> Result<(), Box<std::error::Error>> { 31) -> Result<(), Box<std::error::Error>> {
31 match ev { 32 match ev {
32 DebouncedEvent::NoticeWrite(_) 33 DebouncedEvent::NoticeWrite(_)
@@ -38,6 +39,9 @@ fn send_change_events(
38 sender.send(io::Task::HandleChange(WatcherChange::Rescan))?; 39 sender.send(io::Task::HandleChange(WatcherChange::Rescan))?;
39 } 40 }
40 DebouncedEvent::Create(path) => { 41 DebouncedEvent::Create(path) => {
42 if path.is_dir() {
43 watch_recursive(watcher, &path);
44 }
41 sender.send(io::Task::HandleChange(WatcherChange::Create(path)))?; 45 sender.send(io::Task::HandleChange(WatcherChange::Create(path)))?;
42 } 46 }
43 DebouncedEvent::Write(path) => { 47 DebouncedEvent::Write(path) => {
@@ -58,17 +62,45 @@ fn send_change_events(
58 Ok(()) 62 Ok(())
59} 63}
60 64
65fn watch_one(watcher: &mut RecommendedWatcher, path: &Path) {
66 match watcher.watch(path, RecursiveMode::NonRecursive) {
67 Ok(()) => log::debug!("watching \"{}\"", path.display()),
68 Err(e) => log::warn!("could not watch \"{}\": {}", path.display(), e),
69 }
70}
71
72fn watch_recursive(watcher: &Arc<Mutex<RecommendedWatcher>>, path: &Path) {
73 log::debug!("watch_recursive \"{}\"", path.display());
74 let mut w = watcher.lock().unwrap();
75 // TODO it seems path itself isn't checked against ignores
76 // check if path should be ignored before walking it
77 for res in ignore::Walk::new(path) {
78 match res {
79 Ok(entry) => {
80 if entry.path().is_dir() {
81 watch_one(&mut w, entry.path());
82 }
83 }
84 Err(e) => log::warn!("watcher error: {}", e),
85 }
86 }
87}
88
61impl Watcher { 89impl Watcher {
62 pub(crate) fn start( 90 pub(crate) fn start(
63 output_sender: Sender<io::Task>, 91 output_sender: Sender<io::Task>,
64 ) -> Result<Watcher, Box<std::error::Error>> { 92 ) -> Result<Watcher, Box<std::error::Error>> {
65 let (input_sender, input_receiver) = mpsc::channel(); 93 let (input_sender, input_receiver) = mpsc::channel();
66 let watcher = notify::watcher(input_sender, Duration::from_millis(250))?; 94 let watcher = Arc::new(Mutex::new(notify::watcher(
95 input_sender,
96 Duration::from_millis(250),
97 )?));
98 let w = watcher.clone();
67 let thread = thread::spawn(move || { 99 let thread = thread::spawn(move || {
68 input_receiver 100 input_receiver
69 .into_iter() 101 .into_iter()
70 // forward relevant events only 102 // forward relevant events only
71 .try_for_each(|change| send_change_events(change, &output_sender)) 103 .try_for_each(|change| handle_change_event(change, &output_sender, &w))
72 .unwrap() 104 .unwrap()
73 }); 105 });
74 Ok(Watcher { 106 Ok(Watcher {
@@ -78,9 +110,8 @@ impl Watcher {
78 }) 110 })
79 } 111 }
80 112
81 pub fn watch(&mut self, root: impl AsRef<Path>) -> Result<(), Box<std::error::Error>> { 113 pub fn watch(&mut self, root: impl AsRef<Path>) {
82 self.watcher.watch(root, RecursiveMode::Recursive)?; 114 watch_recursive(&self.watcher, root.as_ref());
83 Ok(())
84 } 115 }
85 116
86 pub fn shutdown(mut self) -> thread::Result<()> { 117 pub fn shutdown(mut self) -> thread::Result<()> {