| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 _builder.basenameWithoutExtension(path); | 99 _builder.basenameWithoutExtension(path); |
| 100 | 100 |
| 101 /// Gets the part of [path] before the last separator. | 101 /// Gets the part of [path] before the last separator. |
| 102 /// | 102 /// |
| 103 /// path.dirname('path/to/foo.dart'); // -> 'path/to' | 103 /// path.dirname('path/to/foo.dart'); // -> 'path/to' |
| 104 /// path.dirname('path/to'); // -> 'path' | 104 /// path.dirname('path/to'); // -> 'path' |
| 105 /// | 105 /// |
| 106 /// Trailing separators are ignored. | 106 /// Trailing separators are ignored. |
| 107 /// | 107 /// |
| 108 /// builder.dirname('path/to/'); // -> 'path' | 108 /// builder.dirname('path/to/'); // -> 'path' |
| 109 /// |
| 110 /// If an absolute path contains no directories, only a root, then the root |
| 111 /// is returned. |
| 112 /// |
| 113 /// path.dirname('/'); // -> '/' (posix) |
| 114 /// path.dirname('c:\'); // -> 'c:\' (windows) |
| 115 /// |
| 116 /// If a relative path has no directories, then '.' is returned. |
| 117 /// |
| 118 /// path.dirname('foo'); // -> '.' |
| 119 /// path.dirname(''); // -> '.' |
| 109 String dirname(String path) => _builder.dirname(path); | 120 String dirname(String path) => _builder.dirname(path); |
| 110 | 121 |
| 111 /// Gets the file extension of [path]: the portion of [basename] from the last | 122 /// Gets the file extension of [path]: the portion of [basename] from the last |
| 112 /// `.` to the end (including the `.` itself). | 123 /// `.` to the end (including the `.` itself). |
| 113 /// | 124 /// |
| 114 /// path.extension('path/to/foo.dart'); // -> '.dart' | 125 /// path.extension('path/to/foo.dart'); // -> '.dart' |
| 115 /// path.extension('path/to/foo'); // -> '' | 126 /// path.extension('path/to/foo'); // -> '' |
| 116 /// path.extension('path.to/foo'); // -> '' | 127 /// path.extension('path.to/foo'); // -> '' |
| 117 /// path.extension('path/to/foo.dart.js'); // -> '.js' | 128 /// path.extension('path/to/foo.dart.js'); // -> '.js' |
| 118 /// | 129 /// |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' | 252 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
| 242 /// path.relative('/root/other.dart'); // -> '../other.dart' | 253 /// path.relative('/root/other.dart'); // -> '../other.dart' |
| 243 /// | 254 /// |
| 244 /// If the [from] argument is passed, [path] is made relative to that instead. | 255 /// If the [from] argument is passed, [path] is made relative to that instead. |
| 245 /// | 256 /// |
| 246 /// path.relative('/root/path/a/b.dart', | 257 /// path.relative('/root/path/a/b.dart', |
| 247 /// from: '/root/path'); // -> 'a/b.dart' | 258 /// from: '/root/path'); // -> 'a/b.dart' |
| 248 /// path.relative('/root/other.dart', | 259 /// path.relative('/root/other.dart', |
| 249 /// from: '/root/path'); // -> '../other.dart' | 260 /// from: '/root/path'); // -> '../other.dart' |
| 250 /// | 261 /// |
| 262 /// If [path] and/or [from] are relative paths, they are assumed to be relative |
| 263 /// to the current directory. |
| 264 /// |
| 251 /// Since there is no relative path from one drive letter to another on Windows, | 265 /// Since there is no relative path from one drive letter to another on Windows, |
| 252 /// or from one hostname to another for URLs, this will return an absolute path | 266 /// or from one hostname to another for URLs, this will return an absolute path |
| 253 /// in those cases. | 267 /// in those cases. |
| 254 /// | 268 /// |
| 255 /// // Windows | 269 /// // Windows |
| 256 /// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other' | 270 /// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other' |
| 257 /// | 271 /// |
| 258 /// // URL | 272 /// // URL |
| 259 /// path.relative('http://dartlang.org', from: 'http://pub.dartlang.org'); | 273 /// path.relative('http://dartlang.org', from: 'http://pub.dartlang.org'); |
| 260 /// // -> 'http://dartlang.org' | 274 /// // -> 'http://dartlang.org' |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 .toList(); | 589 .toList(); |
| 576 if (parsed.root != null) parsed.parts.insert(0, parsed.root); | 590 if (parsed.root != null) parsed.parts.insert(0, parsed.root); |
| 577 return parsed.parts; | 591 return parsed.parts; |
| 578 } | 592 } |
| 579 | 593 |
| 580 /// Normalizes [path], simplifying it by handling `..`, and `.`, and | 594 /// Normalizes [path], simplifying it by handling `..`, and `.`, and |
| 581 /// removing redundant path separators whenever possible. | 595 /// removing redundant path separators whenever possible. |
| 582 /// | 596 /// |
| 583 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt' | 597 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt' |
| 584 String normalize(String path) { | 598 String normalize(String path) { |
| 585 if (path == '') return path; | |
| 586 | |
| 587 var parsed = _parse(path); | 599 var parsed = _parse(path); |
| 588 parsed.normalize(); | 600 parsed.normalize(); |
| 589 return parsed.toString(); | 601 return parsed.toString(); |
| 590 } | 602 } |
| 591 | 603 |
| 592 /// Creates a new path by appending the given path parts to the [root]. | 604 /// Creates a new path by appending the given path parts to the [root]. |
| 593 /// Equivalent to [join()] with [root] as the first argument. Example: | 605 /// Equivalent to [join()] with [root] as the first argument. Example: |
| 594 /// | 606 /// |
| 595 /// var builder = new Builder(root: 'root'); | 607 /// var builder = new Builder(root: 'root'); |
| 596 /// builder.resolve('path', 'to', 'foo'); // -> 'root/path/to/foo' | 608 /// builder.resolve('path', 'to', 'foo'); // -> 'root/path/to/foo' |
| 597 String resolve(String part1, [String part2, String part3, String part4, | 609 String resolve(String part1, [String part2, String part3, String part4, |
| 598 String part5, String part6, String part7]) { | 610 String part5, String part6, String part7]) { |
| 599 return join(root, part1, part2, part3, part4, part5, part6, part7); | 611 return join(root, part1, part2, part3, part4, part5, part6, part7); |
| 600 } | 612 } |
| 601 | 613 |
| 602 /// Attempts to convert [path] to an equivalent relative path relative to | 614 /// Attempts to convert [path] to an equivalent relative path relative to |
| 603 /// [root]. | 615 /// [root]. |
| 604 /// | 616 /// |
| 605 /// var builder = new Builder(root: '/root/path'); | 617 /// var builder = new Builder(root: '/root/path'); |
| 606 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' | 618 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
| 607 /// builder.relative('/root/other.dart'); // -> '../other.dart' | 619 /// builder.relative('/root/other.dart'); // -> '../other.dart' |
| 608 /// | 620 /// |
| 609 /// If the [from] argument is passed, [path] is made relative to that instead. | 621 /// If the [from] argument is passed, [path] is made relative to that instead. |
| 610 /// | 622 /// |
| 611 /// builder.relative('/root/path/a/b.dart', | 623 /// builder.relative('/root/path/a/b.dart', |
| 612 /// from: '/root/path'); // -> 'a/b.dart' | 624 /// from: '/root/path'); // -> 'a/b.dart' |
| 613 /// builder.relative('/root/other.dart', | 625 /// builder.relative('/root/other.dart', |
| 614 /// from: '/root/path'); // -> '../other.dart' | 626 /// from: '/root/path'); // -> '../other.dart' |
| 615 /// | 627 /// |
| 628 /// If [path] and/or [from] are relative paths, they are assumed to be |
| 629 /// relative to [root]. |
| 630 /// |
| 616 /// Since there is no relative path from one drive letter to another on | 631 /// Since there is no relative path from one drive letter to another on |
| 617 /// Windows, this will return an absolute path in that case. | 632 /// Windows, this will return an absolute path in that case. |
| 618 /// | 633 /// |
| 619 /// builder.relative(r'D:\other', from: r'C:\other'); // -> 'D:\other' | 634 /// builder.relative(r'D:\other', from: r'C:\other'); // -> 'D:\other' |
| 620 /// | 635 /// |
| 621 /// This will also return an absolute path if an absolute [path] is passed to | 636 /// This will also return an absolute path if an absolute [path] is passed to |
| 622 /// a builder with a relative [root]. | 637 /// a builder with a relative [root]. |
| 623 /// | 638 /// |
| 624 /// var builder = new Builder(r'some/relative/path'); | 639 /// var builder = new Builder(r'some/relative/path'); |
| 625 /// builder.relative(r'/absolute/path'); // -> '/absolute/path' | 640 /// builder.relative(r'/absolute/path'); // -> '/absolute/path' |
| 626 String relative(String path, {String from}) { | 641 String relative(String path, {String from}) { |
| 627 if (path == '') return '.'; | |
| 628 | |
| 629 from = from == null ? root : this.join(root, from); | 642 from = from == null ? root : this.join(root, from); |
| 630 | 643 |
| 631 // We can't determine the path from a relative path to an absolute path. | 644 // We can't determine the path from a relative path to an absolute path. |
| 632 if (this.isRelative(from) && this.isAbsolute(path)) { | 645 if (this.isRelative(from) && this.isAbsolute(path)) { |
| 633 return this.normalize(path); | 646 return this.normalize(path); |
| 634 } | 647 } |
| 635 | 648 |
| 636 // If the given path is relative, resolve it relative to the root of the | 649 // If the given path is relative, resolve it relative to the root of the |
| 637 // builder. | 650 // builder. |
| 638 if (this.isRelative(path) || this.isRootRelative(path)) { | 651 if (this.isRelative(path) || this.isRootRelative(path)) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 665 | 678 |
| 666 // Strip off their common prefix. | 679 // Strip off their common prefix. |
| 667 while (fromParsed.parts.length > 0 && pathParsed.parts.length > 0 && | 680 while (fromParsed.parts.length > 0 && pathParsed.parts.length > 0 && |
| 668 fromParsed.parts[0] == pathParsed.parts[0]) { | 681 fromParsed.parts[0] == pathParsed.parts[0]) { |
| 669 fromParsed.parts.removeAt(0); | 682 fromParsed.parts.removeAt(0); |
| 670 fromParsed.separators.removeAt(1); | 683 fromParsed.separators.removeAt(1); |
| 671 pathParsed.parts.removeAt(0); | 684 pathParsed.parts.removeAt(0); |
| 672 pathParsed.separators.removeAt(1); | 685 pathParsed.separators.removeAt(1); |
| 673 } | 686 } |
| 674 | 687 |
| 675 // If there are any directories left in the root path, we need to walk up | 688 // If there are any directories left in the from path, we need to walk up |
| 676 // out of them. | 689 // out of them. If a directory left in the from path is '..', it cannot |
| 690 // be cancelled by adding a '..'. |
| 691 if (fromParsed.parts.length > 0 && fromParsed.parts[0] == '..') { |
| 692 throw new ArgumentError('Unable to find a path to "$path" from "$from".'); |
| 693 } |
| 677 _growListFront(pathParsed.parts, fromParsed.parts.length, '..'); | 694 _growListFront(pathParsed.parts, fromParsed.parts.length, '..'); |
| 678 pathParsed.separators[0] = ''; | 695 pathParsed.separators[0] = ''; |
| 679 pathParsed.separators.insertAll(1, | 696 pathParsed.separators.insertAll(1, |
| 680 new List.filled(fromParsed.parts.length, style.separator)); | 697 new List.filled(fromParsed.parts.length, style.separator)); |
| 681 | 698 |
| 682 // Corner case: the paths completely collapsed. | 699 // Corner case: the paths completely collapsed. |
| 683 if (pathParsed.parts.length == 0) return '.'; | 700 if (pathParsed.parts.length == 0) return '.'; |
| 684 | 701 |
| 702 // Corner case: path was '.' and some '..' directories were added in front. |
| 703 // Don't add a final '/.' in that case. |
| 704 if (pathParsed.parts.length > 1 && pathParsed.parts.last == '.') { |
| 705 pathParsed.parts.removeLast(); |
| 706 pathParsed.separators..removeLast()..removeLast()..add(''); |
| 707 } |
| 708 |
| 685 // Make it relative. | 709 // Make it relative. |
| 686 pathParsed.root = ''; | 710 pathParsed.root = ''; |
| 687 pathParsed.removeTrailingSeparators(); | 711 pathParsed.removeTrailingSeparators(); |
| 688 | 712 |
| 689 return pathParsed.toString(); | 713 return pathParsed.toString(); |
| 690 } | 714 } |
| 691 | 715 |
| 692 /// Removes a trailing extension from the last part of [path]. | 716 /// Removes a trailing extension from the last part of [path]. |
| 693 /// | 717 /// |
| 694 /// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' | 718 /// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 return copy.parts.last; | 1059 return copy.parts.last; |
| 1036 } | 1060 } |
| 1037 | 1061 |
| 1038 String get basenameWithoutExtension { | 1062 String get basenameWithoutExtension { |
| 1039 var copy = this.clone(); | 1063 var copy = this.clone(); |
| 1040 copy.removeTrailingSeparators(); | 1064 copy.removeTrailingSeparators(); |
| 1041 if (copy.parts.isEmpty) return root == null ? '' : root; | 1065 if (copy.parts.isEmpty) return root == null ? '' : root; |
| 1042 return copy._splitExtension()[0]; | 1066 return copy._splitExtension()[0]; |
| 1043 } | 1067 } |
| 1044 | 1068 |
| 1045 bool get hasTrailingSeparator => !parts.isEmpty && (parts.last == '' || separa
tors.last != ''); | 1069 bool get hasTrailingSeparator => |
| 1070 !parts.isEmpty && (parts.last == '' || separators.last != ''); |
| 1046 | 1071 |
| 1047 void removeTrailingSeparators() { | 1072 void removeTrailingSeparators() { |
| 1048 while (!parts.isEmpty && parts.last == '') { | 1073 while (!parts.isEmpty && parts.last == '') { |
| 1049 parts.removeLast(); | 1074 parts.removeLast(); |
| 1050 separators.removeLast(); | 1075 separators.removeLast(); |
| 1051 } | 1076 } |
| 1052 if (separators.length > 0) separators[separators.length - 1] = ''; | 1077 if (separators.length > 0) separators[separators.length - 1] = ''; |
| 1053 } | 1078 } |
| 1054 | 1079 |
| 1055 void normalize() { | 1080 void normalize() { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 // doesn't count. | 1152 // doesn't count. |
| 1128 if (lastDot <= 0) return [file, '']; | 1153 if (lastDot <= 0) return [file, '']; |
| 1129 | 1154 |
| 1130 return [file.substring(0, lastDot), file.substring(lastDot)]; | 1155 return [file.substring(0, lastDot), file.substring(lastDot)]; |
| 1131 } | 1156 } |
| 1132 | 1157 |
| 1133 _ParsedPath clone() => new _ParsedPath( | 1158 _ParsedPath clone() => new _ParsedPath( |
| 1134 style, root, isRootRelative, | 1159 style, root, isRootRelative, |
| 1135 new List.from(parts), new List.from(separators)); | 1160 new List.from(parts), new List.from(separators)); |
| 1136 } | 1161 } |
| OLD | NEW |