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

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

Issue 63643008: Remove debugging prints from the Mac OS directory watcher. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/watcher/test/directory_watcher/mac_os_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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; 5 library watcher.directory_watcher.mac_os;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 9
10 import 'package:path/path.dart' as p;
11
12 import '../constructable_file_system_event.dart'; 10 import '../constructable_file_system_event.dart';
13 import '../path_set.dart'; 11 import '../path_set.dart';
14 import '../utils.dart'; 12 import '../utils.dart';
15 import '../watch_event.dart'; 13 import '../watch_event.dart';
16 import 'resubscribable.dart'; 14 import 'resubscribable.dart';
17 15
18 /// Uses the FSEvents subsystem to watch for filesystem events. 16 /// Uses the FSEvents subsystem to watch for filesystem events.
19 /// 17 ///
20 /// FSEvents has two main idiosyncrasies that this class works around. First, it 18 /// FSEvents has two main idiosyncrasies that this class works around. First, it
21 /// will occasionally report events that occurred before the filesystem watch 19 /// will occasionally report events that occurred before the filesystem watch
22 /// was initiated. Second, if multiple events happen to the same file in close 20 /// was initiated. Second, if multiple events happen to the same file in close
23 /// succession, it won't report them in the order they occurred. See issue 21 /// succession, it won't report them in the order they occurred. See issue
24 /// 14373. 22 /// 14373.
25 /// 23 ///
26 /// This also works around issues 14793, 14806, and 14849 in the implementation 24 /// This also works around issues 14793, 14806, and 14849 in the implementation
27 /// of [Directory.watch]. 25 /// of [Directory.watch].
28 class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { 26 class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher {
29 // TODO(nweiz): remove these when issue 15042 is fixed.
30 static var logDebugInfo = false;
31 static var _count = 0;
32 final int _id;
33
34 MacOSDirectoryWatcher(String directory) 27 MacOSDirectoryWatcher(String directory)
35 : _id = _count++, 28 : super(directory, () => new _MacOSDirectoryWatcher(directory));
36 super(directory, () => new _MacOSDirectoryWatcher(directory, _count));
37 } 29 }
38 30
39 class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { 31 class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher {
40 // TODO(nweiz): remove these when issue 15042 is fixed.
41 static var _count = 0;
42 final String _id;
43
44 final String directory; 32 final String directory;
45 33
46 Stream<WatchEvent> get events => _eventsController.stream; 34 Stream<WatchEvent> get events => _eventsController.stream;
47 final _eventsController = new StreamController<WatchEvent>.broadcast(); 35 final _eventsController = new StreamController<WatchEvent>.broadcast();
48 36
49 bool get isReady => _readyCompleter.isCompleted; 37 bool get isReady => _readyCompleter.isCompleted;
50 38
51 Future get ready => _readyCompleter.future; 39 Future get ready => _readyCompleter.future;
52 final _readyCompleter = new Completer(); 40 final _readyCompleter = new Completer();
53 41
(...skipping 19 matching lines...) Expand all
73 /// This is separate from [_subscriptions] because this stream occasionally 61 /// This is separate from [_subscriptions] because this stream occasionally
74 /// needs to be resubscribed in order to work around issue 14849. 62 /// needs to be resubscribed in order to work around issue 14849.
75 StreamSubscription<FileSystemEvent> _watchSubscription; 63 StreamSubscription<FileSystemEvent> _watchSubscription;
76 64
77 /// A set of subscriptions that this watcher subscribes to. 65 /// A set of subscriptions that this watcher subscribes to.
78 /// 66 ///
79 /// These are gathered together so that they may all be canceled when the 67 /// These are gathered together so that they may all be canceled when the
80 /// watcher is closed. This does not include [_watchSubscription]. 68 /// watcher is closed. This does not include [_watchSubscription].
81 final _subscriptions = new Set<StreamSubscription>(); 69 final _subscriptions = new Set<StreamSubscription>();
82 70
83 _MacOSDirectoryWatcher(String directory, int parentId) 71 _MacOSDirectoryWatcher(String directory)
84 : directory = directory, 72 : directory = directory,
85 _files = new PathSet(directory), 73 _files = new PathSet(directory) {
86 _id = "$parentId/${_count++}" {
87 _startWatch(); 74 _startWatch();
88 75
89 _listen(new Directory(directory).list(recursive: true), 76 _listen(new Directory(directory).list(recursive: true),
90 (entity) { 77 (entity) {
91 if (entity is! Directory) _files.add(entity.path); 78 if (entity is! Directory) _files.add(entity.path);
92 }, 79 },
93 onError: _emitError, 80 onError: _emitError,
94 onDone: () { 81 onDone: _readyCompleter.complete,
95 if (MacOSDirectoryWatcher.logDebugInfo) {
96 print("[$_id] watcher is ready, known files:");
97 for (var file in _files.toSet()) {
98 print("[$_id] ${p.relative(file, from: directory)}");
99 }
100 }
101 _readyCompleter.complete();
102 },
103 cancelOnError: true); 82 cancelOnError: true);
104 } 83 }
105 84
106 void close() { 85 void close() {
107 if (MacOSDirectoryWatcher.logDebugInfo) {
108 print("[$_id] watcher is closed");
109 }
110 for (var subscription in _subscriptions) { 86 for (var subscription in _subscriptions) {
111 subscription.cancel(); 87 subscription.cancel();
112 } 88 }
113 _subscriptions.clear(); 89 _subscriptions.clear();
114 if (_watchSubscription != null) _watchSubscription.cancel(); 90 if (_watchSubscription != null) _watchSubscription.cancel();
115 _watchSubscription = null; 91 _watchSubscription = null;
116 _eventsController.close(); 92 _eventsController.close();
117 } 93 }
118 94
119 /// The callback that's run when [Directory.watch] emits a batch of events. 95 /// The callback that's run when [Directory.watch] emits a batch of events.
120 void _onBatch(List<FileSystemEvent> batch) { 96 void _onBatch(List<FileSystemEvent> batch) {
121 if (MacOSDirectoryWatcher.logDebugInfo) {
122 print("[$_id] ======== batch:");
123 for (var event in batch) {
124 print("[$_id] ${_formatEvent(event)}");
125 }
126
127 print("[$_id] known files:");
128 for (var file in _files.toSet()) {
129 print("[$_id] ${p.relative(file, from: directory)}");
130 }
131 }
132
133 batches++; 97 batches++;
134 98
135 _sortEvents(batch).forEach((path, events) { 99 _sortEvents(batch).forEach((path, events) {
136 var relativePath = p.relative(path, from: directory);
137 if (MacOSDirectoryWatcher.logDebugInfo) {
138 print("[$_id] events for $relativePath:\n");
139 for (var event in events) {
140 print("[$_id] ${_formatEvent(event)}");
141 }
142 }
143
144 var canonicalEvent = _canonicalEvent(events); 100 var canonicalEvent = _canonicalEvent(events);
145 events = canonicalEvent == null ? 101 events = canonicalEvent == null ?
146 _eventsBasedOnFileSystem(path) : [canonicalEvent]; 102 _eventsBasedOnFileSystem(path) : [canonicalEvent];
147 if (MacOSDirectoryWatcher.logDebugInfo) {
148 print("[$_id] canonical event for $relativePath: "
149 "${_formatEvent(canonicalEvent)}");
150 print("[$_id] actionable events for $relativePath: "
151 "${events.map(_formatEvent)}");
152 }
153 103
154 for (var event in events) { 104 for (var event in events) {
155 if (event is FileSystemCreateEvent) { 105 if (event is FileSystemCreateEvent) {
156 if (!event.isDirectory) { 106 if (!event.isDirectory) {
157 _emitEvent(ChangeType.ADD, path); 107 _emitEvent(ChangeType.ADD, path);
158 _files.add(path); 108 _files.add(path);
159 continue; 109 continue;
160 } 110 }
161 111
162 _listen(new Directory(path).list(recursive: true), (entity) { 112 _listen(new Directory(path).list(recursive: true), (entity) {
163 if (entity is Directory) return; 113 if (entity is Directory) return;
164 _emitEvent(ChangeType.ADD, entity.path); 114 _emitEvent(ChangeType.ADD, entity.path);
165 _files.add(entity.path); 115 _files.add(entity.path);
166 }, onError: (e, stackTrace) { 116 }, onError: _emitError, cancelOnError: true);
167 if (MacOSDirectoryWatcher.logDebugInfo) {
168 print("[$_id] got error listing $relativePath: $e");
169 }
170 _emitError(e, stackTrace);
171 }, cancelOnError: true);
172 } else if (event is FileSystemModifyEvent) { 117 } else if (event is FileSystemModifyEvent) {
173 assert(!event.isDirectory); 118 assert(!event.isDirectory);
174 _emitEvent(ChangeType.MODIFY, path); 119 _emitEvent(ChangeType.MODIFY, path);
175 } else { 120 } else {
176 assert(event is FileSystemDeleteEvent); 121 assert(event is FileSystemDeleteEvent);
177 for (var removedPath in _files.remove(path)) { 122 for (var removedPath in _files.remove(path)) {
178 _emitEvent(ChangeType.REMOVE, removedPath); 123 _emitEvent(ChangeType.REMOVE, removedPath);
179 } 124 }
180 } 125 }
181 } 126 }
182 }); 127 });
183
184 if (MacOSDirectoryWatcher.logDebugInfo) {
185 print("[$_id] ======== batch complete");
186 }
187 } 128 }
188 129
189 /// Sort all the events in a batch into sets based on their path. 130 /// Sort all the events in a batch into sets based on their path.
190 /// 131 ///
191 /// A single input event may result in multiple events in the returned map; 132 /// A single input event may result in multiple events in the returned map;
192 /// for example, a MOVE event becomes a DELETE event for the source and a 133 /// for example, a MOVE event becomes a DELETE event for the source and a
193 /// CREATE event for the destination. 134 /// CREATE event for the destination.
194 /// 135 ///
195 /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it 136 /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it
196 /// contain any events relating to [directory]. 137 /// contain any events relating to [directory].
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 /// This returns a list whose order should be reflected in the events emitted 254 /// This returns a list whose order should be reflected in the events emitted
314 /// to the user, unlike the batched events from [Directory.watch]. The 255 /// to the user, unlike the batched events from [Directory.watch]. The
315 /// returned list may be empty, indicating that no changes occurred to [path] 256 /// returned list may be empty, indicating that no changes occurred to [path]
316 /// (probably indicating that it was created and then immediately deleted). 257 /// (probably indicating that it was created and then immediately deleted).
317 List<FileSystemEvent> _eventsBasedOnFileSystem(String path) { 258 List<FileSystemEvent> _eventsBasedOnFileSystem(String path) {
318 var fileExisted = _files.contains(path); 259 var fileExisted = _files.contains(path);
319 var dirExisted = _files.containsDir(path); 260 var dirExisted = _files.containsDir(path);
320 var fileExists = new File(path).existsSync(); 261 var fileExists = new File(path).existsSync();
321 var dirExists = new Directory(path).existsSync(); 262 var dirExists = new Directory(path).existsSync();
322 263
323 if (MacOSDirectoryWatcher.logDebugInfo) {
324 print("[$_id] file existed: $fileExisted");
325 print("[$_id] dir existed: $dirExisted");
326 print("[$_id] file exists: $fileExists");
327 print("[$_id] dir exists: $dirExists");
328 }
329
330 var events = []; 264 var events = [];
331 if (fileExisted) { 265 if (fileExisted) {
332 if (fileExists) { 266 if (fileExists) {
333 events.add(new ConstructableFileSystemModifyEvent(path, false, false)); 267 events.add(new ConstructableFileSystemModifyEvent(path, false, false));
334 } else { 268 } else {
335 events.add(new ConstructableFileSystemDeleteEvent(path, false)); 269 events.add(new ConstructableFileSystemDeleteEvent(path, false));
336 } 270 }
337 } else if (dirExisted) { 271 } else if (dirExisted) {
338 if (dirExists) { 272 if (dirExists) {
339 // If we got contradictory events for a directory that used to exist and 273 // If we got contradictory events for a directory that used to exist and
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 323
390 /// Emit an event with the given [type] and [path]. 324 /// Emit an event with the given [type] and [path].
391 void _emitEvent(ChangeType type, String path) { 325 void _emitEvent(ChangeType type, String path) {
392 if (!isReady) return; 326 if (!isReady) return;
393 327
394 // Don't emit ADD events for files that we already know about. Such an event 328 // Don't emit ADD events for files that we already know about. Such an event
395 // probably comes from FSEvents reporting an add that happened prior to the 329 // probably comes from FSEvents reporting an add that happened prior to the
396 // watch beginning. 330 // watch beginning.
397 if (type == ChangeType.ADD && _files.contains(path)) return; 331 if (type == ChangeType.ADD && _files.contains(path)) return;
398 332
399 if (MacOSDirectoryWatcher.logDebugInfo) {
400 print("[$_id] emitting $type ${p.relative(path, from: directory)}");
401 }
402
403 _eventsController.add(new WatchEvent(type, path)); 333 _eventsController.add(new WatchEvent(type, path));
404 } 334 }
405 335
406 /// Emit an error, then close the watcher. 336 /// Emit an error, then close the watcher.
407 void _emitError(error, StackTrace stackTrace) { 337 void _emitError(error, StackTrace stackTrace) {
408 _eventsController.addError(error, stackTrace); 338 _eventsController.addError(error, stackTrace);
409 close(); 339 close();
410 } 340 }
411 341
412 /// Like [Stream.listen], but automatically adds the subscription to 342 /// Like [Stream.listen], but automatically adds the subscription to
413 /// [_subscriptions] so that it can be canceled when [close] is called. 343 /// [_subscriptions] so that it can be canceled when [close] is called.
414 void _listen(Stream stream, void onData(event), {Function onError, 344 void _listen(Stream stream, void onData(event), {Function onError,
415 void onDone(), bool cancelOnError}) { 345 void onDone(), bool cancelOnError}) {
416 var subscription; 346 var subscription;
417 subscription = stream.listen(onData, onError: onError, onDone: () { 347 subscription = stream.listen(onData, onError: onError, onDone: () {
418 _subscriptions.remove(subscription); 348 _subscriptions.remove(subscription);
419 if (onDone != null) onDone(); 349 if (onDone != null) onDone();
420 }, cancelOnError: cancelOnError); 350 }, cancelOnError: cancelOnError);
421 _subscriptions.add(subscription); 351 _subscriptions.add(subscription);
422 } 352 }
423
424 // TODO(nweiz): remove this when issue 15042 is fixed.
425 /// Return a human-friendly string representation of [event].
426 String _formatEvent(FileSystemEvent event) {
427 if (event == null) return 'null';
428
429 var path = p.relative(event.path, from: directory);
430 var type = event.isDirectory ? 'directory' : 'file';
431 if (event is FileSystemCreateEvent) {
432 return "create $type $path";
433 } else if (event is FileSystemDeleteEvent) {
434 return "delete $type $path";
435 } else if (event is FileSystemModifyEvent) {
436 return "modify $type $path";
437 } else if (event is FileSystemMoveEvent) {
438 return "move $type $path to "
439 "${p.relative(event.destination, from: directory)}";
440 }
441 }
442 } 353 }
OLDNEW
« no previous file with comments | « no previous file | pkg/watcher/test/directory_watcher/mac_os_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698