Index: pkg/path/lib/path.dart |
diff --git a/pkg/path/lib/path.dart b/pkg/path/lib/path.dart |
index 3c5f51eb3ea967285dfa8aee4586088c21e8a588..f1d7228c28256dc9efce6a8f290e1f9efed1c9dd 100644 |
--- a/pkg/path/lib/path.dart |
+++ b/pkg/path/lib/path.dart |
@@ -301,6 +301,12 @@ String normalize(String path) => _builder.normalize(path); |
String relative(String path, {String from}) => |
_builder.relative(path, from: from); |
+/// Returns `true` if [child] is a path beneath `parent`, and `false` otherwise. |
+/// |
+/// path.isWithin('/root/path', '/root/path/a'); // -> true |
+/// 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.
|
+bool isWithin(String parent, String child) => _builder.isWithin(parent, child); |
+ |
/// Removes a trailing extension from the last part of [path]. |
/// |
/// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
@@ -560,10 +566,13 @@ class Builder { |
if (this.isRootRelative(part) && isAbsoluteAndNotRootRelative) { |
// If the new part is root-relative, it preserves the previous root but |
// replaces the path after it. |
- var oldRoot = this.rootPrefix(buffer.toString()); |
+ var parsed = _parse(part); |
+ parsed.root = this.rootPrefix(buffer.toString()); |
+ if (parsed.root.contains(style.needsSeparatorPattern)) { |
+ parsed.separators[0] = style.separator; |
+ } |
buffer.clear(); |
- buffer.write(oldRoot); |
- buffer.write(part); |
+ buffer.write(parsed); |
} else if (this.isAbsolute(part)) { |
isAbsoluteAndNotRootRelative = !this.isRootRelative(part); |
// An absolute path discards everything before it. |
@@ -736,6 +745,26 @@ class Builder { |
return pathParsed.toString(); |
} |
+ /// Returns `true` if [child] is a path beneath `parent`, and `false` |
+ /// otherwise. |
+ /// |
+ /// path.isWithin('/root/path', '/root/path/a'); // -> true |
+ /// path.isWithin('/root/path', '/root/other'); // -> false |
+ bool isWithin(String parent, String child) { |
+ var relative; |
+ try { |
+ relative = this.relative(child, from: parent); |
+ } 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
|
+ // If no relative path from [parent] to [child] is found, [child] |
+ // definitely isn't a child of [parent]. |
+ return false; |
+ } |
+ |
+ var parts = this.split(relative); |
+ return this.isRelative(relative) && parts.first != '..' && |
+ parts.first != '.'; |
+ } |
+ |
/// Removes a trailing extension from the last part of [path]. |
/// |
/// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
@@ -983,6 +1012,10 @@ class _WindowsStyle extends Style { |
final needsSeparatorPattern = new RegExp(r'[^/\\]$'); |
final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'); |
+ // Matches a back or forward slash that's not followed by another back or |
+ // forward slash. |
+ final relativeRootPattern = new RegExp(r"^[/\\](?![/\\])"); |
+ |
String pathFromUri(Uri uri) { |
if (uri.scheme != '' && uri.scheme != 'file') { |
throw new ArgumentError("Uri $uri must have scheme 'file:'."); |