mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Move path-manipulation code from io.dart into path.dart.
Review URL: https://codereview.chromium.org//11553005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@16063 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
973a3f0993
commit
7a2155fd65
4 changed files with 339 additions and 132 deletions
|
@ -30,45 +30,24 @@ final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?");
|
|||
* platform-specific path separators. Parts can be [String], [Directory], or
|
||||
* [File] objects.
|
||||
*/
|
||||
String join(part1, [part2, part3, part4]) {
|
||||
part1 = _getPath(part1);
|
||||
if (part2 != null) part2 = _getPath(part2);
|
||||
if (part3 != null) part3 = _getPath(part3);
|
||||
if (part4 != null) part4 = _getPath(part4);
|
||||
String join(part1, [part2, part3, part4, part5, part6, part7, part8]) {
|
||||
var parts = [part1, part2, part3, part4, part5, part6, part7, part8]
|
||||
.map((part) => part == null ? null : _getPath(part));
|
||||
|
||||
// TODO(nweiz): Don't use "?part" in path.dart.
|
||||
if (part4 != null) {
|
||||
return path.join(part1, part2, part3, part4);
|
||||
} else if (part3 != null) {
|
||||
return path.join(part1, part2, part3);
|
||||
} else if (part2 != null) {
|
||||
return path.join(part1, part2);
|
||||
} else {
|
||||
return path.join(part1);
|
||||
}
|
||||
return path.join(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5],
|
||||
parts[6], parts[7]);
|
||||
}
|
||||
|
||||
/// Gets the basename, the file name without any leading directory path, for
|
||||
/// [file], which can either be a [String], [File], or [Directory].
|
||||
String basename(file) => path.basename(_getPath(file));
|
||||
|
||||
// TODO(nweiz): move this into path.dart.
|
||||
/// Gets the the leading directory path for [file], which can either be a
|
||||
/// [String], [File], or [Directory].
|
||||
String dirname(file) {
|
||||
file = _sanitizePath(file);
|
||||
String dirname(file) => path.dirname(_getPath(file));
|
||||
|
||||
int lastSlash = file.lastIndexOf('/', file.length);
|
||||
if (lastSlash == -1) {
|
||||
return '.';
|
||||
} else {
|
||||
return file.substring(0, lastSlash);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(nweiz): move this into path.dart.
|
||||
/// Splits [path] into its individual components.
|
||||
List<String> splitPath(path) => _sanitizePath(path).split('/');
|
||||
/// Splits [entry] into its individual components.
|
||||
List<String> splitPath(entry) => path.split(_getPath(entry));
|
||||
|
||||
/// Returns whether or not [entry] is nested somewhere within [dir]. This just
|
||||
/// performs a path comparison; it doesn't look at the actual filesystem.
|
||||
|
@ -77,10 +56,8 @@ bool isBeneath(entry, dir) {
|
|||
return !path.isAbsolute(relative) && splitPath(relative)[0] != '..';
|
||||
}
|
||||
|
||||
// TODO(nweiz): move this into path.dart.
|
||||
/// Returns the path to [target] from [base].
|
||||
String relativeTo(target, base) =>
|
||||
new path.Builder(root: base).relative(target);
|
||||
String relativeTo(target, base) => path.relative(target, from: base);
|
||||
|
||||
/**
|
||||
* Asynchronously determines if [path], which can be a [String] file path, a
|
||||
|
@ -1067,40 +1044,6 @@ String _getPath(entry) {
|
|||
throw 'Entry $entry is not a supported type.';
|
||||
}
|
||||
|
||||
/// Gets the path string for [entry], normalizing backslashes to forward slashes
|
||||
/// on Windows.
|
||||
String _sanitizePath(entry) {
|
||||
entry = _getPath(entry);
|
||||
if (Platform.operatingSystem != 'windows') return entry;
|
||||
|
||||
var split = _splitAbsolute(entry);
|
||||
if (split.first == null) return split.last.replaceAll('\\', '/');
|
||||
|
||||
// For absolute Windows paths, we don't want the prefix (either "\\" or e.g.
|
||||
// "C:\") to look like a normal path component, so we ensure that it only
|
||||
// contains backslashes.
|
||||
return '${split.first.replaceAll('/', '\\')}'
|
||||
'${split.last.replaceAll('\\', '/')}';
|
||||
}
|
||||
|
||||
// TODO(nweiz): Add something like this to path.dart.
|
||||
/// Splits [entry] into two components: the absolute path prefix and the
|
||||
/// remaining path. Takes into account Windows' quirky absolute paths syntaxes.
|
||||
Pair<String, String> _splitAbsolute(entry) {
|
||||
var path = _getPath(entry);
|
||||
|
||||
if (Platform.operatingSystem != 'windows') {
|
||||
return !path.startsWith('/') ? new Pair(null, path)
|
||||
: new Pair('/', path.substring(1));
|
||||
}
|
||||
|
||||
// An absolute path on Windows is either UNC (two leading backslashes),
|
||||
// or a drive letter followed by a colon and a slash.
|
||||
var match = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])').firstMatch(path);
|
||||
return match == null ? new Pair(null, path)
|
||||
: new Pair(match.group(0), path.substring(match.end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a [Directory] for [entry], which can either already be one, or be a
|
||||
* [String].
|
||||
|
|
|
@ -37,6 +37,12 @@ String basename(String path) => _builder.basename(path);
|
|||
String basenameWithoutExtension(String path) =>
|
||||
_builder.basenameWithoutExtension(path);
|
||||
|
||||
/// Gets the part of [path] before the last separator.
|
||||
///
|
||||
/// path.dirname('path/to/foo.dart'); // -> 'path/to'
|
||||
/// path.dirname('path/to'); // -> 'to'
|
||||
String dirname(String path) => _builder.dirname(path);
|
||||
|
||||
/// Gets the file extension of [path]: the portion of [basename] from the last
|
||||
/// `.` to the end (including the `.` itself).
|
||||
///
|
||||
|
@ -52,6 +58,19 @@ String basenameWithoutExtension(String path) =>
|
|||
/// path.extension('~/.notes.txt'); // -> '.txt'
|
||||
String extension(String path) => _builder.extension(path);
|
||||
|
||||
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
|
||||
/// Returns the root of [path], if it's absolute, or the empty string if it's
|
||||
/// relative.
|
||||
///
|
||||
/// // Unix
|
||||
/// path.rootPrefix('path/to/foo'); // -> ''
|
||||
/// path.rootPrefix('/path/to/foo'); // -> '/'
|
||||
///
|
||||
/// // Windows
|
||||
/// path.rootPrefix(r'path\to\foo'); // -> ''
|
||||
/// path.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
|
||||
String rootPrefix(String path) => _builder.rootPrefix(path);
|
||||
|
||||
/// Returns `true` if [path] is an absolute path and `false` if it is a
|
||||
/// relative path. On POSIX systems, absolute paths start with a `/` (forward
|
||||
/// slash). On Windows, an absolute path starts with `\\`, or a drive letter
|
||||
|
@ -78,17 +97,24 @@ bool isRelative(String path) => _builder.isRelative(path);
|
|||
///
|
||||
/// path.join('path', '/to', 'foo'); // -> '/to/foo'
|
||||
String join(String part1, [String part2, String part3, String part4,
|
||||
String part5, String part6, String part7, String part8]) {
|
||||
if (!?part2) return _builder.join(part1);
|
||||
if (!?part3) return _builder.join(part1, part2);
|
||||
if (!?part4) return _builder.join(part1, part2, part3);
|
||||
if (!?part5) return _builder.join(part1, part2, part3, part4);
|
||||
if (!?part6) return _builder.join(part1, part2, part3, part4, part5);
|
||||
if (!?part7) return _builder.join(part1, part2, part3, part4, part5, part6);
|
||||
if (!?part8) return _builder.join(part1, part2, part3, part4, part5, part6,
|
||||
part7);
|
||||
return _builder.join(part1, part2, part3, part4, part5, part6, part7, part8);
|
||||
}
|
||||
String part5, String part6, String part7, String part8]) =>
|
||||
_builder.join(part1, part2, part3, part4, part5, part6, part7, part8);
|
||||
|
||||
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
|
||||
/// Splits [path] into its components using the current platform's [separator].
|
||||
/// Example:
|
||||
///
|
||||
/// path.split('path/to/foo'); // -> ['path', 'to', 'foo']
|
||||
///
|
||||
/// If [path] is absolute, the root directory will be the first element in the
|
||||
/// array. Example:
|
||||
///
|
||||
/// // Unix
|
||||
/// path.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
|
||||
///
|
||||
/// // Windows
|
||||
/// path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
|
||||
List<String> split(String path) => _builder.split(path);
|
||||
|
||||
/// Normalizes [path], simplifying it by handling `..`, and `.`, and
|
||||
/// removing redundant path separators whenever possible.
|
||||
|
@ -103,12 +129,19 @@ String normalize(String path) => _builder.normalize(path);
|
|||
/// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
|
||||
/// path.relative('/root/other.dart'); // -> '../other.dart'
|
||||
///
|
||||
/// If the [from] argument is passed, [path] is made relative to that instead.
|
||||
///
|
||||
/// path.relative('/root/path/a/b.dart',
|
||||
/// from: '/root/path'); // -> 'a/b.dart'
|
||||
/// path.relative('/root/other.dart',
|
||||
/// from: '/root/path'); // -> '../other.dart'
|
||||
///
|
||||
/// Since there is no relative path from one drive letter to another on Windows,
|
||||
/// this will return an absolute path in that case.
|
||||
///
|
||||
/// // Given current directory is C:\home:
|
||||
/// path.relative(r'D:\other'); // -> 'D:\other'
|
||||
String relative(String path) => _builder.relative(path);
|
||||
/// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other'
|
||||
String relative(String path, {String from}) =>
|
||||
_builder.relative(path, from: from);
|
||||
|
||||
/// Removes a trailing extension from the last part of [path].
|
||||
///
|
||||
|
@ -163,6 +196,24 @@ class Builder {
|
|||
String basenameWithoutExtension(String path) =>
|
||||
_parse(path).basenameWithoutExtension;
|
||||
|
||||
/// Gets the part of [path] before the last separator.
|
||||
///
|
||||
/// builder.dirname('path/to/foo.dart'); // -> 'path/to'
|
||||
/// builder.dirname('path/to'); // -> 'to'
|
||||
String dirname(String path) {
|
||||
var parsed = _parse(path);
|
||||
if (parsed.parts.isEmpty) return parsed.root == null ? '.' : parsed.root;
|
||||
if (!parsed.hasTrailingSeparator) {
|
||||
if (parsed.parts.length == 1) {
|
||||
return parsed.root == null ? '.' : parsed.root;
|
||||
}
|
||||
parsed.parts.removeLast();
|
||||
parsed.separators.removeLast();
|
||||
}
|
||||
parsed.separators[parsed.separators.length - 1] = '';
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
/// Gets the file extension of [path]: the portion of [basename] from the last
|
||||
/// `.` to the end (including the `.` itself).
|
||||
///
|
||||
|
@ -178,6 +229,22 @@ class Builder {
|
|||
/// builder.extension('~/.notes.txt'); // -> '.txt'
|
||||
String extension(String path) => _parse(path).extension;
|
||||
|
||||
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
|
||||
/// Returns the root of [path], if it's absolute, or an empty string if it's
|
||||
/// relative.
|
||||
///
|
||||
/// // Unix
|
||||
/// builder.rootPrefix('path/to/foo'); // -> ''
|
||||
/// builder.rootPrefix('/path/to/foo'); // -> '/'
|
||||
///
|
||||
/// // Windows
|
||||
/// builder.rootPrefix(r'path\to\foo'); // -> ''
|
||||
/// builder.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
|
||||
String rootPrefix(String path) {
|
||||
var root = _parse(path).root;
|
||||
return root == null ? '' : root;
|
||||
}
|
||||
|
||||
/// Returns `true` if [path] is an absolute path and `false` if it is a
|
||||
/// relative path. On POSIX systems, absolute paths start with a `/` (forward
|
||||
/// slash). On Windows, an absolute path starts with `\\`, or a drive letter
|
||||
|
@ -208,8 +275,16 @@ class Builder {
|
|||
var buffer = new StringBuffer();
|
||||
var needsSeparator = false;
|
||||
|
||||
addPart(condition, part) {
|
||||
if (!condition) return;
|
||||
var parts = [part1, part2, part3, part4, part5, part6, part7, part8];
|
||||
for (var i = 1; i < parts.length; i++) {
|
||||
if (parts[i] != null && parts[i - 1] == null) {
|
||||
throw new ArgumentError("join(): part ${i - 1} was null, but part $i "
|
||||
"was not.");
|
||||
}
|
||||
}
|
||||
|
||||
for (var part in parts) {
|
||||
if (part == null) continue;
|
||||
|
||||
if (this.isAbsolute(part)) {
|
||||
// An absolute path discards everything before it.
|
||||
|
@ -231,18 +306,31 @@ class Builder {
|
|||
!style.separatorPattern.hasMatch(part[part.length - 1]);
|
||||
}
|
||||
|
||||
addPart(true, part1);
|
||||
addPart(?part2, part2);
|
||||
addPart(?part3, part3);
|
||||
addPart(?part4, part4);
|
||||
addPart(?part5, part5);
|
||||
addPart(?part6, part6);
|
||||
addPart(?part7, part7);
|
||||
addPart(?part8, part8);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
|
||||
/// Splits [path] into its components using the current platform's
|
||||
/// [separator]. Example:
|
||||
///
|
||||
/// builder.split('path/to/foo'); // -> ['path', 'to', 'foo']
|
||||
///
|
||||
/// If [path] is absolute, the root directory will be the first element in the
|
||||
/// array. Example:
|
||||
///
|
||||
/// // Unix
|
||||
/// builder.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
|
||||
///
|
||||
/// // Windows
|
||||
/// builder.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
|
||||
List<String> split(String path) {
|
||||
var parsed = _parse(path);
|
||||
// Filter out empty parts that exist due to multiple separators in a row.
|
||||
parsed.parts = parsed.parts.filter((part) => part != '');
|
||||
if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root);
|
||||
return parsed.parts;
|
||||
}
|
||||
|
||||
/// Normalizes [path], simplifying it by handling `..`, and `.`, and
|
||||
/// removing redundant path separators whenever possible.
|
||||
///
|
||||
|
@ -278,23 +366,44 @@ class Builder {
|
|||
/// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
|
||||
/// builder.relative('/root/other.dart'); // -> '../other.dart'
|
||||
///
|
||||
/// If the [from] argument is passed, [path] is made relative to that instead.
|
||||
///
|
||||
/// builder.relative('/root/path/a/b.dart',
|
||||
/// from: '/root/path'); // -> 'a/b.dart'
|
||||
/// builder.relative('/root/other.dart',
|
||||
/// from: '/root/path'); // -> '../other.dart'
|
||||
///
|
||||
/// Since there is no relative path from one drive letter to another on
|
||||
/// Windows, this will return an absolute path in that case.
|
||||
///
|
||||
/// var builder = new Builder(root: r'C:\home');
|
||||
/// builder.relative(r'D:\other'); // -> 'D:\other'
|
||||
String relative(String path) {
|
||||
/// builder.relative(r'D:\other', from: r'C:\other'); // -> 'D:\other'
|
||||
///
|
||||
/// This will also return an absolute path if an absolute [path] is passed to
|
||||
/// a builder with a relative [root].
|
||||
///
|
||||
/// var builder = new Builder(r'some/relative/path');
|
||||
/// builder.relative(r'/absolute/path'); // -> '/absolute/path'
|
||||
String relative(String path, {String from}) {
|
||||
if (path == '') return '.';
|
||||
|
||||
// If the base path is relative, resolve it relative to the current
|
||||
// directory.
|
||||
var base = root;
|
||||
if (this.isRelative(base)) base = absolute(base);
|
||||
from = from == null ? root : this.join(root, from);
|
||||
|
||||
// If the given path is relative, resolve it relative to the base.
|
||||
if (this.isRelative(path)) return this.normalize(path);
|
||||
// We can't determine the path from a relative path to an absolute path.
|
||||
if (this.isRelative(from) && this.isAbsolute(path)) {
|
||||
return this.normalize(path);
|
||||
}
|
||||
|
||||
var baseParsed = _parse(base)..normalize();
|
||||
// If the given path is relative, resolve it relative to the root of the
|
||||
// builder.
|
||||
if (this.isRelative(path)) path = this.resolve(path);
|
||||
|
||||
// If the path is still relative and `from` is absolute, we're unable to
|
||||
// find a path from `from` to `path`.
|
||||
if (this.isRelative(path) && this.isAbsolute(from)) {
|
||||
throw new ArgumentError('Unable to find a path to "$path" from "$from".');
|
||||
}
|
||||
|
||||
var fromParsed = _parse(from)..normalize();
|
||||
var pathParsed = _parse(path)..normalize();
|
||||
|
||||
// If the root prefixes don't match (for example, different drive letters
|
||||
|
@ -302,21 +411,21 @@ class Builder {
|
|||
// one.
|
||||
// TODO(rnystrom): Drive letters are case-insentive on Windows. Should
|
||||
// handle "C:\" and "c:\" being the same root.
|
||||
if (baseParsed.root != pathParsed.root) return pathParsed.toString();
|
||||
if (fromParsed.root != pathParsed.root) return pathParsed.toString();
|
||||
|
||||
// Strip off their common prefix.
|
||||
while (baseParsed.parts.length > 0 && pathParsed.parts.length > 0 &&
|
||||
baseParsed.parts[0] == pathParsed.parts[0]) {
|
||||
baseParsed.parts.removeAt(0);
|
||||
baseParsed.separators.removeAt(0);
|
||||
while (fromParsed.parts.length > 0 && pathParsed.parts.length > 0 &&
|
||||
fromParsed.parts[0] == pathParsed.parts[0]) {
|
||||
fromParsed.parts.removeAt(0);
|
||||
fromParsed.separators.removeAt(0);
|
||||
pathParsed.parts.removeAt(0);
|
||||
pathParsed.separators.removeAt(0);
|
||||
}
|
||||
|
||||
// If there are any directories left in the root path, we need to walk up
|
||||
// out of them.
|
||||
pathParsed.parts.insertRange(0, baseParsed.parts.length, '..');
|
||||
pathParsed.separators.insertRange(0, baseParsed.parts.length,
|
||||
pathParsed.parts.insertRange(0, fromParsed.parts.length, '..');
|
||||
pathParsed.separators.insertRange(0, fromParsed.parts.length,
|
||||
style.separator);
|
||||
|
||||
// Corner case: the paths completely collapsed.
|
||||
|
|
|
@ -33,6 +33,30 @@ main() {
|
|||
expect(builder.extension(r'a.b\c'), r'.b\c');
|
||||
});
|
||||
|
||||
test('rootPrefix', () {
|
||||
expect(builder.rootPrefix(''), '');
|
||||
expect(builder.rootPrefix('a'), '');
|
||||
expect(builder.rootPrefix('a/b'), '');
|
||||
expect(builder.rootPrefix('/a/c'), '/');
|
||||
expect(builder.rootPrefix('/'), '/');
|
||||
});
|
||||
|
||||
test('dirname', () {
|
||||
expect(builder.dirname(''), '.');
|
||||
expect(builder.dirname('a'), '.');
|
||||
expect(builder.dirname('a/b'), 'a');
|
||||
expect(builder.dirname('a/b/c'), 'a/b');
|
||||
expect(builder.dirname('a/b.c'), 'a');
|
||||
expect(builder.dirname('a/'), 'a');
|
||||
expect(builder.dirname('a/.'), 'a');
|
||||
expect(builder.dirname(r'a\b/c'), r'a\b');
|
||||
expect(builder.dirname('/a'), '/');
|
||||
expect(builder.dirname('/'), '/');
|
||||
expect(builder.dirname('a/b/'), 'a/b');
|
||||
expect(builder.dirname(r'a/b\c'), 'a');
|
||||
expect(builder.dirname('a//'), 'a/');
|
||||
});
|
||||
|
||||
test('basename', () {
|
||||
expect(builder.basename(''), '');
|
||||
expect(builder.basename('a'), 'a');
|
||||
|
@ -41,7 +65,13 @@ main() {
|
|||
expect(builder.basename('a/b.c'), 'b.c');
|
||||
expect(builder.basename('a/'), '');
|
||||
expect(builder.basename('a/.'), '.');
|
||||
expect(builder.basename(r'a\b/c'), 'c');
|
||||
expect(builder.basename('/a'), 'a');
|
||||
// TODO(nweiz): this should actually return '/'
|
||||
expect(builder.basename('/'), '');
|
||||
expect(builder.basename('a/b/'), '');
|
||||
expect(builder.basename(r'a/b\c'), r'b\c');
|
||||
expect(builder.basename('a//'), '');
|
||||
});
|
||||
|
||||
test('basenameWithoutExtension', () {
|
||||
|
@ -104,10 +134,42 @@ main() {
|
|||
});
|
||||
|
||||
test('ignores parts before an absolute path', () {
|
||||
expect(builder.join('a', '/', 'b', 'c'), '/b/c');
|
||||
expect(builder.join('a', '/b', '/c', 'd'), '/c/d');
|
||||
expect(builder.join('a', r'c:\b', 'c', 'd'), r'a/c:\b/c/d');
|
||||
expect(builder.join('a', r'\\b', 'c', 'd'), r'a/\\b/c/d');
|
||||
});
|
||||
|
||||
test('ignores trailing nulls', () {
|
||||
expect(builder.join('a', null), equals('a'));
|
||||
expect(builder.join('a', 'b', 'c', null, null), equals('a/b/c'));
|
||||
});
|
||||
|
||||
test('disallows intermediate nulls', () {
|
||||
expect(() => builder.join('a', null, 'b'), throwsArgumentError);
|
||||
expect(() => builder.join(null, 'a'), throwsArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
group('split', () {
|
||||
test('simple cases', () {
|
||||
expect(builder.split('foo'), equals(['foo']));
|
||||
expect(builder.split('foo/bar'), equals(['foo', 'bar']));
|
||||
expect(builder.split('foo/bar/baz'), equals(['foo', 'bar', 'baz']));
|
||||
expect(builder.split('foo/../bar/./baz'),
|
||||
equals(['foo', '..', 'bar', '.', 'baz']));
|
||||
expect(builder.split('foo//bar///baz'), equals(['foo', 'bar', 'baz']));
|
||||
expect(builder.split('foo/\\/baz'), equals(['foo', '\\', 'baz']));
|
||||
expect(builder.split('.'), equals(['.']));
|
||||
expect(builder.split(''), equals([]));
|
||||
expect(builder.split('foo/'), equals(['foo']));
|
||||
expect(builder.split('//'), equals(['/']));
|
||||
});
|
||||
|
||||
test('includes the root for absolute paths', () {
|
||||
expect(builder.split('/foo/bar/baz'), equals(['/', 'foo', 'bar', 'baz']));
|
||||
expect(builder.split('/'), equals(['/']));
|
||||
});
|
||||
});
|
||||
|
||||
group('normalize', () {
|
||||
|
@ -211,15 +273,10 @@ main() {
|
|||
group('from relative root', () {
|
||||
var r = new path.Builder(style: path.Style.posix, root: 'foo/bar');
|
||||
|
||||
// These tests rely on the current working directory, so don't do the
|
||||
// right thing if you run them on the wrong platform.
|
||||
if (io.Platform.operatingSystem != 'windows') {
|
||||
test('given absolute path', () {
|
||||
var b = new path.Builder(style: path.Style.posix);
|
||||
expect(r.relative('/'), b.join(b.relative('/'), '../..'));
|
||||
expect(r.relative('/a/b'), b.join(b.relative('/'), '../../a/b'));
|
||||
});
|
||||
}
|
||||
test('given absolute path', () {
|
||||
expect(r.relative('/'), equals('/'));
|
||||
expect(r.relative('/a/b'), equals('/a/b'));
|
||||
});
|
||||
|
||||
test('given relative path', () {
|
||||
// The path is considered relative to the root, so it basically just
|
||||
|
@ -238,6 +295,23 @@ main() {
|
|||
var r = new path.Builder(style: path.Style.posix, root: '/dir.ext');
|
||||
expect(r.relative('/dir.ext/file'), 'file');
|
||||
});
|
||||
|
||||
test('with a root parameter', () {
|
||||
expect(builder.relative('/foo/bar/baz', from: '/foo/bar'), equals('baz'));
|
||||
expect(builder.relative('..', from: '/foo/bar'), equals('../../root'));
|
||||
expect(builder.relative('/foo/bar/baz', from: 'foo/bar'),
|
||||
equals('../../../../foo/bar/baz'));
|
||||
expect(builder.relative('..', from: 'foo/bar'), equals('../../..'));
|
||||
});
|
||||
|
||||
test('with a root parameter and a relative root', () {
|
||||
var r = new path.Builder(style: path.Style.posix, root: 'relative/root');
|
||||
expect(r.relative('/foo/bar/baz', from: '/foo/bar'), equals('baz'));
|
||||
expect(() => r.relative('..', from: '/foo/bar'), throwsArgumentError);
|
||||
expect(r.relative('/foo/bar/baz', from: 'foo/bar'),
|
||||
equals('/foo/bar/baz'));
|
||||
expect(r.relative('..', from: 'foo/bar'), equals('../../..'));
|
||||
});
|
||||
});
|
||||
|
||||
group('resolve', () {
|
||||
|
|
|
@ -35,6 +35,35 @@ main() {
|
|||
expect(builder.extension(r'a.b/c'), r'');
|
||||
});
|
||||
|
||||
test('rootPrefix', () {
|
||||
expect(builder.rootPrefix(''), '');
|
||||
expect(builder.rootPrefix('a'), '');
|
||||
expect(builder.rootPrefix(r'a\b'), '');
|
||||
expect(builder.rootPrefix(r'C:\a\c'), r'C:\');
|
||||
expect(builder.rootPrefix('C:\\'), r'C:\');
|
||||
expect(builder.rootPrefix('C:/'), 'C:/');
|
||||
|
||||
// TODO(nweiz): enable this once issue 7323 is fixed.
|
||||
// expect(builder.rootPrefix(r'\\server\a\b'), r'\\server\');
|
||||
});
|
||||
|
||||
test('dirname', () {
|
||||
expect(builder.dirname(r''), '.');
|
||||
expect(builder.dirname(r'a'), '.');
|
||||
expect(builder.dirname(r'a\b'), 'a');
|
||||
expect(builder.dirname(r'a\b\c'), r'a\b');
|
||||
expect(builder.dirname(r'a\b.c'), 'a');
|
||||
expect(builder.dirname(r'a\'), 'a');
|
||||
expect(builder.dirname('a/'), 'a');
|
||||
expect(builder.dirname(r'a\.'), 'a');
|
||||
expect(builder.dirname(r'a\b/c'), r'a\b');
|
||||
expect(builder.dirname(r'C:\a'), r'C:\');
|
||||
expect(builder.dirname('C:\\'), r'C:\');
|
||||
expect(builder.dirname(r'a\b\'), r'a\b');
|
||||
expect(builder.dirname(r'a/b\c'), 'a/b');
|
||||
expect(builder.dirname(r'a\\'), r'a\');
|
||||
});
|
||||
|
||||
test('basename', () {
|
||||
expect(builder.basename(r''), '');
|
||||
expect(builder.basename(r'a'), 'a');
|
||||
|
@ -45,6 +74,12 @@ main() {
|
|||
expect(builder.basename(r'a/'), '');
|
||||
expect(builder.basename(r'a\.'), '.');
|
||||
expect(builder.basename(r'a\b/c'), r'c');
|
||||
expect(builder.basename(r'C:\a'), 'a');
|
||||
// TODO(nweiz): this should actually return 'C:\'
|
||||
expect(builder.basename(r'C:\'), '');
|
||||
expect(builder.basename(r'a\b\'), '');
|
||||
expect(builder.basename(r'a/b\c'), 'c');
|
||||
expect(builder.basename(r'a\\'), '');
|
||||
});
|
||||
|
||||
test('basenameWithoutExtension', () {
|
||||
|
@ -123,6 +158,43 @@ main() {
|
|||
expect(builder.join('a', r'c:\b', 'c', 'd'), r'c:\b\c\d');
|
||||
expect(builder.join('a', r'\\b', r'\\c', 'd'), r'\\c\d');
|
||||
});
|
||||
|
||||
test('ignores trailing nulls', () {
|
||||
expect(builder.join('a', null), equals('a'));
|
||||
expect(builder.join('a', 'b', 'c', null, null), equals(r'a\b\c'));
|
||||
});
|
||||
|
||||
test('disallows intermediate nulls', () {
|
||||
expect(() => builder.join('a', null, 'b'), throwsArgumentError);
|
||||
expect(() => builder.join(null, 'a'), throwsArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
group('split', () {
|
||||
test('simple cases', () {
|
||||
expect(builder.split('foo'), equals(['foo']));
|
||||
expect(builder.split(r'foo\bar'), equals(['foo', 'bar']));
|
||||
expect(builder.split(r'foo\bar\baz'), equals(['foo', 'bar', 'baz']));
|
||||
expect(builder.split(r'foo\..\bar\.\baz'),
|
||||
equals(['foo', '..', 'bar', '.', 'baz']));
|
||||
expect(builder.split(r'foo\\bar\\\baz'), equals(['foo', 'bar', 'baz']));
|
||||
expect(builder.split(r'foo\/\baz'), equals(['foo', 'baz']));
|
||||
expect(builder.split('.'), equals(['.']));
|
||||
expect(builder.split(''), equals([]));
|
||||
expect(builder.split('foo/'), equals(['foo']));
|
||||
expect(builder.split(r'C:\'), equals([r'C:\']));
|
||||
});
|
||||
|
||||
test('includes the root for absolute paths', () {
|
||||
expect(builder.split(r'C:\foo\bar\baz'),
|
||||
equals([r'C:\', 'foo', 'bar', 'baz']));
|
||||
expect(builder.split(r'C:\\'), equals([r'C:\']));
|
||||
|
||||
// TODO(nweiz): enable these once issue 7323 is fixed.
|
||||
// expect(builder.split(r'\\server\foo\bar\baz'),
|
||||
// equals([r'\\server\', 'foo', 'bar', 'baz']));
|
||||
// expect(builder.split(r'\\server\'), equals([r'\\server\']));
|
||||
});
|
||||
});
|
||||
|
||||
group('normalize', () {
|
||||
|
@ -225,21 +297,10 @@ main() {
|
|||
group('from relative root', () {
|
||||
var r = new path.Builder(style: path.Style.windows, root: r'foo\bar');
|
||||
|
||||
// These tests rely on the current working directory, so don't do the
|
||||
// right thing if you run them on the wrong platform.
|
||||
if (io.Platform.operatingSystem == 'windows') {
|
||||
test('given absolute path', () {
|
||||
var b = new path.Builder(style: path.Style.windows);
|
||||
// TODO(rnystrom): Use a path method here to get the root prefix
|
||||
// when one exists.
|
||||
var drive = path.current.substring(0, 3);
|
||||
expect(r.relative(drive), b.join(b.relative(drive), r'..\..'));
|
||||
expect(r.relative(b.join(drive, r'a\b')),
|
||||
b.join(b.relative(drive), r'..\..\a\b'));
|
||||
|
||||
// TODO(rnystrom): Test behavior when drive letters differ.
|
||||
});
|
||||
}
|
||||
test('given absolute path', () {
|
||||
expect(r.relative(r'C:\'), equals(r'C:\'));
|
||||
expect(r.relative(r'C:\a\b'), equals(r'C:\a\b'));
|
||||
});
|
||||
|
||||
test('given relative path', () {
|
||||
// The path is considered relative to the root, so it basically just
|
||||
|
@ -259,6 +320,26 @@ main() {
|
|||
expect(r.relative(r'C:\dir.ext\file'), 'file');
|
||||
});
|
||||
|
||||
test('with a root parameter', () {
|
||||
expect(builder.relative(r'C:\foo\bar\baz', from: r'C:\foo\bar'),
|
||||
equals('baz'));
|
||||
expect(builder.relative('..', from: r'C:\foo\bar'),
|
||||
equals(r'..\..\root'));
|
||||
expect(builder.relative('..', from: r'D:\foo\bar'), equals(r'C:\root'));
|
||||
expect(builder.relative(r'C:\foo\bar\baz', from: r'foo\bar'),
|
||||
equals(r'..\..\..\..\foo\bar\baz'));
|
||||
expect(builder.relative('..', from: r'foo\bar'), equals(r'..\..\..'));
|
||||
});
|
||||
|
||||
test('with a root parameter and a relative root', () {
|
||||
var r = new path.Builder(style: path.Style.windows, root: r'relative\root');
|
||||
expect(r.relative(r'C:\foo\bar\baz', from: r'C:\foo\bar'), equals('baz'));
|
||||
expect(() => r.relative('..', from: r'C:\foo\bar'), throwsArgumentError);
|
||||
expect(r.relative(r'C:\foo\bar\baz', from: r'foo\bar'),
|
||||
equals(r'C:\foo\bar\baz'));
|
||||
expect(r.relative('..', from: r'foo\bar'), equals(r'..\..\..'));
|
||||
});
|
||||
|
||||
test('given absolute with different root prefix', () {
|
||||
expect(builder.relative(r'D:\a\b'), r'D:\a\b');
|
||||
expect(builder.relative(r'\\a\b'), r'\\a\b');
|
||||
|
|
Loading…
Reference in a new issue