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 /// A comprehensive, cross-platform path manipulation library. | 5 /// A comprehensive, cross-platform path manipulation library. |
| 6 /// | 6 /// |
| 7 /// ## Installing ## | 7 /// ## Installing ## |
| 8 /// | 8 /// |
| 9 /// Use [pub][] to install this package. Add the following to your | 9 /// Use [pub][] to install this package. Add the following to your |
| 10 /// `pubspec.yaml` file. | 10 /// `pubspec.yaml` file. |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 /// | 294 /// |
| 295 /// // Windows | 295 /// // Windows |
| 296 /// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other' | 296 /// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other' |
| 297 /// | 297 /// |
| 298 /// // URL | 298 /// // URL |
| 299 /// path.relative('http://dartlang.org', from: 'http://pub.dartlang.org'); | 299 /// path.relative('http://dartlang.org', from: 'http://pub.dartlang.org'); |
| 300 /// // -> 'http://dartlang.org' | 300 /// // -> 'http://dartlang.org' |
| 301 String relative(String path, {String from}) => | 301 String relative(String path, {String from}) => |
| 302 _builder.relative(path, from: from); | 302 _builder.relative(path, from: from); |
| 303 | 303 |
| 304 /// Returns `true` if [child] is a path beneath `parent`, and `false` otherwise. | |
| 305 /// | |
| 306 /// path.isWithin('/root/path', '/root/path/a'); // -> true | |
| 307 /// path.isWithin('/root/path', '/root/other'); // -> false | |
|
Bob Nystrom
2013/11/14 22:58:59
Add an example for
path.isWith('/root/path', '/ro
nweiz
2013/11/14 23:51:55
Done.
| |
| 308 bool isWithin(String parent, String child) => _builder.isWithin(parent, child); | |
| 309 | |
| 304 /// Removes a trailing extension from the last part of [path]. | 310 /// Removes a trailing extension from the last part of [path]. |
| 305 /// | 311 /// |
| 306 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' | 312 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
| 307 String withoutExtension(String path) => _builder.withoutExtension(path); | 313 String withoutExtension(String path) => _builder.withoutExtension(path); |
| 308 | 314 |
| 309 /// Returns the path represented by [uri]. | 315 /// Returns the path represented by [uri]. |
| 310 /// | 316 /// |
| 311 /// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL | 317 /// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL |
| 312 /// style, this will just convert [uri] to a string. | 318 /// style, this will just convert [uri] to a string. |
| 313 /// | 319 /// |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 /// For a fixed number of parts, [join] is usually terser. | 559 /// For a fixed number of parts, [join] is usually terser. |
| 554 String joinAll(Iterable<String> parts) { | 560 String joinAll(Iterable<String> parts) { |
| 555 var buffer = new StringBuffer(); | 561 var buffer = new StringBuffer(); |
| 556 var needsSeparator = false; | 562 var needsSeparator = false; |
| 557 var isAbsoluteAndNotRootRelative = false; | 563 var isAbsoluteAndNotRootRelative = false; |
| 558 | 564 |
| 559 for (var part in parts.where((part) => part != '')) { | 565 for (var part in parts.where((part) => part != '')) { |
| 560 if (this.isRootRelative(part) && isAbsoluteAndNotRootRelative) { | 566 if (this.isRootRelative(part) && isAbsoluteAndNotRootRelative) { |
| 561 // If the new part is root-relative, it preserves the previous root but | 567 // If the new part is root-relative, it preserves the previous root but |
| 562 // replaces the path after it. | 568 // replaces the path after it. |
| 563 var oldRoot = this.rootPrefix(buffer.toString()); | 569 var parsed = _parse(part); |
| 570 parsed.root = this.rootPrefix(buffer.toString()); | |
| 571 if (parsed.root.contains(style.needsSeparatorPattern)) { | |
| 572 parsed.separators[0] = style.separator; | |
| 573 } | |
| 564 buffer.clear(); | 574 buffer.clear(); |
| 565 buffer.write(oldRoot); | 575 buffer.write(parsed); |
| 566 buffer.write(part); | |
| 567 } else if (this.isAbsolute(part)) { | 576 } else if (this.isAbsolute(part)) { |
| 568 isAbsoluteAndNotRootRelative = !this.isRootRelative(part); | 577 isAbsoluteAndNotRootRelative = !this.isRootRelative(part); |
| 569 // An absolute path discards everything before it. | 578 // An absolute path discards everything before it. |
| 570 buffer.clear(); | 579 buffer.clear(); |
| 571 buffer.write(part); | 580 buffer.write(part); |
| 572 } else { | 581 } else { |
| 573 if (part.length > 0 && part[0].contains(style.separatorPattern)) { | 582 if (part.length > 0 && part[0].contains(style.separatorPattern)) { |
| 574 // The part starts with a separator, so we don't need to add one. | 583 // The part starts with a separator, so we don't need to add one. |
| 575 } else if (needsSeparator) { | 584 } else if (needsSeparator) { |
| 576 buffer.write(separator); | 585 buffer.write(separator); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 729 pathParsed.separators..removeLast()..removeLast()..add(''); | 738 pathParsed.separators..removeLast()..removeLast()..add(''); |
| 730 } | 739 } |
| 731 | 740 |
| 732 // Make it relative. | 741 // Make it relative. |
| 733 pathParsed.root = ''; | 742 pathParsed.root = ''; |
| 734 pathParsed.removeTrailingSeparators(); | 743 pathParsed.removeTrailingSeparators(); |
| 735 | 744 |
| 736 return pathParsed.toString(); | 745 return pathParsed.toString(); |
| 737 } | 746 } |
| 738 | 747 |
| 748 /// Returns `true` if [child] is a path beneath `parent`, and `false` | |
| 749 /// otherwise. | |
| 750 /// | |
| 751 /// path.isWithin('/root/path', '/root/path/a'); // -> true | |
| 752 /// path.isWithin('/root/path', '/root/other'); // -> false | |
| 753 bool isWithin(String parent, String child) { | |
| 754 var relative; | |
| 755 try { | |
| 756 relative = this.relative(child, from: parent); | |
| 757 } on ArgumentError catch (_) { | |
|
Bob Nystrom
2013/11/14 22:58:59
relative() can throw an ArgumentError?
We really
nweiz
2013/11/14 23:51:55
Yes. If [root] is relative, you can get unresolvab
Bob Nystrom
2013/11/15 00:05:51
Right. In that case, relative() should throw a sub
nweiz
2013/11/15 01:17:50
I don't like FormatException, because nothing's be
Bob Nystrom
2013/11/15 01:44:52
I was thinking the same thing. We should document
| |
| 758 // If no relative path from [parent] to [child] is found, [child] | |
| 759 // definitely isn't a child of [parent]. | |
| 760 return false; | |
| 761 } | |
| 762 | |
| 763 var parts = this.split(relative); | |
| 764 return this.isRelative(relative) && parts.first != '..' && | |
| 765 parts.first != '.'; | |
| 766 } | |
| 767 | |
| 739 /// Removes a trailing extension from the last part of [path]. | 768 /// Removes a trailing extension from the last part of [path]. |
| 740 /// | 769 /// |
| 741 /// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' | 770 /// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
| 742 String withoutExtension(String path) { | 771 String withoutExtension(String path) { |
| 743 var parsed = _parse(path); | 772 var parsed = _parse(path); |
| 744 | 773 |
| 745 for (var i = parsed.parts.length - 1; i >= 0; i--) { | 774 for (var i = parsed.parts.length - 1; i >= 0; i--) { |
| 746 if (!parsed.parts[i].isEmpty) { | 775 if (!parsed.parts[i].isEmpty) { |
| 747 parsed.parts[i] = parsed.basenameWithoutExtension; | 776 parsed.parts[i] = parsed.basenameWithoutExtension; |
| 748 break; | 777 break; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 976 /// The style for Windows paths. | 1005 /// The style for Windows paths. |
| 977 class _WindowsStyle extends Style { | 1006 class _WindowsStyle extends Style { |
| 978 _WindowsStyle(); | 1007 _WindowsStyle(); |
| 979 | 1008 |
| 980 final name = 'windows'; | 1009 final name = 'windows'; |
| 981 final separator = '\\'; | 1010 final separator = '\\'; |
| 982 final separatorPattern = new RegExp(r'[/\\]'); | 1011 final separatorPattern = new RegExp(r'[/\\]'); |
| 983 final needsSeparatorPattern = new RegExp(r'[^/\\]$'); | 1012 final needsSeparatorPattern = new RegExp(r'[^/\\]$'); |
| 984 final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'); | 1013 final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'); |
| 985 | 1014 |
| 1015 // Matches a back or forward slash that's not followed by another back or | |
| 1016 // forward slash. | |
| 1017 final relativeRootPattern = new RegExp(r"^[/\\](?![/\\])"); | |
| 1018 | |
| 986 String pathFromUri(Uri uri) { | 1019 String pathFromUri(Uri uri) { |
| 987 if (uri.scheme != '' && uri.scheme != 'file') { | 1020 if (uri.scheme != '' && uri.scheme != 'file') { |
| 988 throw new ArgumentError("Uri $uri must have scheme 'file:'."); | 1021 throw new ArgumentError("Uri $uri must have scheme 'file:'."); |
| 989 } | 1022 } |
| 990 | 1023 |
| 991 var path = uri.path; | 1024 var path = uri.path; |
| 992 if (uri.host == '') { | 1025 if (uri.host == '') { |
| 993 // Drive-letter paths look like "file:///C:/path/to/file". The | 1026 // Drive-letter paths look like "file:///C:/path/to/file". The |
| 994 // replaceFirst removes the extra initial slash. | 1027 // replaceFirst removes the extra initial slash. |
| 995 if (path.startsWith('/')) path = path.replaceFirst("/", ""); | 1028 if (path.startsWith('/')) path = path.replaceFirst("/", ""); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1190 // doesn't count. | 1223 // doesn't count. |
| 1191 if (lastDot <= 0) return [file, '']; | 1224 if (lastDot <= 0) return [file, '']; |
| 1192 | 1225 |
| 1193 return [file.substring(0, lastDot), file.substring(lastDot)]; | 1226 return [file.substring(0, lastDot), file.substring(lastDot)]; |
| 1194 } | 1227 } |
| 1195 | 1228 |
| 1196 _ParsedPath clone() => new _ParsedPath( | 1229 _ParsedPath clone() => new _ParsedPath( |
| 1197 style, root, isRootRelative, | 1230 style, root, isRootRelative, |
| 1198 new List.from(parts), new List.from(separators)); | 1231 new List.from(parts), new List.from(separators)); |
| 1199 } | 1232 } |
| OLD | NEW |