@@ -17,14 +17,28 @@ pub(crate) enum Task {
17
17
AddRoot { root : VfsRoot , config : Arc < RootConfig > } ,
18
18
}
19
19
20
+ /// `TaskResult` transfers files read on the IO thread to the VFS on the main
21
+ /// thread.
20
22
#[ derive( Debug ) ]
21
23
pub enum TaskResult {
24
+ /// Emitted when we've recursively scanned a source root during the initial
25
+ /// load.
22
26
BulkLoadRoot { root : VfsRoot , files : Vec < ( RelativePathBuf , String ) > } ,
23
- AddSingleFile { root : VfsRoot , path : RelativePathBuf , text : String } ,
24
- ChangeSingleFile { root : VfsRoot , path : RelativePathBuf , text : String } ,
25
- RemoveSingleFile { root : VfsRoot , path : RelativePathBuf } ,
27
+ /// Emitted when we've noticed that a single file has changed.
28
+ ///
29
+ /// Note that this by design does not distinguish between
30
+ /// create/delete/write events, and instead specifies the *current* state of
31
+ /// the file. The idea is to guarantee that in the quiescent state the sum
32
+ /// of all results equals to the current state of the file system, while
33
+ /// allowing to skip intermediate events in non-quiescent states.
34
+ SingleFile { root : VfsRoot , path : RelativePathBuf , text : Option < String > } ,
26
35
}
27
36
37
+ /// The kind of raw notification we've received from the notify library.
38
+ ///
39
+ /// Note that these are not necessary 100% precise (for example we might receive
40
+ /// `Create` instead of `Write`, see #734), but we try do distinguish `Create`s
41
+ /// to implement recursive watching of directories.
28
42
#[ derive( Debug ) ]
29
43
enum ChangeKind {
30
44
Create ,
@@ -45,7 +59,7 @@ impl Worker {
45
59
// explained by the following concerns:
46
60
// * we need to burn a thread translating from notify's mpsc to
47
61
// crossbeam_channel.
48
- // * we want to read all files from a single thread, to gurantee that
62
+ // * we want to read all files from a single thread, to guarantee that
49
63
// we always get fresher versions and never go back in time.
50
64
// * we want to tear down everything neatly during shutdown.
51
65
let ( worker, worker_handle) = thread_worker:: spawn (
@@ -63,7 +77,7 @@ impl Worker {
63
77
let mut watcher = notify:: watcher ( notify_sender, WATCHER_DELAY )
64
78
. map_err ( |e| log:: error!( "failed to spawn notify {}" , e) )
65
79
. ok ( ) ;
66
- // Start a silly thread to tranform between two channels
80
+ // Start a silly thread to transform between two channels
67
81
let thread = thread:: spawn ( move || {
68
82
notify_receiver
69
83
. into_iter ( )
@@ -98,7 +112,7 @@ impl Worker {
98
112
}
99
113
// Stopped the watcher
100
114
drop ( watcher. take ( ) ) ;
101
- // Drain pending events: we are not inrerested in them anyways!
115
+ // Drain pending events: we are not interested in them anyways!
102
116
watcher_receiver. into_iter ( ) . for_each ( |_| ( ) ) ;
103
117
104
118
let res = thread. join ( ) ;
@@ -199,23 +213,16 @@ fn handle_change(
199
213
}
200
214
paths
201
215
. into_iter ( )
202
- . filter_map ( |rel_path| {
216
+ . try_for_each ( |rel_path| {
203
217
let abs_path = rel_path. to_path ( & config. root ) ;
204
- let text = read_to_string ( & abs_path) ?;
205
- Some ( ( rel_path, text) )
206
- } )
207
- . try_for_each ( |( path, text) | {
208
- sender. send ( TaskResult :: AddSingleFile { root, path, text } )
218
+ let text = read_to_string ( & abs_path) ;
219
+ sender. send ( TaskResult :: SingleFile { root, path : rel_path, text } )
209
220
} )
210
221
. unwrap ( )
211
222
}
212
- ChangeKind :: Write => {
213
- if let Some ( text) = read_to_string ( & path) {
214
- sender. send ( TaskResult :: ChangeSingleFile { root, path : rel_path, text } ) . unwrap ( ) ;
215
- }
216
- }
217
- ChangeKind :: Remove => {
218
- sender. send ( TaskResult :: RemoveSingleFile { root, path : rel_path } ) . unwrap ( )
223
+ ChangeKind :: Write | ChangeKind :: Remove => {
224
+ let text = read_to_string ( & path) ;
225
+ sender. send ( TaskResult :: SingleFile { root, path : rel_path, text } ) . unwrap ( ) ;
219
226
}
220
227
}
221
228
}
0 commit comments