diff options
-rw-r--r-- | Cargo.lock | 32 | ||||
-rw-r--r-- | crates/ra_vfs/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_vfs/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_vfs/src/watcher.rs | 57 |
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" | |||
447 | source = "registry+https://github.com/rust-lang/crates.io-index" | 447 | source = "registry+https://github.com/rust-lang/crates.io-index" |
448 | 448 | ||
449 | [[package]] | 449 | [[package]] |
450 | name = "globset" | ||
451 | version = "0.4.2" | ||
452 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
453 | dependencies = [ | ||
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]] | ||
450 | name = "heck" | 462 | name = "heck" |
451 | version = "0.3.1" | 463 | version = "0.3.1" |
452 | source = "registry+https://github.com/rust-lang/crates.io-index" | 464 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -470,6 +482,23 @@ dependencies = [ | |||
470 | ] | 482 | ] |
471 | 483 | ||
472 | [[package]] | 484 | [[package]] |
485 | name = "ignore" | ||
486 | version = "0.4.6" | ||
487 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
488 | dependencies = [ | ||
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]] | ||
473 | name = "im" | 502 | name = "im" |
474 | version = "12.3.0" | 503 | version = "12.3.0" |
475 | source = "registry+https://github.com/rust-lang/crates.io-index" | 504 | source = "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" | |||
12 | log = "0.4.6" | 12 | log = "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 |
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 | drop_bomb = "0.1.0" | 16 | drop_bomb = "0.1.0" |
16 | 17 | ||
17 | thread_worker = { path = "../thread_worker" } | 18 | thread_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 @@ | |||
1 | use crate::io; | ||
2 | use crossbeam_channel::Sender; | ||
3 | use drop_bomb::DropBomb; | ||
4 | use ignore; | ||
5 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; | ||
1 | use std::{ | 6 | use 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 | ||
8 | use crate::io; | ||
9 | use crossbeam_channel::Sender; | ||
10 | use drop_bomb::DropBomb; | ||
11 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; | ||
12 | |||
13 | pub struct Watcher { | 13 | pub 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 | ||
27 | fn send_change_events( | 27 | fn 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 | ||
65 | fn 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 | |||
72 | fn 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 | |||
61 | impl Watcher { | 89 | impl 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<()> { |