OLD | NEW |
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; | 10 import 'package:path/path.dart' as p; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 /// The subscription to the stream returned by [Directory.watch]. | 62 /// The subscription to the stream returned by [Directory.watch]. |
63 /// | 63 /// |
64 /// This is separate from [_subscriptions] because this stream occasionally | 64 /// This is separate from [_subscriptions] because this stream occasionally |
65 /// needs to be resubscribed in order to work around issue 14849. | 65 /// needs to be resubscribed in order to work around issue 14849. |
66 StreamSubscription<FileSystemEvent> _watchSubscription; | 66 StreamSubscription<FileSystemEvent> _watchSubscription; |
67 | 67 |
68 /// The subscription to the [Directory.list] call for the initial listing of | 68 /// The subscription to the [Directory.list] call for the initial listing of |
69 /// the directory to determine its initial state. | 69 /// the directory to determine its initial state. |
70 StreamSubscription<FileSystemEntity> _initialListSubscription; | 70 StreamSubscription<FileSystemEntity> _initialListSubscription; |
71 | 71 |
72 /// The subscription to the [Directory.list] call for listing the contents of | 72 /// The subscriptions to [Directory.list] calls for listing the contents of a |
73 /// a subdirectory that was moved into the watched directory. | 73 /// subdirectory that was moved into the watched directory. |
74 StreamSubscription<FileSystemEntity> _listSubscription; | 74 final _listSubscriptions = new Set<StreamSubscription<FileSystemEntity>>(); |
75 | 75 |
76 /// The timer for tracking how long we wait for an initial batch of bogus | 76 /// The timer for tracking how long we wait for an initial batch of bogus |
77 /// events (see issue 14373). | 77 /// events (see issue 14373). |
78 Timer _bogusEventTimer; | 78 Timer _bogusEventTimer; |
79 | 79 |
80 _MacOSDirectoryWatcher(String directory, int parentId) | 80 _MacOSDirectoryWatcher(String directory, int parentId) |
81 : directory = directory, | 81 : directory = directory, |
82 _files = new PathSet(directory), | 82 _files = new PathSet(directory), |
83 _id = "$parentId/${_count++}" { | 83 _id = "$parentId/${_count++}" { |
84 _startWatch(); | 84 _startWatch(); |
(...skipping 21 matching lines...) Expand all Loading... |
106 _readyCompleter.complete(); | 106 _readyCompleter.complete(); |
107 }); | 107 }); |
108 } | 108 } |
109 | 109 |
110 void close() { | 110 void close() { |
111 if (MacOSDirectoryWatcher.logDebugInfo) { | 111 if (MacOSDirectoryWatcher.logDebugInfo) { |
112 print("[$_id] watcher is closed\n${new Chain.current().terse}"); | 112 print("[$_id] watcher is closed\n${new Chain.current().terse}"); |
113 } | 113 } |
114 if (_watchSubscription != null) _watchSubscription.cancel(); | 114 if (_watchSubscription != null) _watchSubscription.cancel(); |
115 if (_initialListSubscription != null) _initialListSubscription.cancel(); | 115 if (_initialListSubscription != null) _initialListSubscription.cancel(); |
116 if (_listSubscription != null) _listSubscription.cancel(); | |
117 _watchSubscription = null; | 116 _watchSubscription = null; |
118 _initialListSubscription = null; | 117 _initialListSubscription = null; |
119 _listSubscription = null; | 118 |
| 119 for (var subscription in _listSubscriptions) { |
| 120 subscription.cancel(); |
| 121 } |
| 122 _listSubscriptions.clear(); |
| 123 |
120 _eventsController.close(); | 124 _eventsController.close(); |
121 } | 125 } |
122 | 126 |
123 /// The callback that's run when [Directory.watch] emits a batch of events. | 127 /// The callback that's run when [Directory.watch] emits a batch of events. |
124 void _onBatch(List<FileSystemEvent> batch) { | 128 void _onBatch(List<FileSystemEvent> batch) { |
125 if (MacOSDirectoryWatcher.logDebugInfo) { | 129 if (MacOSDirectoryWatcher.logDebugInfo) { |
126 print("[$_id] ======== batch:"); | 130 print("[$_id] ======== batch:"); |
127 for (var event in batch) { | 131 for (var event in batch) { |
128 print("[$_id] ${_formatEvent(event)}"); | 132 print("[$_id] ${_formatEvent(event)}"); |
129 } | 133 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 // that happened prior to the watch beginning. | 188 // that happened prior to the watch beginning. |
185 if (_files.contains(path)) continue; | 189 if (_files.contains(path)) continue; |
186 | 190 |
187 _emitEvent(ChangeType.ADD, path); | 191 _emitEvent(ChangeType.ADD, path); |
188 _files.add(path); | 192 _files.add(path); |
189 continue; | 193 continue; |
190 } | 194 } |
191 | 195 |
192 if (_files.containsDir(path)) continue; | 196 if (_files.containsDir(path)) continue; |
193 | 197 |
194 var stream = Chain.track(new Directory(path).list(recursive: true)); | 198 var subscription; |
195 _listSubscription = stream.listen((entity) { | 199 subscription = Chain.track(new Directory(path).list(recursive: true)) |
| 200 .listen((entity) { |
196 if (entity is Directory) return; | 201 if (entity is Directory) return; |
197 if (_files.contains(path)) return; | 202 if (_files.contains(path)) return; |
198 | 203 |
199 _emitEvent(ChangeType.ADD, entity.path); | 204 _emitEvent(ChangeType.ADD, entity.path); |
200 _files.add(entity.path); | 205 _files.add(entity.path); |
201 }, onError: (e, stackTrace) { | 206 }, onError: (e, stackTrace) { |
202 if (MacOSDirectoryWatcher.logDebugInfo) { | 207 if (MacOSDirectoryWatcher.logDebugInfo) { |
203 print("[$_id] got error listing $relativePath: $e"); | 208 print("[$_id] got error listing $relativePath: $e"); |
204 } | 209 } |
205 _emitError(e, stackTrace); | 210 _emitError(e, stackTrace); |
| 211 }, onDone: () { |
| 212 _listSubscriptions.remove(subscription); |
206 }, cancelOnError: true); | 213 }, cancelOnError: true); |
| 214 _listSubscriptions.add(subscription); |
207 } else if (event is FileSystemModifyEvent) { | 215 } else if (event is FileSystemModifyEvent) { |
208 assert(!event.isDirectory); | 216 assert(!event.isDirectory); |
209 _emitEvent(ChangeType.MODIFY, path); | 217 _emitEvent(ChangeType.MODIFY, path); |
210 } else { | 218 } else { |
211 assert(event is FileSystemDeleteEvent); | 219 assert(event is FileSystemDeleteEvent); |
212 for (var removedPath in _files.remove(path)) { | 220 for (var removedPath in _files.remove(path)) { |
213 _emitEvent(ChangeType.REMOVE, removedPath); | 221 _emitEvent(ChangeType.REMOVE, removedPath); |
214 } | 222 } |
215 } | 223 } |
216 } | 224 } |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 } else if (event is FileSystemDeleteEvent) { | 496 } else if (event is FileSystemDeleteEvent) { |
489 return "delete $type $path"; | 497 return "delete $type $path"; |
490 } else if (event is FileSystemModifyEvent) { | 498 } else if (event is FileSystemModifyEvent) { |
491 return "modify $type $path"; | 499 return "modify $type $path"; |
492 } else if (event is FileSystemMoveEvent) { | 500 } else if (event is FileSystemMoveEvent) { |
493 return "move $type $path to " | 501 return "move $type $path to " |
494 "${p.relative(event.destination, from: directory)}"; | 502 "${p.relative(event.destination, from: directory)}"; |
495 } | 503 } |
496 } | 504 } |
497 } | 505 } |
OLD | NEW |