Index: mojo/public/dart/third_party/watcher/lib/src/file_watcher/polling.dart |
diff --git a/mojo/public/dart/third_party/watcher/lib/src/file_watcher/polling.dart b/mojo/public/dart/third_party/watcher/lib/src/file_watcher/polling.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3480ae29eb78094e0b9f86a6d41022cab7039c54 |
--- /dev/null |
+++ b/mojo/public/dart/third_party/watcher/lib/src/file_watcher/polling.dart |
@@ -0,0 +1,93 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+library watcher.file_watcher.polling; |
+ |
+import 'dart:async'; |
+import 'dart:io'; |
+ |
+import '../file_watcher.dart'; |
+import '../resubscribable.dart'; |
+import '../stat.dart'; |
+import '../watch_event.dart'; |
+ |
+/// Periodically polls a file for changes. |
+class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { |
+ PollingFileWatcher(String path, {Duration pollingDelay}) |
+ : super(path, () { |
+ return new _PollingFileWatcher(path, |
+ pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); |
+ }); |
+} |
+ |
+class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { |
+ final String path; |
+ |
+ Stream<WatchEvent> get events => _eventsController.stream; |
+ final _eventsController = new StreamController<WatchEvent>.broadcast(); |
+ |
+ bool get isReady => _readyCompleter.isCompleted; |
+ |
+ Future get ready => _readyCompleter.future; |
+ final _readyCompleter = new Completer(); |
+ |
+ /// The timer that controls polling. |
+ Timer _timer; |
+ |
+ /// The previous modification time of the file. |
+ /// |
+ /// Used to tell when the file was modified. This is `null` before the file's |
+ /// mtime has first been checked. |
+ DateTime _lastModified; |
+ |
+ _PollingFileWatcher(this.path, Duration pollingDelay) { |
+ _timer = new Timer.periodic(pollingDelay, (_) => _poll()); |
+ _poll(); |
+ } |
+ |
+ /// Checks the mtime of the file and whether it's been removed. |
+ Future _poll() async { |
+ // We don't mark the file as removed if this is the first poll (indicated by |
+ // [_lastModified] being null). Instead, below we forward the dart:io error |
+ // that comes from trying to read the mtime below. |
+ var pathExists = await new File(path).exists(); |
+ if (_eventsController.isClosed) return; |
+ |
+ if (_lastModified != null && !pathExists) { |
+ _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); |
+ close(); |
+ return; |
+ } |
+ |
+ var modified; |
+ try { |
+ try { |
+ modified = await getModificationTime(path); |
+ } finally { |
+ if (_eventsController.isClosed) return; |
+ } |
+ } on FileSystemException catch (error, stackTrace) { |
+ _eventsController.addError(error, stackTrace); |
+ close(); |
+ return; |
+ } |
+ |
+ if (_lastModified == modified) return; |
+ |
+ if (_lastModified == null) { |
+ // If this is the first poll, don't emit an event, just set the last mtime |
+ // and complete the completer. |
+ _lastModified = modified; |
+ _readyCompleter.complete(); |
+ } else { |
+ _lastModified = modified; |
+ _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); |
+ } |
+ } |
+ |
+ void close() { |
+ _timer.cancel(); |
+ _eventsController.close(); |
+ } |
+} |