Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: packages/watcher/lib/src/directory_watcher/mac_os.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library watcher.directory_watcher.mac_os;
6
7 import 'dart:async'; 5 import 'dart:async';
8 import 'dart:io'; 6 import 'dart:io';
9 7
10 import '../directory_watcher.dart'; 8 import '../directory_watcher.dart';
11 import '../constructable_file_system_event.dart'; 9 import '../constructable_file_system_event.dart';
12 import '../path_set.dart'; 10 import '../path_set.dart';
13 import '../resubscribable.dart'; 11 import '../resubscribable.dart';
14 import '../utils.dart'; 12 import '../utils.dart';
15 import '../watch_event.dart'; 13 import '../watch_event.dart';
16 14
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 /// The state of files on the filesystem is compared against this to determine 49 /// The state of files on the filesystem is compared against this to determine
52 /// the real change that occurred when working around issue 14373. This is 50 /// the real change that occurred when working around issue 14373. This is
53 /// also used to emit REMOVE events when subdirectories are moved out of the 51 /// also used to emit REMOVE events when subdirectories are moved out of the
54 /// watched directory. 52 /// watched directory.
55 final PathSet _files; 53 final PathSet _files;
56 54
57 /// The subscription to the stream returned by [Directory.watch]. 55 /// The subscription to the stream returned by [Directory.watch].
58 /// 56 ///
59 /// This is separate from [_subscriptions] because this stream occasionally 57 /// This is separate from [_subscriptions] because this stream occasionally
60 /// needs to be resubscribed in order to work around issue 14849. 58 /// needs to be resubscribed in order to work around issue 14849.
61 StreamSubscription<FileSystemEvent> _watchSubscription; 59 StreamSubscription<List<FileSystemEvent>> _watchSubscription;
62 60
63 /// The subscription to the [Directory.list] call for the initial listing of 61 /// The subscription to the [Directory.list] call for the initial listing of
64 /// the directory to determine its initial state. 62 /// the directory to determine its initial state.
65 StreamSubscription<FileSystemEntity> _initialListSubscription; 63 StreamSubscription<FileSystemEntity> _initialListSubscription;
66 64
67 /// The subscriptions to [Directory.list] calls for listing the contents of a 65 /// The subscriptions to [Directory.list] calls for listing the contents of a
68 /// subdirectory that was moved into the watched directory. 66 /// subdirectory that was moved into the watched directory.
69 final _listSubscriptions = new Set<StreamSubscription<FileSystemEntity>>(); 67 final _listSubscriptions = new Set<StreamSubscription<FileSystemEntity>>();
70 68
71 /// The timer for tracking how long we wait for an initial batch of bogus 69 /// The timer for tracking how long we wait for an initial batch of bogus
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // it's probable that it's a batch of pre-watcher events (see issue 14373). 107 // it's probable that it's a batch of pre-watcher events (see issue 14373).
110 // Ignore those events and re-list the directory. 108 // Ignore those events and re-list the directory.
111 if (!isReady) { 109 if (!isReady) {
112 // Cancel the timer because bogus events only occur in the first batch, so 110 // Cancel the timer because bogus events only occur in the first batch, so
113 // we can fire [ready] as soon as we're done listing the directory. 111 // we can fire [ready] as soon as we're done listing the directory.
114 _bogusEventTimer.cancel(); 112 _bogusEventTimer.cancel();
115 _listDir().then((_) => _readyCompleter.complete()); 113 _listDir().then((_) => _readyCompleter.complete());
116 return; 114 return;
117 } 115 }
118 116
119 _sortEvents(batch).forEach((path, events) { 117 _sortEvents(batch).forEach((path, eventSet) {
120 var canonicalEvent = _canonicalEvent(events); 118 var canonicalEvent = _canonicalEvent(eventSet);
121 events = canonicalEvent == null ? 119 var events = canonicalEvent == null ?
122 _eventsBasedOnFileSystem(path) : [canonicalEvent]; 120 _eventsBasedOnFileSystem(path) : [canonicalEvent];
123 121
124 for (var event in events) { 122 for (var event in events) {
125 if (event is FileSystemCreateEvent) { 123 if (event is FileSystemCreateEvent) {
126 if (!event.isDirectory) { 124 if (!event.isDirectory) {
127 // If we already know about the file, treat it like a modification. 125 // If we already know about the file, treat it like a modification.
128 // This can happen if a file is copied on top of an existing one. 126 // This can happen if a file is copied on top of an existing one.
129 // We'll see an ADD event for the latter file when from the user's 127 // We'll see an ADD event for the latter file when from the user's
130 // perspective, the file's contents just changed. 128 // perspective, the file's contents just changed.
131 var type = _files.contains(path) 129 var type = _files.contains(path)
132 ? ChangeType.MODIFY 130 ? ChangeType.MODIFY
133 : ChangeType.ADD; 131 : ChangeType.ADD;
134 132
135 _emitEvent(type, path); 133 _emitEvent(type, path);
136 _files.add(path); 134 _files.add(path);
137 continue; 135 continue;
138 } 136 }
139 137
140 if (_files.containsDir(path)) continue; 138 if (_files.containsDir(path)) continue;
141 139
142 var subscription; 140 StreamSubscription<FileSystemEntity> subscription;
143 subscription = new Directory(path).list(recursive: true) 141 subscription = new Directory(path).list(recursive: true)
144 .listen((entity) { 142 .listen((entity) {
145 if (entity is Directory) return; 143 if (entity is Directory) return;
146 if (_files.contains(path)) return; 144 if (_files.contains(path)) return;
147 145
148 _emitEvent(ChangeType.ADD, entity.path); 146 _emitEvent(ChangeType.ADD, entity.path);
149 _files.add(entity.path); 147 _files.add(entity.path);
150 }, onError: (e, stackTrace) { 148 }, onError: (e, stackTrace) {
151 _emitError(e, stackTrace); 149 _emitError(e, stackTrace);
152 }, onDone: () { 150 }, onDone: () {
(...skipping 15 matching lines...) Expand all
168 166
169 /// Sort all the events in a batch into sets based on their path. 167 /// Sort all the events in a batch into sets based on their path.
170 /// 168 ///
171 /// A single input event may result in multiple events in the returned map; 169 /// A single input event may result in multiple events in the returned map;
172 /// for example, a MOVE event becomes a DELETE event for the source and a 170 /// for example, a MOVE event becomes a DELETE event for the source and a
173 /// CREATE event for the destination. 171 /// CREATE event for the destination.
174 /// 172 ///
175 /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it 173 /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it
176 /// contain any events relating to [path]. 174 /// contain any events relating to [path].
177 Map<String, Set<FileSystemEvent>> _sortEvents(List<FileSystemEvent> batch) { 175 Map<String, Set<FileSystemEvent>> _sortEvents(List<FileSystemEvent> batch) {
178 var eventsForPaths = {}; 176 var eventsForPaths = <String, Set>{};
179 177
180 // FSEvents can report past events, including events on the root directory 178 // FSEvents can report past events, including events on the root directory
181 // such as it being created. We want to ignore these. If the directory is 179 // such as it being created. We want to ignore these. If the directory is
182 // really deleted, that's handled by [_onDone]. 180 // really deleted, that's handled by [_onDone].
183 batch = batch.where((event) => event.path != path).toList(); 181 batch = batch.where((event) => event.path != path).toList();
184 182
185 // Events within directories that already have events are superfluous; the 183 // Events within directories that already have events are superfluous; the
186 // directory's full contents will be examined anyway, so we ignore such 184 // directory's full contents will be examined anyway, so we ignore such
187 // events. Emitting them could cause useless or out-of-order events. 185 // events. Emitting them could cause useless or out-of-order events.
188 var directories = unionAll(batch.map((event) { 186 var directories = unionAll(batch.map((event) {
189 if (!event.isDirectory) return new Set(); 187 if (!event.isDirectory) return new Set();
190 if (event is! FileSystemMoveEvent) return new Set.from([event.path]); 188 if (event is FileSystemMoveEvent) {
191 return new Set.from([event.path, event.destination]); 189 return new Set.from([event.path, event.destination]);
190 }
191 return new Set.from([event.path]);
192 })); 192 }));
193 193
194 isInModifiedDirectory(path) => 194 isInModifiedDirectory(path) =>
195 directories.any((dir) => path != dir && path.startsWith(dir)); 195 directories.any((dir) => path != dir && path.startsWith(dir));
196 196
197 addEvent(path, event) { 197 addEvent(path, event) {
198 if (isInModifiedDirectory(path)) return; 198 if (isInModifiedDirectory(path)) return;
199 var set = eventsForPaths.putIfAbsent(path, () => new Set()); 199 var set = eventsForPaths.putIfAbsent(path, () => new Set());
200 set.add(event); 200 set.add(event);
201 } 201 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 /// This returns a list whose order should be reflected in the events emitted 287 /// This returns a list whose order should be reflected in the events emitted
288 /// to the user, unlike the batched events from [Directory.watch]. The 288 /// to the user, unlike the batched events from [Directory.watch]. The
289 /// returned list may be empty, indicating that no changes occurred to [path] 289 /// returned list may be empty, indicating that no changes occurred to [path]
290 /// (probably indicating that it was created and then immediately deleted). 290 /// (probably indicating that it was created and then immediately deleted).
291 List<FileSystemEvent> _eventsBasedOnFileSystem(String path) { 291 List<FileSystemEvent> _eventsBasedOnFileSystem(String path) {
292 var fileExisted = _files.contains(path); 292 var fileExisted = _files.contains(path);
293 var dirExisted = _files.containsDir(path); 293 var dirExisted = _files.containsDir(path);
294 var fileExists = new File(path).existsSync(); 294 var fileExists = new File(path).existsSync();
295 var dirExists = new Directory(path).existsSync(); 295 var dirExists = new Directory(path).existsSync();
296 296
297 var events = []; 297 var events = <FileSystemEvent>[];
298 if (fileExisted) { 298 if (fileExisted) {
299 if (fileExists) { 299 if (fileExists) {
300 events.add(new ConstructableFileSystemModifyEvent(path, false, false)); 300 events.add(new ConstructableFileSystemModifyEvent(path, false, false));
301 } else { 301 } else {
302 events.add(new ConstructableFileSystemDeleteEvent(path, false)); 302 events.add(new ConstructableFileSystemDeleteEvent(path, false));
303 } 303 }
304 } else if (dirExisted) { 304 } else if (dirExisted) {
305 if (dirExists) { 305 if (dirExists) {
306 // If we got contradictory events for a directory that used to exist and 306 // If we got contradictory events for a directory that used to exist and
307 // still exists, we need to rescan the whole thing in case it was 307 // still exists, we need to rescan the whole thing in case it was
(...skipping 22 matching lines...) Expand all
330 // this is probably issue 14849 rather than a real close event. We should 330 // this is probably issue 14849 rather than a real close event. We should
331 // just restart the watcher. 331 // just restart the watcher.
332 if (!isReady && new Directory(path).existsSync()) { 332 if (!isReady && new Directory(path).existsSync()) {
333 _startWatch(); 333 _startWatch();
334 return; 334 return;
335 } 335 }
336 336
337 // FSEvents can fail to report the contents of the directory being removed 337 // FSEvents can fail to report the contents of the directory being removed
338 // when the directory itself is removed, so we need to manually mark the 338 // when the directory itself is removed, so we need to manually mark the
339 // files as removed. 339 // files as removed.
340 for (var file in _files.toSet()) { 340 for (var file in _files.paths) {
341 _emitEvent(ChangeType.REMOVE, file); 341 _emitEvent(ChangeType.REMOVE, file);
342 } 342 }
343 _files.clear(); 343 _files.clear();
344 close(); 344 close();
345 } 345 }
346 346
347 /// Start or restart the underlying [Directory.watch] stream. 347 /// Start or restart the underlying [Directory.watch] stream.
348 void _startWatch() { 348 void _startWatch() {
349 // Batch the FSEvent changes together so that we can dedup events. 349 // Batch the FSEvent changes together so that we can dedup events.
350 var innerStream = new Directory(path).watch(recursive: true) 350 var innerStream = new Directory(path).watch(recursive: true)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 if (!isReady) return; 390 if (!isReady) return;
391 _eventsController.add(new WatchEvent(type, path)); 391 _eventsController.add(new WatchEvent(type, path));
392 } 392 }
393 393
394 /// Emit an error, then close the watcher. 394 /// Emit an error, then close the watcher.
395 void _emitError(error, StackTrace stackTrace) { 395 void _emitError(error, StackTrace stackTrace) {
396 _eventsController.addError(error, stackTrace); 396 _eventsController.addError(error, stackTrace);
397 close(); 397 close();
398 } 398 }
399 } 399 }
OLDNEW
« no previous file with comments | « packages/watcher/lib/src/directory_watcher/linux.dart ('k') | packages/watcher/lib/src/directory_watcher/polling.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698