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( |