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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 parts.removeLast(); | 55 parts.removeLast(); |
| 56 } | 56 } |
| 57 parts.add(piece); | 57 parts.add(piece); |
| 58 } | 58 } |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 | 61 |
| 62 return Strings.join(parts, Platform.pathSeparator); | 62 return Strings.join(parts, Platform.pathSeparator); |
| 63 } | 63 } |
| 64 | 64 |
| 65 List<String> splitPath(path) => _sanitizePath(path).split('/'); | |
|
Bob Nystrom
2012/11/30 21:31:59
Doc comment.
nweiz
2012/11/30 21:37:45
Done.
| |
| 66 | |
| 65 /** | 67 /** |
| 66 * Gets the basename, the file name without any leading directory path, for | 68 * Gets the basename, the file name without any leading directory path, for |
| 67 * [file], which can either be a [String], [File], or [Directory]. | 69 * [file], which can either be a [String], [File], or [Directory]. |
| 68 */ | 70 */ |
| 69 // TODO(rnystrom): Copied from file_system (so that we don't have to add | 71 // TODO(rnystrom): Copied from file_system (so that we don't have to add |
| 70 // file_system to the SDK). Should unify. | 72 // file_system to the SDK). Should unify. |
| 71 String basename(file) { | 73 String basename(file) { |
| 72 file = _sanitizePath(file); | 74 file = _sanitizePath(file); |
| 73 | 75 |
| 74 int lastSlash = file.lastIndexOf('/', file.length); | 76 int lastSlash = file.lastIndexOf('/', file.length); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 * [Directory]. Returns a [Future] that completes when the deletion is done. | 240 * [Directory]. Returns a [Future] that completes when the deletion is done. |
| 239 */ | 241 */ |
| 240 Future<Directory> deleteDir(dir) { | 242 Future<Directory> deleteDir(dir) { |
| 241 dir = _getDirectory(dir); | 243 dir = _getDirectory(dir); |
| 242 return dir.delete(recursive: true); | 244 return dir.delete(recursive: true); |
| 243 } | 245 } |
| 244 | 246 |
| 245 /** | 247 /** |
| 246 * Asynchronously lists the contents of [dir], which can be a [String] directory | 248 * Asynchronously lists the contents of [dir], which can be a [String] directory |
| 247 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents | 249 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents |
| 248 * (defaults to `false`). If [includeHiddenFiles] is `true`, includes files | 250 * (defaults to `false`). If [includeHiddenFiles] is `true`, includes files and |
| 249 * beginning with `.` (defaults to `false`). | 251 * directories beginning with `.` (defaults to `false`). |
| 250 */ | 252 */ |
| 251 Future<List<String>> listDir(dir, | 253 Future<List<String>> listDir(dir, |
| 252 {bool recursive: false, bool includeHiddenFiles: false}) { | 254 {bool recursive: false, bool includeHiddenFiles: false}) { |
| 253 final completer = new Completer<List<String>>(); | 255 final completer = new Completer<List<String>>(); |
| 254 final contents = <String>[]; | 256 final contents = <String>[]; |
| 255 | 257 |
| 256 dir = _getDirectory(dir); | 258 dir = _getDirectory(dir); |
| 257 var lister = dir.list(recursive: recursive); | 259 var lister = dir.list(recursive: recursive); |
| 258 | 260 |
| 259 lister.onDone = (done) { | 261 lister.onDone = (done) { |
| 260 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile | 262 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile |
| 261 // aren't guaranteed to be called in a certain order. So far, they seem to. | 263 // aren't guaranteed to be called in a certain order. So far, they seem to. |
| 262 if (done) completer.complete(contents); | 264 if (done) completer.complete(contents); |
| 263 }; | 265 }; |
| 264 | 266 |
| 265 // TODO(nweiz): remove this when issue 4061 is fixed. | 267 // TODO(nweiz): remove this when issue 4061 is fixed. |
| 266 var stackTrace; | 268 var stackTrace; |
| 267 try { | 269 try { |
| 268 throw ""; | 270 throw ""; |
| 269 } catch (_, localStackTrace) { | 271 } catch (_, localStackTrace) { |
| 270 stackTrace = localStackTrace; | 272 stackTrace = localStackTrace; |
| 271 } | 273 } |
| 272 | 274 |
| 273 lister.onError = (error) => completer.completeException(error, stackTrace); | 275 lister.onError = (error) => completer.completeException(error, stackTrace); |
| 274 lister.onDir = (file) => contents.add(file); | 276 lister.onDir = (file) { |
| 277 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | |
| 278 contents.add(file); | |
| 279 }; | |
| 275 lister.onFile = (file) { | 280 lister.onFile = (file) { |
| 276 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 281 if (!includeHiddenFiles && basename(file).startsWith('.')) return; |
| 277 contents.add(file); | 282 contents.add(file); |
| 278 }; | 283 }; |
| 279 | 284 |
| 280 return completer.future; | 285 return completer.future; |
| 281 } | 286 } |
| 282 | 287 |
| 283 /** | 288 /** |
| 284 * Asynchronously determines if [dir], which can be a [String] directory path | 289 * Asynchronously determines if [dir], which can be a [String] directory path |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 return new Future.immediate(to); | 370 return new Future.immediate(to); |
| 366 }); | 371 }); |
| 367 } | 372 } |
| 368 | 373 |
| 369 /// Given [entry] which may be a [String], [File], or [Directory] relative to | 374 /// Given [entry] which may be a [String], [File], or [Directory] relative to |
| 370 /// the current working directory, returns its full canonicalized path. | 375 /// the current working directory, returns its full canonicalized path. |
| 371 String getFullPath(entry) { | 376 String getFullPath(entry) { |
| 372 var path = _getPath(entry); | 377 var path = _getPath(entry); |
| 373 | 378 |
| 374 // Don't do anything if it's already absolute. | 379 // Don't do anything if it's already absolute. |
| 375 if (Platform.operatingSystem == 'windows') { | 380 if (isAbsolute(path)) return path; |
| 376 // An absolute path on Windows is either UNC (two leading backslashes), | |
| 377 // or a drive letter followed by a colon and a slash. | |
| 378 var ABSOLUTE = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])'); | |
| 379 if (ABSOLUTE.hasMatch(path)) return path; | |
| 380 } else { | |
| 381 if (path.startsWith('/')) return path; | |
| 382 } | |
| 383 | 381 |
| 384 // Using Path.join here instead of File().fullPathSync() because the former | 382 // Using Path.join here instead of File().fullPathSync() because the former |
| 385 // does not require an actual file to exist at that path. | 383 // does not require an actual file to exist at that path. |
| 386 return new Path.fromNative(currentWorkingDir).join(new Path(path)) | 384 return new Path.fromNative(currentWorkingDir).join(new Path(path)) |
| 387 .toNativePath(); | 385 .toNativePath(); |
| 388 } | 386 } |
| 389 | 387 |
| 388 bool isAbsolute(entry) => _splitAbsolute(entry).first != null; | |
| 389 | |
| 390 Pair<String, String> _splitAbsolute(entry) { | |
| 391 var path = _getPath(entry); | |
| 392 | |
| 393 if (Platform.operatingSystem != 'windows') { | |
| 394 return !path.startsWith('/') ? new Pair(null, path) | |
| 395 : new Pair('/', path.substring(1)); | |
| 396 } | |
| 397 | |
| 398 // An absolute path on Windows is either UNC (two leading backslashes), | |
| 399 // or a drive letter followed by a colon and a slash. | |
| 400 var match = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])').firstMatch(path); | |
| 401 return match == null ? new Pair(null, path) | |
| 402 : new Pair(match.group(0), path.substring(match.end)); | |
| 403 } | |
| 404 | |
| 390 /// Resolves [path] relative to the location of pub.dart. | 405 /// Resolves [path] relative to the location of pub.dart. |
| 391 String relativeToPub(String path) { | 406 String relativeToPub(String path) { |
| 392 var scriptPath = new File(new Options().script).fullPathSync(); | 407 var scriptPath = new File(new Options().script).fullPathSync(); |
| 393 | 408 |
| 394 // Walk up until we hit the "util(s)" directory. This lets us figure out where | 409 // Walk up until we hit the "util(s)" directory. This lets us figure out where |
| 395 // we are if this function is called from pub.dart, or one of the tests, | 410 // we are if this function is called from pub.dart, or one of the tests, |
| 396 // which also live under "utils", or from the SDK where pub is in "util". | 411 // which also live under "utils", or from the SDK where pub is in "util". |
| 397 var utilDir = new Path.fromNative(scriptPath).directoryPath; | 412 var utilDir = new Path.fromNative(scriptPath).directoryPath; |
| 398 while (utilDir.filename != 'utils' && utilDir.filename != 'util') { | 413 while (utilDir.filename != 'utils' && utilDir.filename != 'util') { |
| 399 if (utilDir.filename == '') throw 'Could not find path to pub.'; | 414 if (utilDir.filename == '') throw 'Could not find path to pub.'; |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 943 if (entry is String) return entry; | 958 if (entry is String) return entry; |
| 944 if (entry is File) return entry.name; | 959 if (entry is File) return entry.name; |
| 945 if (entry is Directory) return entry.path; | 960 if (entry is Directory) return entry.path; |
| 946 throw 'Entry $entry is not a supported type.'; | 961 throw 'Entry $entry is not a supported type.'; |
| 947 } | 962 } |
| 948 | 963 |
| 949 /// Gets the path string for [entry] as in [_getPath], but normalizes | 964 /// Gets the path string for [entry] as in [_getPath], but normalizes |
| 950 /// backslashes to forward slashes on Windows. | 965 /// backslashes to forward slashes on Windows. |
| 951 String _sanitizePath(entry) { | 966 String _sanitizePath(entry) { |
| 952 entry = _getPath(entry); | 967 entry = _getPath(entry); |
| 953 if (Platform.operatingSystem == 'windows') { | 968 if (Platform.operatingSystem != 'windows') return entry; |
| 954 entry = entry.replaceAll('\\', '/'); | 969 |
| 955 } | 970 var split = _splitAbsolute(entry); |
| 956 return entry; | 971 if (split.first == null) return split.last.replaceAll('\\', '/'); |
| 972 | |
| 973 // For absolute Windows paths, we don't want the prefix (either "\\" or e.g. | |
| 974 // "C:\") to look like a normal path component, so we ensure that it only | |
| 975 // contains backslashes. | |
| 976 return '${split.first.replaceAll('/', '\\')}' | |
| 977 '${split.last.replaceAll('\\', '/')}'; | |
| 957 } | 978 } |
| 958 | 979 |
| 959 /** | 980 /** |
| 960 * Gets a [Directory] for [entry], which can either already be one, or be a | 981 * Gets a [Directory] for [entry], which can either already be one, or be a |
| 961 * [String]. | 982 * [String]. |
| 962 */ | 983 */ |
| 963 Directory _getDirectory(entry) { | 984 Directory _getDirectory(entry) { |
| 964 if (entry is Directory) return entry; | 985 if (entry is Directory) return entry; |
| 965 return new Directory(entry); | 986 return new Directory(entry); |
| 966 } | 987 } |
| 967 | 988 |
| 968 /** | 989 /** |
| 969 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 990 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
| 970 */ | 991 */ |
| 971 Uri _getUri(uri) { | 992 Uri _getUri(uri) { |
| 972 if (uri is Uri) return uri; | 993 if (uri is Uri) return uri; |
| 973 return new Uri.fromString(uri); | 994 return new Uri.fromString(uri); |
| 974 } | 995 } |
| OLD | NEW |