@@ -34,6 +34,8 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
34
34
final _readyCompleter = Completer <void >();
35
35
36
36
StreamSubscription <List <FileSystemEvent >>? _subscription;
37
+ Future <bool >? _existedAtStartupFuture;
38
+ bool ? _existedAtStartup;
37
39
38
40
_NativeFileWatcher (this .path) {
39
41
_listen ();
@@ -44,20 +46,37 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
44
46
}
45
47
46
48
void _listen () {
49
+ var file = File (path);
50
+
47
51
// Batch the events together so that we can dedup them.
48
- _subscription = File (path)
52
+ _subscription = file
49
53
.watch ()
50
54
.batchEvents ()
51
55
.listen (_onBatch, onError: _eventsController.addError, onDone: _onDone);
56
+
57
+ // On MacOS events can arrive from file changes before the `watch`. Check
58
+ // existence on startup to differentiate creation before and after the
59
+ // `watch`.
60
+ if (Platform .isMacOS) _existedAtStartupFuture = file.exists ();
52
61
}
53
62
54
- void _onBatch (List <FileSystemEvent > batch) {
63
+ void _onBatch (List <FileSystemEvent > batch) async {
55
64
if (batch.any ((event) => event.type == FileSystemEvent .delete)) {
56
65
// If the file is deleted, the underlying stream will close. We handle
57
66
// emitting our own REMOVE event in [_onDone].
58
67
return ;
59
68
}
60
69
70
+ if (Platform .isMacOS) {
71
+ var existedAtStartup =
72
+ _existedAtStartup ?? = await _existedAtStartupFuture! ;
73
+ if (existedAtStartup &&
74
+ batch.every ((event) => event.type == FileSystemEvent .create)) {
75
+ // It's a create event from before `watch` was called, ignore it.
76
+ return ;
77
+ }
78
+ }
79
+
61
80
_eventsController.add (WatchEvent (ChangeType .MODIFY , path));
62
81
}
63
82
0 commit comments