| Index: sdk/lib/io/path_impl.dart
|
| diff --git a/sdk/lib/io/path_impl.dart b/sdk/lib/io/path_impl.dart
|
| index b3c98572d8cc58ddccddd2aa5ce935319614d27d..2ea2fea9893e3bf0bc4ccde1a394be2046e8d2b6 100644
|
| --- a/sdk/lib/io/path_impl.dart
|
| +++ b/sdk/lib/io/path_impl.dart
|
| @@ -45,64 +45,68 @@ class _Path implements Path {
|
| String toString() => _path;
|
|
|
| Path relativeTo(Path base) {
|
| - // Throws exception if an unimplemented or impossible case is reached.
|
| // Returns a path "relative" such that
|
| // base.join(relative) == this.canonicalize.
|
| - // Throws an exception if no such path exists, or the case is not
|
| - // implemented yet.
|
| + // Throws exception if an impossible case is reached.
|
| + if (base.isAbsolute != isAbsolute ||
|
| + base.isWindowsShare != isWindowsShare) {
|
| + throw new ArgumentError(
|
| + "Invalid case of Path.relativeTo(base):\n"
|
| + " Path and base must both be relative, or both absolute.\n"
|
| + " Arguments: $_path.relativeTo($base)");
|
| + }
|
| +
|
| var basePath = base.toString();
|
| - if (base.isAbsolute && _path.startsWith(basePath) &&
|
| - base.isWindowsShare == isWindowsShare) {
|
| + if (_path.startsWith(basePath)) {
|
| if (_path == basePath) return new Path('.');
|
| - if (base.hasTrailingSeparator) {
|
| - return new Path(_path.substring(basePath.length));
|
| - }
|
| - if (_path[basePath.length] == '/') {
|
| - return new Path(_path.substring(basePath.length + 1));
|
| - }
|
| - } else if (base.isAbsolute == isAbsolute &&
|
| - base.isWindowsShare == isWindowsShare) {
|
| - List<String> baseSegments = base.canonicalize().segments();
|
| - List<String> pathSegments = canonicalize().segments();
|
| - if (baseSegments.length == 1 && baseSegments[0] == '.') {
|
| - baseSegments = [];
|
| - }
|
| - if (pathSegments.length == 1 && pathSegments[0] == '.') {
|
| - pathSegments = [];
|
| - }
|
| - int common = 0;
|
| - int length = min(pathSegments.length, baseSegments.length);
|
| - while (common < length && pathSegments[common] == baseSegments[common]) {
|
| - common++;
|
| + // There must be a '/' at the end of the match, or immediately after.
|
| + int matchEnd = basePath.length;
|
| + if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') {
|
| + // Drop any extra '/' characters at matchEnd
|
| + while (matchEnd < _path.length && _path[matchEnd] == '/') {
|
| + matchEnd++;
|
| + }
|
| + return new Path(_path.substring(matchEnd)).canonicalize();
|
| }
|
| - final segments = new List<String>();
|
| + }
|
|
|
| - if (common < baseSegments.length && baseSegments[common] == '..') {
|
| - throw new ArgumentError(
|
| - "Invalid case of Path.relativeTo(base):\n"
|
| - " Base path has more '..'s than path does."
|
| - " Arguments: $_path.relativeTo($base)");
|
| - }
|
| - for (int i = common; i < baseSegments.length; i++) {
|
| - segments.add('..');
|
| - }
|
| - for (int i = common; i < pathSegments.length; i++) {
|
| - segments.add('${pathSegments[i]}');
|
| - }
|
| - if (segments.isEmpty) {
|
| - segments.add('.');
|
| - }
|
| - if (hasTrailingSeparator) {
|
| + List<String> baseSegments = base.canonicalize().segments();
|
| + List<String> pathSegments = canonicalize().segments();
|
| + if (baseSegments.length == 1 && baseSegments[0] == '.') {
|
| + baseSegments = [];
|
| + }
|
| + if (pathSegments.length == 1 && pathSegments[0] == '.') {
|
| + pathSegments = [];
|
| + }
|
| + int common = 0;
|
| + int length = min(pathSegments.length, baseSegments.length);
|
| + while (common < length && pathSegments[common] == baseSegments[common]) {
|
| + common++;
|
| + }
|
| + final segments = new List<String>();
|
| +
|
| + if (common < baseSegments.length && baseSegments[common] == '..') {
|
| + throw new ArgumentError(
|
| + "Invalid case of Path.relativeTo(base):\n"
|
| + " Base path has more '..'s than path does."
|
| + " Arguments: $_path.relativeTo($base)");
|
| + }
|
| + for (int i = common; i < baseSegments.length; i++) {
|
| + segments.add('..');
|
| + }
|
| + for (int i = common; i < pathSegments.length; i++) {
|
| + segments.add('${pathSegments[i]}');
|
| + }
|
| + if (segments.isEmpty) {
|
| + segments.add('.');
|
| + }
|
| + if (hasTrailingSeparator) {
|
| segments.add('');
|
| - }
|
| - return new Path(Strings.join(segments, '/'));
|
| }
|
| - throw new ArgumentError(
|
| - "Invalid case of Path.relativeTo(base):\n"
|
| - " Path and base must both be relative, or both absolute.\n"
|
| - " Arguments: $_path.relativeTo($base)");
|
| + return new Path(Strings.join(segments, '/'));
|
| }
|
|
|
| +
|
| Path join(Path further) {
|
| if (further.isAbsolute) {
|
| throw new ArgumentError(
|
|
|