Chromium Code Reviews| 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:'."); |