Browse Source

Create first file event handling stubs.

Mathias Gottschlag 5 years ago
parent
commit
ef35767034
2 changed files with 73 additions and 17 deletions
  1. 63
    10
      src/file_system_watcher.rs
  2. 10
    7
      src/file_tree.rs

+ 63
- 10
src/file_system_watcher.rs View File

1
+use std::collections::HashMap;
2
+use std::ffi::OsString;
3
+use std::fs;
1
 use std::sync::Arc;
4
 use std::sync::Arc;
2
 use std::time::Duration;
5
 use std::time::Duration;
3
 
6
 
146
     }
149
     }
147
 
150
 
148
     async fn handle_file_event(
151
     async fn handle_file_event(
149
-        _file_tree: &mut Arc<Mutex<FileTree>>,
152
+        file_tree: &mut Arc<Mutex<FileTree>>,
150
         errors: &mut mpsc::Sender<SynchronizationError>,
153
         errors: &mut mpsc::Sender<SynchronizationError>,
151
         event: FileSystemEvent,
154
         event: FileSystemEvent,
152
     ) -> Result<(), Error> {
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
         match event {
159
         match event {
154
             FileSystemEvent::Stopped(reason) => match reason {
160
             FileSystemEvent::Stopped(reason) => match reason {
155
                 StopReason::DirectoryRemoved => {
161
                 StopReason::DirectoryRemoved => {
156
                     return Err(Error::DirectoryRemoved);
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
             FileSystemEvent::DirectoryCreated(_path) => {
206
             FileSystemEvent::DirectoryCreated(_path) => {
163
                 // TODO
207
                 // TODO
184
                 // TODO
228
                 // TODO
185
             }
229
             }
186
             FileSystemEvent::Error(e) => {
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
         task::yield_now().await;
239
         task::yield_now().await;
202
         Ok(())
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
 impl Drop for FileSystemWatcher {
259
 impl Drop for FileSystemWatcher {

+ 10
- 7
src/file_tree.rs View File

54
         source
54
         source
55
     }
55
     }
56
 
56
 
57
-    pub fn get_file_info(_path: &str) -> Option<FileInfo> {
57
+    pub fn get_file_info(&self, _path: &OsStr) -> Option<FileInfo> {
58
         // TODO
58
         // TODO
59
         panic!("Not yet implemented.");
59
         panic!("Not yet implemented.");
60
     }
60
     }
61
 
61
 
62
-    pub fn get_directory_listing(_path: &str) -> Option<Vec<FileInfo>> {
62
+    pub fn get_directory_listing(&self, _path: &OsStr) -> Option<Vec<FileInfo>> {
63
         // TODO
63
         // TODO
64
         panic!("Not yet implemented.");
64
         panic!("Not yet implemented.");
65
     }
65
     }
66
 
66
 
67
-    pub fn local_file_changed(_source: NewVersionSource, _path: &str, _info: FileInfo) {
67
+    pub fn local_file_changed(&self, _source: NewVersionSource, _path: &OsStr, _info: FileInfo) {
68
         // TODO
68
         // TODO
69
         panic!("Not yet implemented.");
69
         panic!("Not yet implemented.");
70
     }
70
     }
71
 
71
 
72
-    pub fn local_file_removed(_source: NewVersionSource, _path: &str) {
72
+    pub fn local_file_removed(&self, _source: NewVersionSource, _path: &OsStr) {
73
         // TODO
73
         // TODO
74
         panic!("Not yet implemented.");
74
         panic!("Not yet implemented.");
75
     }
75
     }
76
 
76
 
77
     // TODO: Limit on size of all temporary files, make this function return a
77
     // TODO: Limit on size of all temporary files, make this function return a
78
     // future which yields a temporary file once enough space is available?
78
     // future which yields a temporary file once enough space is available?
79
-    pub fn create_temporary_file(_target_path: &str) -> Result<TemporaryFile, Error> {
79
+    pub fn create_temporary_file(&self, _target_path: &OsStr) -> Result<TemporaryFile, Error> {
80
         // TODO
80
         // TODO
81
         panic!("Not yet implemented.");
81
         panic!("Not yet implemented.");
82
     }
82
     }
83
 
83
 
84
     pub fn update_file(
84
     pub fn update_file(
85
+        &self,
85
         _source: NewVersionSource,
86
         _source: NewVersionSource,
86
-        _path: &str,
87
+        _path: &OsStr,
87
         _info: FileInfo,
88
         _info: FileInfo,
88
         _contents: TemporaryFile,
89
         _contents: TemporaryFile,
89
         _origin: OriginInfo,
90
         _origin: OriginInfo,
93
     }
94
     }
94
 
95
 
95
     pub fn create_directory(
96
     pub fn create_directory(
97
+        &self,
96
         _source: NewVersionSource,
98
         _source: NewVersionSource,
97
-        _path: &str,
99
+        _path: &OsStr,
98
         _origin: OriginInfo,
100
         _origin: OriginInfo,
99
     ) -> Result<NewVersionEvent, Error> {
101
     ) -> Result<NewVersionEvent, Error> {
100
         // TODO
102
         // TODO
118
 }
120
 }
119
 
121
 
120
 pub struct FileInfo {
122
 pub struct FileInfo {
123
+    pub file_name: OsString,
121
     // TODO
124
     // TODO
122
 }
125
 }
123
 
126
 

Loading…
Cancel
Save