Skip to content

Commit 72e6cc8

Browse files
authored
Don't emit two WatchEvents when creating a file in a non-existent directory on Windows (#2111)
1 parent e84cbd9 commit 72e6cc8

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

pkgs/watcher/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.1.2
2+
3+
- Fix a bug on Windows where a file creation event could be reported twice when creating
4+
a file recursively in a non-existent directory.
5+
16
## 1.1.1
27

38
- Ensure `PollingFileWatcher.ready` completes for files that do not exist.

pkgs/watcher/lib/src/directory_watcher/windows.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ class _WindowsDirectoryWatcher
184184
var stream = Directory(path).list(recursive: true);
185185
var subscription = stream.listen((entity) {
186186
if (entity is Directory) return;
187-
if (_files.contains(path)) return;
187+
if (_files.contains(entity.path)) return;
188188

189189
_emitEvent(ChangeType.ADD, entity.path);
190190
_files.add(entity.path);

pkgs/watcher/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: watcher
2-
version: 1.1.1
2+
version: 1.1.2
33
description: >-
44
A file system watcher. It monitors changes to contents of directories and
55
sends notifications when files have been added, removed, or modified.

pkgs/watcher/test/directory_watcher/windows_test.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
@TestOn('windows')
66
library;
77

8+
import 'dart:async';
9+
import 'dart:io';
10+
11+
import 'package:path/path.dart' as p;
812
import 'package:test/test.dart';
913
import 'package:watcher/src/directory_watcher/windows.dart';
1014
import 'package:watcher/watcher.dart';
@@ -20,4 +24,41 @@ void main() {
2024
test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () {
2125
expect(DirectoryWatcher('.'), const TypeMatcher<WindowsDirectoryWatcher>());
2226
});
27+
28+
test('Regression test for https://github.com/dart-lang/tools/issues/2110',
29+
() async {
30+
late StreamSubscription<WatchEvent> sub;
31+
try {
32+
final temp = Directory.systemTemp.createTempSync();
33+
final watcher = DirectoryWatcher(temp.path);
34+
final events = <WatchEvent>[];
35+
sub = watcher.events.listen(events.add);
36+
await watcher.ready;
37+
38+
// Create a file in a directory that doesn't exist. This forces the
39+
// directory to be created first before the child file.
40+
//
41+
// When directory creation is detected by the watcher, it calls
42+
// `Directory.list` on the directory to determine if there's files that
43+
// have been created or modified. It's possible that the watcher will have
44+
// already detected the file creation event before `Directory.list`
45+
// returns. Before https://github.com/dart-lang/tools/issues/2110 was
46+
// resolved, the check to ensure an event hadn't already been emitted for
47+
// the file creation was incorrect, leading to the event being emitted
48+
// again in some circumstances.
49+
final file = File(p.join(temp.path, 'foo', 'file.txt'))
50+
..createSync(recursive: true);
51+
52+
// Introduce a short delay to allow for the directory watcher to detect
53+
// the creation of foo/ and foo/file.txt.
54+
await Future<void>.delayed(const Duration(seconds: 1));
55+
56+
// There should only be a single file added event.
57+
expect(events, hasLength(1));
58+
expect(events.first.toString(),
59+
WatchEvent(ChangeType.ADD, file.path).toString());
60+
} finally {
61+
await sub.cancel();
62+
}
63+
});
2364
}

0 commit comments

Comments
 (0)