| Index: pkg/watcher/lib/src/directory_watcher/windows.dart
|
| diff --git a/pkg/watcher/lib/src/directory_watcher/windows.dart b/pkg/watcher/lib/src/directory_watcher/windows.dart
|
| index ddcf897d361217b7529c66a7a6fcab9bd341fbea..4f41d339538b7ce0562743697b44f89bd43efbcb 100644
|
| --- a/pkg/watcher/lib/src/directory_watcher/windows.dart
|
| +++ b/pkg/watcher/lib/src/directory_watcher/windows.dart
|
| @@ -28,11 +28,8 @@ class _EventBatcher {
|
| final List<FileSystemEvent> events = [];
|
| Timer timer;
|
|
|
| - void addEvent(FileSystemEvent event) {
|
| + void addEvent(FileSystemEvent event, void callback()) {
|
| events.add(event);
|
| - }
|
| -
|
| - void startTimer(void callback()) {
|
| if (timer != null) {
|
| timer.cancel();
|
| }
|
| @@ -78,18 +75,19 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
| /// the directory to determine its initial state.
|
| StreamSubscription<FileSystemEntity> _initialListSubscription;
|
|
|
| - /// The subscriptions to the [Directory.list] call for listing the contents of
|
| - /// subdirectories that was moved into the watched directory.
|
| + /// The subscriptions to the [Directory.list] calls for listing the contents
|
| + /// of subdirectories that were moved into the watched directory.
|
| final Set<StreamSubscription<FileSystemEntity>> _listSubscriptions
|
| = new HashSet<StreamSubscription<FileSystemEntity>>();
|
|
|
| _WindowsDirectoryWatcher(String directory)
|
| : directory = directory, _files = new PathSet(directory) {
|
| - _startWatch();
|
| - _startParentWatcher();
|
| -
|
| // Before we're ready to emit events, wait for [_listDir] to complete.
|
| - _listDir().then(_readyCompleter.complete);
|
| + _listDir().then((_) {
|
| + _startWatch();
|
| + _startParentWatcher();
|
| + _readyCompleter.complete();
|
| + });
|
| }
|
|
|
| void close() {
|
| @@ -111,13 +109,13 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
| }
|
|
|
| /// On Windows, if [directory] is deleted, we will not receive any event.
|
| + ///
|
| /// Instead, we add a watcher on the parent folder (if any), that can notify
|
| - /// us about [directory].
|
| - /// This also includes events such as moves.
|
| + /// us about [directory]. This also includes events such as moves.
|
| void _startParentWatcher() {
|
| var absoluteDir = p.absolute(directory);
|
| var parent = p.dirname(absoluteDir);
|
| - // Check if we [directory] is already the root directory.
|
| + // Check if [directory] is already the root directory.
|
| if (FileSystemEntity.identicalSync(parent, directory)) return;
|
| var parentStream = Chain.track(
|
| new Directory(parent).watch(recursive: false));
|
| @@ -140,26 +138,19 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
| close();
|
| }
|
| }, onError: (error) {
|
| - // Ignore errors, simply close the stream.
|
| + // Ignore errors, simply close the stream. The user listens on
|
| + // [directory], and while it can fail to listen on the parent, we may
|
| + // still be able to listen on the path requested.
|
| _parentWatchSubscription.cancel();
|
| _parentWatchSubscription = null;
|
| });
|
| }
|
|
|
| void _onEvent(FileSystemEvent event) {
|
| - // If we get a event before we're ready to begin emitting events,
|
| - // ignore those events and re-list the directory.
|
| - if (!isReady) {
|
| - _listDir().then((_) {
|
| - _readyCompleter.complete();
|
| - });
|
| - return;
|
| - }
|
| -
|
| - _EventBatcher batcher = _eventBatchers.putIfAbsent(
|
| + assert(isReady);
|
| + final batcher = _eventBatchers.putIfAbsent(
|
| event.path, () => new _EventBatcher());
|
| - batcher.addEvent(event);
|
| - batcher.startTimer(() {
|
| + batcher.addEvent(event, () {
|
| _eventBatchers.remove(event.path);
|
| _onBatch(batcher.events);
|
| });
|
| @@ -246,8 +237,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
|
|
| for (var event in batch) {
|
| if (event is FileSystemMoveEvent) {
|
| - FileSystemMoveEvent moveEvent = event;
|
| - addEvent(moveEvent.destination, event);
|
| + addEvent(event.destination, event);
|
| }
|
| addEvent(event.path, event);
|
| }
|
| @@ -366,7 +356,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
| void _onDone() {
|
| _watchSubscription = null;
|
|
|
| - // Emit remove-events for any remaining files.
|
| + // Emit remove events for any remaining files.
|
| for (var file in _files.toSet()) {
|
| _emitEvent(ChangeType.REMOVE, file);
|
| }
|
| @@ -376,7 +366,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
|
|
|
| /// Start or restart the underlying [Directory.watch] stream.
|
| void _startWatch() {
|
| - // Batch the events changes together so that we can dedup events.
|
| + // Batch the events together so that we can dedup events.
|
| var innerStream =
|
| Chain.track(new Directory(directory).watch(recursive: true));
|
| _watchSubscription = innerStream.listen(_onEvent,
|
|
|