aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_vfs/Cargo.toml1
-rw-r--r--crates/ra_vfs/src/watcher.rs26
2 files changed, 18 insertions, 9 deletions
diff --git a/crates/ra_vfs/Cargo.toml b/crates/ra_vfs/Cargo.toml
index 58196555c..b77b7139f 100644
--- a/crates/ra_vfs/Cargo.toml
+++ b/crates/ra_vfs/Cargo.toml
@@ -14,6 +14,7 @@ log = "0.4.6"
14notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" } 14notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" }
15ignore = "0.4" 15ignore = "0.4"
16drop_bomb = "0.1.0" 16drop_bomb = "0.1.0"
17parking_lot = "0.7.0"
17 18
18thread_worker = { path = "../thread_worker" } 19thread_worker = { path = "../thread_worker" }
19ra_arena = { path = "../ra_arena" } 20ra_arena = { path = "../ra_arena" }
diff --git a/crates/ra_vfs/src/watcher.rs b/crates/ra_vfs/src/watcher.rs
index 013611e1a..9d552f886 100644
--- a/crates/ra_vfs/src/watcher.rs
+++ b/crates/ra_vfs/src/watcher.rs
@@ -3,15 +3,16 @@ use crossbeam_channel::Sender;
3use drop_bomb::DropBomb; 3use drop_bomb::DropBomb;
4use ignore; 4use ignore;
5use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; 5use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
6use parking_lot::Mutex;
6use std::{ 7use std::{
7 path::{Path, PathBuf}, 8 path::{Path, PathBuf},
8 sync::{mpsc, Arc, Mutex}, 9 sync::{mpsc, Arc},
9 thread, 10 thread,
10 time::Duration, 11 time::Duration,
11}; 12};
12 13
13pub struct Watcher { 14pub struct Watcher {
14 watcher: Arc<Mutex<RecommendedWatcher>>, 15 watcher: Arc<Mutex<Option<RecommendedWatcher>>>,
15 thread: thread::JoinHandle<()>, 16 thread: thread::JoinHandle<()>,
16 bomb: DropBomb, 17 bomb: DropBomb,
17} 18}
@@ -27,7 +28,7 @@ pub enum WatcherChange {
27fn handle_change_event( 28fn handle_change_event(
28 ev: DebouncedEvent, 29 ev: DebouncedEvent,
29 sender: &Sender<io::Task>, 30 sender: &Sender<io::Task>,
30 watcher: &Arc<Mutex<RecommendedWatcher>>, 31 watcher: &Arc<Mutex<Option<RecommendedWatcher>>>,
31) -> Result<(), Box<std::error::Error>> { 32) -> Result<(), Box<std::error::Error>> {
32 match ev { 33 match ev {
33 DebouncedEvent::NoticeWrite(_) 34 DebouncedEvent::NoticeWrite(_)
@@ -69,16 +70,23 @@ fn watch_one(watcher: &mut RecommendedWatcher, path: &Path) {
69 } 70 }
70} 71}
71 72
72fn watch_recursive(watcher: &Arc<Mutex<RecommendedWatcher>>, path: &Path) { 73fn watch_recursive(watcher: &Arc<Mutex<Option<RecommendedWatcher>>>, path: &Path) {
73 log::debug!("watch_recursive \"{}\"", path.display()); 74 log::debug!("watch_recursive \"{}\"", path.display());
74 let mut w = watcher.lock().unwrap(); 75 let mut watcher = watcher.lock();
76 let mut watcher = match *watcher {
77 Some(ref mut watcher) => watcher,
78 None => {
79 // watcher has been dropped
80 return;
81 }
82 };
75 // TODO it seems path itself isn't checked against ignores 83 // TODO it seems path itself isn't checked against ignores
76 // check if path should be ignored before walking it 84 // check if path should be ignored before walking it
77 for res in ignore::Walk::new(path) { 85 for res in ignore::Walk::new(path) {
78 match res { 86 match res {
79 Ok(entry) => { 87 Ok(entry) => {
80 if entry.path().is_dir() { 88 if entry.path().is_dir() {
81 watch_one(&mut w, entry.path()); 89 watch_one(&mut watcher, entry.path());
82 } 90 }
83 } 91 }
84 Err(e) => log::warn!("watcher error: {}", e), 92 Err(e) => log::warn!("watcher error: {}", e),
@@ -91,10 +99,10 @@ impl Watcher {
91 output_sender: Sender<io::Task>, 99 output_sender: Sender<io::Task>,
92 ) -> Result<Watcher, Box<std::error::Error>> { 100 ) -> Result<Watcher, Box<std::error::Error>> {
93 let (input_sender, input_receiver) = mpsc::channel(); 101 let (input_sender, input_receiver) = mpsc::channel();
94 let watcher = Arc::new(Mutex::new(notify::watcher( 102 let watcher = Arc::new(Mutex::new(Some(notify::watcher(
95 input_sender, 103 input_sender,
96 Duration::from_millis(250), 104 Duration::from_millis(250),
97 )?)); 105 )?)));
98 let w = watcher.clone(); 106 let w = watcher.clone();
99 let thread = thread::spawn(move || { 107 let thread = thread::spawn(move || {
100 input_receiver 108 input_receiver
@@ -116,7 +124,7 @@ impl Watcher {
116 124
117 pub fn shutdown(mut self) -> thread::Result<()> { 125 pub fn shutdown(mut self) -> thread::Result<()> {
118 self.bomb.defuse(); 126 self.bomb.defuse();
119 drop(self.watcher); 127 drop(self.watcher.lock().take());
120 let res = self.thread.join(); 128 let res = self.thread.join();
121 match &res { 129 match &res {
122 Ok(()) => log::info!("... Watcher terminated with ok"), 130 Ok(()) => log::info!("... Watcher terminated with ok"),