|
|
@@ -1,7 +1,7 @@
|
|
1
|
1
|
use std::sync::Arc;
|
|
2
|
2
|
use std::time::Duration;
|
|
3
|
3
|
|
|
4
|
|
-use fswatcher::{FileEventDelay, FileSystemEvent};
|
|
|
4
|
+use fswatcher::{FileEventDelay, FileSystemEvent, StopReason};
|
|
5
|
5
|
use futures::future::{self, Either};
|
|
6
|
6
|
use tokio::stream::StreamExt;
|
|
7
|
7
|
use tokio::sync::{mpsc, oneshot, Mutex};
|
|
|
@@ -88,7 +88,8 @@ impl FileSystemWatcher {
|
|
88
|
88
|
};
|
|
89
|
89
|
let mut file_events = FileEventDelay::new(fsw, Duration::from_secs(3));
|
|
90
|
90
|
|
|
91
|
|
- loop {
|
|
|
91
|
+ let mut error_needs_pause = None;
|
|
|
92
|
+ while error_needs_pause.is_none() {
|
|
92
|
93
|
// We only want to wait for file system events until a state change pauses the file
|
|
93
|
94
|
// system watcher.
|
|
94
|
95
|
match future::select(Box::pin(file_events.next()), Box::pin(state_receive.recv())).await
|
|
|
@@ -96,7 +97,11 @@ impl FileSystemWatcher {
|
|
96
|
97
|
Either::Left((event, _state_future)) => {
|
|
97
|
98
|
// We cannot get any end-of-stream None here - we would first get a "Stopped"
|
|
98
|
99
|
// file event.
|
|
99
|
|
- Self::handle_file_event(file_tree, event.unwrap()).await;
|
|
|
100
|
+ if let Err(error) =
|
|
|
101
|
+ Self::handle_file_event(file_tree, errors, event.unwrap()).await
|
|
|
102
|
+ {
|
|
|
103
|
+ error_needs_pause = Some(error);
|
|
|
104
|
+ }
|
|
100
|
105
|
}
|
|
101
|
106
|
Either::Right((next_state, _file_event_future)) => {
|
|
102
|
107
|
match next_state.unwrap() {
|
|
|
@@ -110,6 +115,7 @@ impl FileSystemWatcher {
|
|
110
|
115
|
}
|
|
111
|
116
|
};
|
|
112
|
117
|
}
|
|
|
118
|
+ return Self::wait_for_pause(error_needs_pause.unwrap(), state_receive, errors).await;
|
|
113
|
119
|
}
|
|
114
|
120
|
|
|
115
|
121
|
async fn wait_for_pause(
|
|
|
@@ -137,14 +143,19 @@ impl FileSystemWatcher {
|
|
137
|
143
|
(StateChange::Terminate, _) => return StateChange::Terminate,
|
|
138
|
144
|
}
|
|
139
|
145
|
}
|
|
140
|
|
- // TODO
|
|
141
|
146
|
}
|
|
142
|
147
|
|
|
143
|
|
- async fn handle_file_event(_file_tree: &mut Arc<Mutex<FileTree>>, event: FileSystemEvent) {
|
|
|
148
|
+ async fn handle_file_event(
|
|
|
149
|
+ _file_tree: &mut Arc<Mutex<FileTree>>,
|
|
|
150
|
+ errors: &mut mpsc::Sender<SynchronizationError>,
|
|
|
151
|
+ event: FileSystemEvent,
|
|
|
152
|
+ ) -> Result<(), Error> {
|
|
144
|
153
|
match event {
|
|
145
|
|
- FileSystemEvent::Stopped(_reason) => {
|
|
146
|
|
- // TODO
|
|
147
|
|
- }
|
|
|
154
|
+ FileSystemEvent::Stopped(reason) => match reason {
|
|
|
155
|
+ StopReason::DirectoryRemoved => {
|
|
|
156
|
+ return Err(Error::DirectoryRemoved);
|
|
|
157
|
+ }
|
|
|
158
|
+ },
|
|
148
|
159
|
FileSystemEvent::DirectoryWatched(_path) => {
|
|
149
|
160
|
// TODO
|
|
150
|
161
|
}
|
|
|
@@ -172,8 +183,14 @@ impl FileSystemWatcher {
|
|
172
|
183
|
FileSystemEvent::FileMoved(_from, _to) => {
|
|
173
|
184
|
// TODO
|
|
174
|
185
|
}
|
|
175
|
|
- FileSystemEvent::Error(_e) => {
|
|
176
|
|
- // TODO
|
|
|
186
|
+ FileSystemEvent::Error(e) => {
|
|
|
187
|
+ errors
|
|
|
188
|
+ .send(SynchronizationError {
|
|
|
189
|
+ needs_pause: false,
|
|
|
190
|
+ error: e.into(),
|
|
|
191
|
+ })
|
|
|
192
|
+ .await
|
|
|
193
|
+ .ok();
|
|
177
|
194
|
}
|
|
178
|
195
|
}
|
|
179
|
196
|
|
|
|
@@ -182,6 +199,7 @@ impl FileSystemWatcher {
|
|
182
|
199
|
// TODO: Check whether this is really necessary and how large the impact on
|
|
183
|
200
|
// performance is.
|
|
184
|
201
|
task::yield_now().await;
|
|
|
202
|
+ Ok(())
|
|
185
|
203
|
}
|
|
186
|
204
|
}
|
|
187
|
205
|
|