| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * Helper functionality to make working with IO easier. | 6 * Helper functionality to make working with IO easier. |
| 7 */ | 7 */ |
| 8 library io; | 8 library io; |
| 9 | 9 |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 * Asynchronously recursively deletes [dir], which can be a [String] or a | 238 * Asynchronously recursively deletes [dir], which can be a [String] or a |
| 239 * [Directory]. Returns a [Future] that completes when the deletion is done. | 239 * [Directory]. Returns a [Future] that completes when the deletion is done. |
| 240 */ | 240 */ |
| 241 Future<Directory> deleteDir(dir) { | 241 Future<Directory> deleteDir(dir) { |
| 242 dir = _getDirectory(dir); | 242 dir = _getDirectory(dir); |
| 243 | 243 |
| 244 return _attemptRetryable(() => log.ioAsync("delete directory ${dir.path}", | 244 return _attemptRetryable(() => log.ioAsync("delete directory ${dir.path}", |
| 245 dir.delete(recursive: true))); | 245 dir.delete(recursive: true))); |
| 246 } | 246 } |
| 247 | 247 |
| 248 /** | 248 /// Asynchronously lists the contents of [dir], which can be a [String] |
| 249 * Asynchronously lists the contents of [dir], which can be a [String] directory | 249 /// directory path or a [Directory]. If [recursive] is `true`, lists |
| 250 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents | 250 /// subdirectory contents (defaults to `false`). If [includeHiddenFiles] is |
| 251 * (defaults to `false`). If [includeHiddenFiles] is `true`, includes files and | 251 /// `true`, includes files and directories beginning with `.` (defaults to |
| 252 * directories beginning with `.` (defaults to `false`). | 252 /// `false`). |
| 253 */ | 253 /// |
| 254 /// If [dir] is a string, the returned paths are guaranteed to begin with it. |
| 254 Future<List<String>> listDir(dir, | 255 Future<List<String>> listDir(dir, |
| 255 {bool recursive: false, bool includeHiddenFiles: false}) { | 256 {bool recursive: false, bool includeHiddenFiles: false}) { |
| 256 final completer = new Completer<List<String>>(); | 257 Future<List<String>> doList(Directory dir, Set<String> listedDirectories) { |
| 257 final contents = <String>[]; | 258 var contents = <String>[]; |
| 259 var completer = new Completer<List<String>>(); |
| 258 | 260 |
| 259 dir = _getDirectory(dir); | 261 // Avoid recursive symlinks. |
| 260 log.io("Listing directory ${dir.path}."); | 262 var resolvedPath = new File(dir.path).fullPathSync(); |
| 261 var lister = dir.list(recursive: recursive); | 263 if (listedDirectories.contains(resolvedPath)) { |
| 264 return new Future.immediate([]); |
| 265 } |
| 266 listedDirectories = new Set<String>.from(listedDirectories); |
| 267 listedDirectories.add(resolvedPath); |
| 262 | 268 |
| 263 lister.onDone = (done) { | 269 log.io("Listing directory ${dir.path}."); |
| 264 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile | 270 var lister = dir.list(); |
| 265 // aren't guaranteed to be called in a certain order. So far, they seem to. | 271 |
| 266 if (done) { | 272 lister.onDone = (done) { |
| 267 log.fine("Listed directory ${dir.path}:\n" | 273 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile |
| 268 "${Strings.join(contents, '\n')}"); | 274 // aren't guaranteed to be called in a certain order. So far, they seem to
. |
| 269 completer.complete(contents); | 275 if (done) { |
| 276 log.fine("Listed directory ${dir.path}:\n" |
| 277 "${Strings.join(contents, '\n')}"); |
| 278 completer.complete(contents); |
| 279 } |
| 280 }; |
| 281 |
| 282 // TODO(nweiz): remove this when issue 4061 is fixed. |
| 283 var stackTrace; |
| 284 try { |
| 285 throw ""; |
| 286 } catch (_, localStackTrace) { |
| 287 stackTrace = localStackTrace; |
| 270 } | 288 } |
| 271 }; | |
| 272 | 289 |
| 273 // TODO(nweiz): remove this when issue 4061 is fixed. | 290 var children = []; |
| 274 var stackTrace; | 291 lister.onError = (error) => completer.completeException(error, stackTrace); |
| 275 try { | 292 lister.onDir = (file) { |
| 276 throw ""; | 293 if (!includeHiddenFiles && basename(file).startsWith('.')) return; |
| 277 } catch (_, localStackTrace) { | 294 file = join(dir, basename(file)); |
| 278 stackTrace = localStackTrace; | 295 contents.add(file); |
| 296 |
| 297 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. |
| 298 if (recursive) { |
| 299 children.add(doList(new Directory(file), listedDirectories)); |
| 300 } |
| 301 }; |
| 302 lister.onFile = (file) { |
| 303 if (!includeHiddenFiles && basename(file).startsWith('.')) return; |
| 304 contents.add(join(dir, basename(file))); |
| 305 }; |
| 306 |
| 307 return completer.future.chain((contents) { |
| 308 return Futures.wait(children).transform((childContents) { |
| 309 contents.addAll(flatten(childContents)); |
| 310 return contents; |
| 311 }); |
| 312 }); |
| 279 } | 313 } |
| 280 | 314 |
| 281 lister.onError = (error) => completer.completeException(error, stackTrace); | 315 return doList(_getDirectory(dir), new Set<String>()); |
| 282 lister.onDir = (file) { | |
| 283 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | |
| 284 contents.add(file); | |
| 285 }; | |
| 286 lister.onFile = (file) { | |
| 287 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | |
| 288 contents.add(file); | |
| 289 }; | |
| 290 | |
| 291 return completer.future; | |
| 292 } | 316 } |
| 293 | 317 |
| 294 /** | 318 /** |
| 295 * Asynchronously determines if [dir], which can be a [String] directory path | 319 * Asynchronously determines if [dir], which can be a [String] directory path |
| 296 * or a [Directory], exists on the file system. Returns a [Future] that | 320 * or a [Directory], exists on the file system. Returns a [Future] that |
| 297 * completes with the result. | 321 * completes with the result. |
| 298 */ | 322 */ |
| 299 Future<bool> dirExists(dir) { | 323 Future<bool> dirExists(dir) { |
| 300 dir = _getDirectory(dir); | 324 dir = _getDirectory(dir); |
| 301 return log.ioAsync("Seeing if directory ${dir.path} exists.", | 325 return log.ioAsync("Seeing if directory ${dir.path} exists.", |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 return new Directory(entry); | 1017 return new Directory(entry); |
| 994 } | 1018 } |
| 995 | 1019 |
| 996 /** | 1020 /** |
| 997 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 1021 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
| 998 */ | 1022 */ |
| 999 Uri _getUri(uri) { | 1023 Uri _getUri(uri) { |
| 1000 if (uri is Uri) return uri; | 1024 if (uri is Uri) return uri; |
| 1001 return new Uri.fromString(uri); | 1025 return new Uri.fromString(uri); |
| 1002 } | 1026 } |
| OLD | NEW |