Chromium Code Reviews| 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, | 
| 257 Set<String> _listedDirectories}) { | |
| 
 
Bob Nystrom
2012/12/17 23:42:33
Instead of making this an optional parameter, how
 
nweiz
2012/12/18 18:38:43
Done.
 
 | |
| 256 final completer = new Completer<List<String>>(); | 258 final completer = new Completer<List<String>>(); | 
| 257 final contents = <String>[]; | 259 final contents = <String>[]; | 
| 258 | 260 | 
| 261 // Avoid recursive symlinks. | |
| 262 if (_listedDirectories == null) _listedDirectories = new Set<String>(); | |
| 263 var resolvedPath = new File(dir).fullPathSync(); | |
| 264 if (_listedDirectories.contains(resolvedPath)) { | |
| 265 return new Future.immediate([]); | |
| 266 } | |
| 267 _listedDirectories = new Set<String>.from(_listedDirectories); | |
| 268 _listedDirectories.add(resolvedPath); | |
| 269 | |
| 259 dir = _getDirectory(dir); | 270 dir = _getDirectory(dir); | 
| 260 log.io("Listing directory ${dir.path}."); | 271 log.io("Listing directory ${dir.path}."); | 
| 261 var lister = dir.list(recursive: recursive); | 272 var lister = dir.list(); | 
| 262 | 273 | 
| 263 lister.onDone = (done) { | 274 lister.onDone = (done) { | 
| 264 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile | 275 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile | 
| 265 // aren't guaranteed to be called in a certain order. So far, they seem to. | 276 // aren't guaranteed to be called in a certain order. So far, they seem to. | 
| 266 if (done) { | 277 if (done) { | 
| 267 log.fine("Listed directory ${dir.path}:\n" | 278 log.fine("Listed directory ${dir.path}:\n" | 
| 268 "${Strings.join(contents, '\n')}"); | 279 "${Strings.join(contents, '\n')}"); | 
| 269 completer.complete(contents); | 280 completer.complete(contents); | 
| 270 } | 281 } | 
| 271 }; | 282 }; | 
| 272 | 283 | 
| 273 // TODO(nweiz): remove this when issue 4061 is fixed. | 284 // TODO(nweiz): remove this when issue 4061 is fixed. | 
| 274 var stackTrace; | 285 var stackTrace; | 
| 275 try { | 286 try { | 
| 276 throw ""; | 287 throw ""; | 
| 277 } catch (_, localStackTrace) { | 288 } catch (_, localStackTrace) { | 
| 278 stackTrace = localStackTrace; | 289 stackTrace = localStackTrace; | 
| 279 } | 290 } | 
| 280 | 291 | 
| 292 var children = []; | |
| 281 lister.onError = (error) => completer.completeException(error, stackTrace); | 293 lister.onError = (error) => completer.completeException(error, stackTrace); | 
| 282 lister.onDir = (file) { | 294 lister.onDir = (file) { | 
| 283 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 295 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 
| 296 file = join(dir, basename(file)); | |
| 284 contents.add(file); | 297 contents.add(file); | 
| 298 | |
| 299 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. | |
| 300 if (recursive) { | |
| 301 children.add(listDir(file, | |
| 302 recursive: true, | |
| 303 includeHiddenFiles: includeHiddenFiles, | |
| 304 _listedDirectories: _listedDirectories)); | |
| 305 } | |
| 285 }; | 306 }; | 
| 286 lister.onFile = (file) { | 307 lister.onFile = (file) { | 
| 287 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 308 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 
| 288 contents.add(file); | 309 contents.add(join(dir, basename(file))); | 
| 289 }; | 310 }; | 
| 290 | 311 | 
| 291 return completer.future; | 312 return completer.future.chain((contents) { | 
| 313 return Futures.wait(children).transform((childContents) { | |
| 314 contents.addAll(flatten(childContents)); | |
| 315 return contents; | |
| 316 }); | |
| 317 }); | |
| 292 } | 318 } | 
| 293 | 319 | 
| 294 /** | 320 /** | 
| 295 * Asynchronously determines if [dir], which can be a [String] directory path | 321 * Asynchronously determines if [dir], which can be a [String] directory path | 
| 296 * or a [Directory], exists on the file system. Returns a [Future] that | 322 * or a [Directory], exists on the file system. Returns a [Future] that | 
| 297 * completes with the result. | 323 * completes with the result. | 
| 298 */ | 324 */ | 
| 299 Future<bool> dirExists(dir) { | 325 Future<bool> dirExists(dir) { | 
| 300 dir = _getDirectory(dir); | 326 dir = _getDirectory(dir); | 
| 301 return log.ioAsync("Seeing if directory ${dir.path} exists.", | 327 return log.ioAsync("Seeing if directory ${dir.path} exists.", | 
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1067 return new Directory(entry); | 1093 return new Directory(entry); | 
| 1068 } | 1094 } | 
| 1069 | 1095 | 
| 1070 /** | 1096 /** | 
| 1071 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 1097 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 
| 1072 */ | 1098 */ | 
| 1073 Uri _getUri(uri) { | 1099 Uri _getUri(uri) { | 
| 1074 if (uri is Uri) return uri; | 1100 if (uri is Uri) return uri; | 
| 1075 return new Uri.fromString(uri); | 1101 return new Uri.fromString(uri); | 
| 1076 } | 1102 } | 
| OLD | NEW |