Chromium Code Reviews

Side by Side Diff: watcher/lib/src/file_watcher/native.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « watcher/lib/src/file_watcher.dart ('k') | watcher/lib/src/file_watcher/polling.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library watcher.file_watcher.native;
6
7 import 'dart:async';
8 import 'dart:io';
9
10 import '../file_watcher.dart';
11 import '../resubscribable.dart';
12 import '../utils.dart';
13 import '../watch_event.dart';
14
15 /// Uses the native file system notifications to watch for filesystem events.
16 ///
17 /// Single-file notifications are much simpler than those for multiple files, so
18 /// this doesn't need to be split out into multiple OS-specific classes.
19 class NativeFileWatcher extends ResubscribableWatcher implements FileWatcher {
20 NativeFileWatcher(String path)
21 : super(path, () => new _NativeFileWatcher(path));
22 }
23
24 class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher {
25 final String path;
26
27 Stream<WatchEvent> get events => _eventsController.stream;
28 final _eventsController = new StreamController<WatchEvent>.broadcast();
29
30 bool get isReady => _readyCompleter.isCompleted;
31
32 Future get ready => _readyCompleter.future;
33 final _readyCompleter = new Completer();
34
35 StreamSubscription _subscription;
36
37 _NativeFileWatcher(this.path) {
38 _listen();
39
40 // We don't need to do any initial set-up, so we're ready immediately after
41 // being listened to.
42 _readyCompleter.complete();
43 }
44
45 void _listen() {
46 // Batch the events together so that we can dedup them.
47 _subscription = new File(path).watch()
48 .transform(new BatchedStreamTransformer<FileSystemEvent>())
49 .listen(_onBatch, onError: _eventsController.addError, onDone: _onDone);
50 }
51
52 void _onBatch(List<FileSystemEvent> batch) {
53 if (batch.any((event) => event.type == FileSystemEvent.DELETE)) {
54 // If the file is deleted, the underlying stream will close. We handle
55 // emitting our own REMOVE event in [_onDone].
56 return;
57 }
58
59 _eventsController.add(new WatchEvent(ChangeType.MODIFY, path));
60 }
61
62 _onDone() async {
63 var fileExists = await new File(path).exists();
64
65 // Check for this after checking whether the file exists because it's
66 // possible that [close] was called between [File.exists] being called and
67 // it completing.
68 if (_eventsController.isClosed) return;
69
70 if (fileExists) {
71 // If the file exists now, it was probably removed and quickly replaced;
72 // this can happen for example when another file is moved on top of it.
73 // Re-subscribe and report a modify event.
74 _eventsController.add(new WatchEvent(ChangeType.MODIFY, path));
75 _listen();
76 } else {
77 _eventsController.add(new WatchEvent(ChangeType.REMOVE, path));
78 close();
79 }
80 }
81
82 void close() {
83 if (_subscription != null) _subscription.cancel();
84 _subscription = null;
85 _eventsController.close();
86 }
87 }
OLDNEW
« no previous file with comments | « watcher/lib/src/file_watcher.dart ('k') | watcher/lib/src/file_watcher/polling.dart » ('j') | no next file with comments »

Powered by Google App Engine