@@ -35,6 +35,9 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
3535
3636 StreamSubscription <List <FileSystemEvent >>? _subscription;
3737
38+ /// On MacOS only, whether the file existed on startup.
39+ bool ? _existedAtStartup;
40+
3841 _NativeFileWatcher (this .path) {
3942 _listen ();
4043
@@ -43,12 +46,23 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
4346 _readyCompleter.complete ();
4447 }
4548
46- void _listen () {
47- // Batch the events together so that we can dedup them.
48- _subscription = File (path)
49- .watch ()
50- .batchEvents ()
51- .listen (_onBatch, onError: _eventsController.addError, onDone: _onDone);
49+ void _listen () async {
50+ var file = File (path);
51+
52+ // Batch the events together so that we can dedupe them.
53+ var stream = file.watch ().batchEvents ();
54+
55+ if (Platform .isMacOS) {
56+ var existedAtStartupFuture = file.exists ();
57+ // Delay processing watch events until the existence check finishes.
58+ stream = stream.asyncMap ((event) async {
59+ _existedAtStartup ?? = await existedAtStartupFuture;
60+ return event;
61+ });
62+ }
63+
64+ _subscription = stream.listen (_onBatch,
65+ onError: _eventsController.addError, onDone: _onDone);
5266 }
5367
5468 void _onBatch (List <FileSystemEvent > batch) {
@@ -58,6 +72,16 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
5872 return ;
5973 }
6074
75+ if (Platform .isMacOS) {
76+ // On MacOS, a spurious `create` event can be received for a file that is
77+ // created just before the `watch`. If the file existed at startup then it
78+ // should be ignored.
79+ if (_existedAtStartup! &&
80+ batch.every ((event) => event.type == FileSystemEvent .create)) {
81+ return ;
82+ }
83+ }
84+
6185 _eventsController.add (WatchEvent (ChangeType .MODIFY , path));
6286 }
6387
0 commit comments