diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_vfs/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_vfs/src/watcher.rs | 26 |
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" | |||
14 | notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" } | 14 | notify = { git = "https://github.com/vemoo/notify/", branch = "v4-legacy" } |
15 | ignore = "0.4" | 15 | ignore = "0.4" |
16 | drop_bomb = "0.1.0" | 16 | drop_bomb = "0.1.0" |
17 | parking_lot = "0.7.0" | ||
17 | 18 | ||
18 | thread_worker = { path = "../thread_worker" } | 19 | thread_worker = { path = "../thread_worker" } |
19 | ra_arena = { path = "../ra_arena" } | 20 | ra_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; | |||
3 | use drop_bomb::DropBomb; | 3 | use drop_bomb::DropBomb; |
4 | use ignore; | 4 | use ignore; |
5 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; | 5 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; |
6 | use parking_lot::Mutex; | ||
6 | use std::{ | 7 | use 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 | ||
13 | pub struct Watcher { | 14 | pub 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 { | |||
27 | fn handle_change_event( | 28 | fn 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 | ||
72 | fn watch_recursive(watcher: &Arc<Mutex<RecommendedWatcher>>, path: &Path) { | 73 | fn 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"), |