Selaa lähdekoodia

Create first file event handling stubs.

Mathias Gottschlag 5 vuotta sitten
vanhempi
commit
ef35767034
2 muutettua tiedostoa jossa 73 lisäystä ja 17 poistoa
  1. 63
    10
      src/file_system_watcher.rs
  2. 10
    7
      src/file_tree.rs

+ 63
- 10
src/file_system_watcher.rs Näytä tiedosto

@@ -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 {

+ 10
- 7
src/file_tree.rs Näytä tiedosto

@@ -54,36 +54,37 @@ impl FileTree {
54 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 58
         // TODO
59 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 63
         // TODO
64 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 68
         // TODO
69 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 73
         // TODO
74 74
         panic!("Not yet implemented.");
75 75
     }
76 76
 
77 77
     // TODO: Limit on size of all temporary files, make this function return a
78 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 80
         // TODO
81 81
         panic!("Not yet implemented.");
82 82
     }
83 83
 
84 84
     pub fn update_file(
85
+        &self,
85 86
         _source: NewVersionSource,
86
-        _path: &str,
87
+        _path: &OsStr,
87 88
         _info: FileInfo,
88 89
         _contents: TemporaryFile,
89 90
         _origin: OriginInfo,
@@ -93,8 +94,9 @@ impl FileTree {
93 94
     }
94 95
 
95 96
     pub fn create_directory(
97
+        &self,
96 98
         _source: NewVersionSource,
97
-        _path: &str,
99
+        _path: &OsStr,
98 100
         _origin: OriginInfo,
99 101
     ) -> Result<NewVersionEvent, Error> {
100 102
         // TODO
@@ -118,6 +120,7 @@ pub struct NewVersionSource {
118 120
 }
119 121
 
120 122
 pub struct FileInfo {
123
+    pub file_name: OsString,
121 124
     // TODO
122 125
 }
123 126
 

Loading…
Peruuta
Tallenna