@@ -133,8 +133,8 @@ class _MacOSDirectoryWatcher
133
133
: [canonicalEvent];
134
134
135
135
for (var event in events) {
136
- if (event.isCreate ) {
137
- if ( ! event.isDirectory ! ) {
136
+ switch (event.type ) {
137
+ case EventType .createFile :
138
138
// If we already know about the file, treat it like a modification.
139
139
// This can happen if a file is copied on top of an existing one.
140
140
// We'll see an ADD event for the latter file when from the user's
@@ -144,47 +144,57 @@ class _MacOSDirectoryWatcher
144
144
145
145
_emitEvent (type, path);
146
146
_files.add (path);
147
- continue ;
148
- }
149
-
150
- if (_files.containsDir (path)) continue ;
151
-
152
- var stream = Directory (path)
153
- .list (recursive: true )
154
- .ignoring <PathNotFoundException >();
155
- var subscription = stream.listen ((entity) {
156
- if (entity is Directory ) return ;
157
- if (_files.contains (path)) return ;
158
-
159
- _emitEvent (ChangeType .ADD , entity.path);
160
- _files.add (entity.path);
161
- }, cancelOnError: true );
162
- subscription.onDone (() {
163
- _listSubscriptions.remove (subscription);
164
- });
165
- subscription.onError (_emitError);
166
- _listSubscriptions.add (subscription);
167
- } else if (event.isModify) {
168
- assert (! event.isDirectory! );
169
- _emitEvent (ChangeType .MODIFY , path);
170
- } else {
171
- assert (event.isDelete);
172
- for (var removedPath in _files.remove (path)) {
173
- _emitEvent (ChangeType .REMOVE , removedPath);
174
- }
147
+
148
+ case EventType .createDirectory:
149
+ if (_files.containsDir (path)) continue ;
150
+
151
+ var stream = Directory (path)
152
+ .list (recursive: true )
153
+ .ignoring <PathNotFoundException >();
154
+ var subscription = stream.listen ((entity) {
155
+ if (entity is Directory ) return ;
156
+ if (_files.contains (path)) return ;
157
+
158
+ _emitEvent (ChangeType .ADD , entity.path);
159
+ _files.add (entity.path);
160
+ }, cancelOnError: true );
161
+ subscription.onDone (() {
162
+ _listSubscriptions.remove (subscription);
163
+ });
164
+ subscription.onError (_emitError);
165
+ _listSubscriptions.add (subscription);
166
+
167
+ case EventType .modifyFile:
168
+ _emitEvent (ChangeType .MODIFY , path);
169
+
170
+ case EventType .delete:
171
+ for (var removedPath in _files.remove (path)) {
172
+ _emitEvent (ChangeType .REMOVE , removedPath);
173
+ }
174
+
175
+ // TODO(davidmorgan): explain.
176
+ case EventType .modifyDirectory:
177
+ throw ArgumentError ();
178
+
179
+ // No move events on MacOS.
180
+ case EventType .moveFile:
181
+ case EventType .moveDirectory:
182
+ throw ArgumentError ();
175
183
}
176
184
}
177
185
});
178
186
}
179
187
180
188
/// Sort all the events in a batch into sets based on their path.
181
189
///
182
- /// A single input event may result in multiple events in the returned map;
183
- /// for example, a MOVE event becomes a DELETE event for the source and a
184
- /// CREATE event for the destination .
190
+ /// Events for `path` are discarded.
191
+ ///
192
+ /// Events under directories that are created or modified are discarded .
185
193
///
186
- /// The returned events won't contain any [FileSystemMoveEvent] s, nor will it
187
- /// contain any events relating to [path] .
194
+ /// There should already be no [EventType.moveFile] or
195
+ /// [EventType.moveDirectory] events because the SDK does not send any on
196
+ /// MacOS. See https://github.com/dart-lang/sdk/issues/14806. If there are
197
+ /// any, they are dropped.
188
198
Map <String , Set <Event >> _sortEvents (List <Event > batch) {
189
199
var eventsForPaths = < String , Set <Event >> {};
190
200
@@ -193,9 +203,10 @@ class _MacOSDirectoryWatcher
193
203
// really deleted, that's handled by [_onDone].
194
204
batch = batch.where ((event) => event.path != path).toList ();
195
205
196
- // Events within directories that already have events are superfluous; the
197
- // directory's full contents will be examined anyway, so we ignore such
198
- // events. Emitting them could cause useless or out-of-order events.
206
+ // Events within directories that already have create or modify events are
207
+ // superfluous; the directory's full contents will be examined anyway, so we
208
+ // ignore such events. Emitting them could cause useless or out-of-order
209
+ // events.
199
210
var directories = unionAll (batch.map ((event) {
200
211
if (event.isDelete || ! event.isDirectory! ) return < String > {};
201
212
return event.paths;
@@ -210,8 +221,7 @@ class _MacOSDirectoryWatcher
210
221
}
211
222
212
223
for (var event in batch) {
213
- // The Mac OS watcher doesn't emit move events. See issue 14806.
214
- assert (! event.isMove);
224
+ if (event.isMove) continue ;
215
225
addEvent (event.path, event);
216
226
}
217
227
@@ -233,6 +243,7 @@ class _MacOSDirectoryWatcher
233
243
// contradictory (e.g. because of a move).
234
244
if (batch.isEmpty) return null ;
235
245
246
+ var path = batch.first.path;
236
247
var type = batch.first.type;
237
248
var isDirectory = batch.first.isDirectory;
238
249
var hadModifyEvent = false ;
@@ -254,42 +265,50 @@ class _MacOSDirectoryWatcher
254
265
255
266
// If we previously thought this was a MODIFY, we now consider it to be a
256
267
// CREATE or REMOVE event. This is safe for the same reason as above.
257
- if (type == EventType .modify ) {
268
+ if (type == EventType .modifyFile || type == EventType .modifyDirectory ) {
258
269
type = event.type;
259
270
continue ;
260
271
}
261
272
262
273
// A CREATE event contradicts a REMOVE event and vice versa.
263
- assert (type == EventType .create || type == EventType .delete);
274
+ assert (type == EventType .createFile ||
275
+ type == EventType .createDirectory ||
276
+ type == EventType .delete);
264
277
if (type != event.type) return null ;
265
278
}
266
279
267
280
// If we got a CREATE event for a file we already knew about, that comes
268
281
// from FSEvents reporting an add that happened prior to the watch
269
282
// beginning. If we also received a MODIFY event, we want to report that,
270
283
// but not the CREATE.
271
- if (type == EventType .create &&
284
+ if (type == EventType .createFile &&
272
285
hadModifyEvent &&
273
- _files.contains (batch.first. path)) {
274
- type = EventType .modify ;
286
+ _files.contains (path)) {
287
+ type = EventType .modifyFile ;
275
288
}
276
289
277
290
switch (type) {
278
- case EventType .create :
291
+ case EventType .createDirectory :
279
292
// Issue 16003 means that a CREATE event for a directory can indicate
280
293
// that the directory was moved and then re-created.
281
294
// [_eventsBasedOnFileSystem] will handle this correctly by producing a
282
295
// DELETE event followed by a CREATE event if the directory exists.
283
- if (isDirectory! ) return null ;
284
- return Event .createFile (batch.first.path);
296
+ return null ;
297
+ case EventType .createFile:
298
+ return Event .createFile (path);
299
+
285
300
case EventType .delete:
286
- return Event .delete (batch.first.path);
287
- case EventType .modify:
288
- return isDirectory!
289
- ? Event .modifyDirectory (batch.first.path)
290
- : Event .modifyFile (batch.first.path);
291
- default :
292
- throw StateError ('unreachable' );
301
+ return Event .delete (path);
302
+
303
+ case EventType .modifyFile:
304
+ return Event .modifyFile (path);
305
+ case EventType .modifyDirectory:
306
+ return Event .modifyDirectory (path);
307
+
308
+ // No move events on MacOS.
309
+ case EventType .moveFile:
310
+ case EventType .moveDirectory:
311
+ throw ArgumentError ();
293
312
}
294
313
}
295
314
0 commit comments