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 |