|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+use std::collections::HashMap;
|
|
|
2
|
+use std::ffi::OsString;
|
|
|
3
|
+use std::fs;
|
|
1
|
4
|
use std::sync::Arc;
|
|
2
|
5
|
use std::time::Duration;
|
|
3
|
6
|
|
|
|
@@ -146,18 +149,59 @@ impl FileSystemWatcher {
|
|
146
|
149
|
}
|
|
147
|
150
|
|
|
148
|
151
|
async fn handle_file_event(
|
|
149
|
|
- _file_tree: &mut Arc<Mutex<FileTree>>,
|
|
|
152
|
+ file_tree: &mut Arc<Mutex<FileTree>>,
|
|
150
|
153
|
errors: &mut mpsc::Sender<SynchronizationError>,
|
|
151
|
154
|
event: FileSystemEvent,
|
|
152
|
155
|
) -> Result<(), Error> {
|
|
|
156
|
+ // When we get an I/O error, we simply ignore the corresponding file/directory. Most
|
|
|
157
|
+ // likely, it has been deleted, and we will get a deletion event later. If a file or
|
|
|
158
|
+ // directory is not readable, we do not want to synchronize it.
|
|
153
|
159
|
match event {
|
|
154
|
160
|
FileSystemEvent::Stopped(reason) => match reason {
|
|
155
|
161
|
StopReason::DirectoryRemoved => {
|
|
156
|
162
|
return Err(Error::DirectoryRemoved);
|
|
157
|
163
|
}
|
|
158
|
164
|
},
|
|
159
|
|
- FileSystemEvent::DirectoryWatched(_path) => {
|
|
160
|
|
- // TODO
|
|
|
165
|
+ FileSystemEvent::DirectoryWatched(path) => {
|
|
|
166
|
+ // Fetch the directory contents as well as the database contents.
|
|
|
167
|
+ // TODO: We load all entries into a vector, which might be problematic for *very*
|
|
|
168
|
+ // large directories.
|
|
|
169
|
+ let fs_entries = match fs::read_dir(&path) {
|
|
|
170
|
+ Ok(entries) => entries,
|
|
|
171
|
+ Err(_) => return Ok(()),
|
|
|
172
|
+ };
|
|
|
173
|
+ let fs_entries = fs_entries
|
|
|
174
|
+ .filter(|x| x.is_ok())
|
|
|
175
|
+ .map(|x| (x.as_ref().unwrap().file_name(), x.unwrap()))
|
|
|
176
|
+ .collect::<HashMap<_, _>>();
|
|
|
177
|
+ let db_entries = match file_tree.lock().await.get_directory_listing(&path) {
|
|
|
178
|
+ Some(entries) => entries,
|
|
|
179
|
+ None => return Ok(()),
|
|
|
180
|
+ };
|
|
|
181
|
+ let db_entries = db_entries
|
|
|
182
|
+ .into_iter()
|
|
|
183
|
+ .map(|x| (x.file_name.clone(), x))
|
|
|
184
|
+ .collect::<HashMap<_, _>>();
|
|
|
185
|
+
|
|
|
186
|
+ // Compare file metadata and report changed, deleted and created files and
|
|
|
187
|
+ // directories.
|
|
|
188
|
+ for (name, _entry) in fs_entries.iter() {
|
|
|
189
|
+ if db_entries.contains_key(name) {
|
|
|
190
|
+ // The entry is known, compare the file attributes.
|
|
|
191
|
+ // TODO
|
|
|
192
|
+ // If the file attributes do not match, compare the file checksums.
|
|
|
193
|
+ // TODO
|
|
|
194
|
+ } else {
|
|
|
195
|
+ // The file seems to be new, insert it into the database.
|
|
|
196
|
+ // TODO
|
|
|
197
|
+ }
|
|
|
198
|
+ }
|
|
|
199
|
+ for (name, _entry) in db_entries.iter() {
|
|
|
200
|
+ if !fs_entries.contains_key(name) {
|
|
|
201
|
+ // The file has been deleted, remove it from the database.
|
|
|
202
|
+ // TODO
|
|
|
203
|
+ }
|
|
|
204
|
+ }
|
|
161
|
205
|
}
|
|
162
|
206
|
FileSystemEvent::DirectoryCreated(_path) => {
|
|
163
|
207
|
// TODO
|
|
|
@@ -184,13 +228,7 @@ impl FileSystemWatcher {
|
|
184
|
228
|
// TODO
|
|
185
|
229
|
}
|
|
186
|
230
|
FileSystemEvent::Error(e) => {
|
|
187
|
|
- errors
|
|
188
|
|
- .send(SynchronizationError {
|
|
189
|
|
- needs_pause: false,
|
|
190
|
|
- error: e.into(),
|
|
191
|
|
- })
|
|
192
|
|
- .await
|
|
193
|
|
- .ok();
|
|
|
231
|
+ Self::send_error_no_pause(e.into(), None, errors).await;
|
|
194
|
232
|
}
|
|
195
|
233
|
}
|
|
196
|
234
|
|
|
|
@@ -201,6 +239,21 @@ impl FileSystemWatcher {
|
|
201
|
239
|
task::yield_now().await;
|
|
202
|
240
|
Ok(())
|
|
203
|
241
|
}
|
|
|
242
|
+
|
|
|
243
|
+ async fn send_error_no_pause(
|
|
|
244
|
+ error: Error,
|
|
|
245
|
+ _path: Option<OsString>,
|
|
|
246
|
+ errors: &mut mpsc::Sender<SynchronizationError>,
|
|
|
247
|
+ ) {
|
|
|
248
|
+ // TODO: Encode the path in the error!
|
|
|
249
|
+ errors
|
|
|
250
|
+ .send(SynchronizationError {
|
|
|
251
|
+ needs_pause: false,
|
|
|
252
|
+ error: error,
|
|
|
253
|
+ })
|
|
|
254
|
+ .await
|
|
|
255
|
+ .ok();
|
|
|
256
|
+ }
|
|
204
|
257
|
}
|
|
205
|
258
|
|
|
206
|
259
|
impl Drop for FileSystemWatcher {
|