Revert "Mac no longer fire bogus events. Fix Mac watcher." BUG= Review URL: https://codereview.chromium.org//670653003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@41221 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 175a860..eb544f6 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md
@@ -1,7 +1,3 @@ -# 0.9.4 - -* Remove delay-fixes in MacOSDirectoryWatcher, by depending on sdk 1.6. - # 0.9.3 * Improved support for Windows via `WindowsDirectoryWatcher`.
diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 65f07fa..e3efa2d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart
@@ -73,15 +73,30 @@ /// a subdirectory that was moved into the watched directory. StreamSubscription<FileSystemEntity> _listSubscription; + /// The timer for tracking how long we wait for an initial batch of bogus + /// events (see issue 14373). + Timer _bogusEventTimer; + _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, _files = new PathSet(directory), _id = "$parentId/${_count++}" { - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - _startWatch(); + _startWatch(); + + // Before we're ready to emit events, wait for [_listDir] to complete and + // for enough time to elapse that if bogus events (issue 14373) would be + // emitted, they will be. + // + // If we do receive a batch of events, [_onBatch] will ensure that these + // futures don't fire and that the directory is re-listed. + Future.wait([ + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + }), + _waitForBogusEvents() + ]).then((_) { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -119,6 +134,29 @@ } } + // If we get a batch of events before we're ready to begin emitting events, + // it's probable that it's a batch of pre-watcher events (see issue 14373). + // Ignore those events and re-list the directory. + if (!isReady) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] not ready to emit events, re-listing directory"); + } + + // Cancel the timer because bogus events only occur in the first batch, so + // we can fire [ready] as soon as we're done listing the directory. + _bogusEventTimer.cancel(); + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + _readyCompleter.complete(); + }); + return; + } + _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { @@ -354,6 +392,17 @@ _watchSubscription = null; + // If the directory still exists and we're still expecting bogus events, + // this is probably issue 14849 rather than a real close event. We should + // just restart the watcher. + if (!isReady && new Directory(directory).existsSync()) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] fake closure (issue 14849), re-opening stream"); + } + _startWatch(); + return; + } + // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. @@ -393,6 +442,19 @@ return completer.future; } + /// Wait 200ms for a batch of bogus events (issue 14373) to come in. + /// + /// 200ms is short in terms of human interaction, but longer than any Mac OS + /// watcher tests take on the bots, so it should be safe to assume that any + /// bogus events will be signaled in that time frame. + Future _waitForBogusEvents() { + var completer = new Completer(); + _bogusEventTimer = new Timer( + new Duration(milliseconds: 200), + completer.complete); + return completer.future; + } + /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return;
diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 473e1c9..6f96a56 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml
@@ -1,5 +1,5 @@ name: watcher -version: 0.9.4 +version: 0.9.3 author: Dart Team <misc@dartlang.org> homepage: http://www.dartlang.org description: > @@ -13,5 +13,3 @@ dev_dependencies: scheduled_test: '>=0.9.3 <0.12.0' unittest: '>=0.9.2 <0.12.0' -environment: - sdk: ">=1.6.0 <2.0.0"