| 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 |