Index: utils/pub/path.dart |
diff --git a/utils/pub/path.dart b/utils/pub/path.dart |
index 3b889d380654bd50e2d75c97e3e8f3e5964bfc15..3f36b862baa4b35d4451567c259761ecafe22eaf 100644 |
--- a/utils/pub/path.dart |
+++ b/utils/pub/path.dart |
@@ -24,42 +24,44 @@ String get separator => _builder.separator; |
/// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt |
String absolute(String path) => join(current, path); |
-/// Gets the file extension of [path]; the portion after the last `.` in the |
-/// [basename] of the path. |
+/// Gets the part of [path] after the last separator. |
+/// |
+/// path.basename('path/to/foo.dart'); // -> 'foo.dart' |
+/// path.basename('path/to'); // -> 'to' |
+String basename(String path) => _builder.basename(path); |
+ |
+/// Gets the part of [path] after the last separator, and without any trailing |
+/// file extension. |
+/// |
+/// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
+String basenameWithoutExtension(String path) => |
+ _builder.basenameWithoutExtension(path); |
+ |
+/// Gets the file extension of [path]: the portion of [basename] from the last |
+/// `.` to the end (including the `.` itself). |
/// |
/// path.extension('path/to/foo.dart'); // -> '.dart' |
/// path.extension('path/to/foo'); // -> '' |
/// path.extension('path.to/foo'); // -> '' |
/// path.extension('path/to/foo.dart.js'); // -> '.js' |
/// |
-/// If the file name starts with a `.`, then it is not considered an extension: |
+/// If the file name starts with a `.`, then that is not considered the |
+/// extension: |
/// |
-/// path.extension('~/.bashrc'); // -> '' |
+/// path.extension('~/.bashrc'); // -> '' |
+/// path.extension('~/.notes.txt'); // -> '.txt' |
String extension(String path) => _builder.extension(path); |
-/// Gets the part of [path] after the last separator on the current platform. |
-/// |
-/// path.filename('path/to/foo.dart'); // -> 'foo.dart' |
-/// path.filename('path/to'); // -> 'to' |
-String filename(String path) => _builder.filename(path); |
- |
-/// Gets the part of [path] after the last separator on the current platform, |
-/// and without any trailing file extension. |
-/// |
-/// path.filenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
-String filenameWithoutExtension(String path) => |
- _builder.filenameWithoutExtension(path); |
- |
/// Returns `true` if [path] is an absolute path and `false` if it is a |
-/// relative path. On Mac and Unix systems, relative paths start with a `/` |
-/// (forward slash). On Windows, an absolute path starts with `\\`, or a drive |
-/// letter followed by `:/` or `:\`. |
+/// relative path. On POSIX systems, absolute paths start with a `/` (forward |
+/// slash). On Windows, an absolute path starts with `\\`, or a drive letter |
+/// followed by `:/` or `:\`. |
bool isAbsolute(String path) => _builder.isAbsolute(path); |
/// Returns `true` if [path] is a relative path and `false` if it is absolute. |
-/// On Mac and Unix systems, relative paths start with a `/` (forward slash). |
-/// On Windows, an absolute path starts with `\\`, or a drive letter followed |
-/// by `:/` or `:\`. |
+/// On POSIX systems, absolute paths start with a `/` (forward slash). On |
+/// Windows, an absolute path starts with `\\`, or a drive letter followed by |
+/// `:/` or `:\`. |
bool isRelative(String path) => _builder.isRelative(path); |
/// Joins the given path parts into a single path using the current platform's |
@@ -75,7 +77,6 @@ bool isRelative(String path) => _builder.isRelative(path); |
/// If a part is an absolute path, then anything before that will be ignored: |
/// |
/// 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); |
@@ -95,11 +96,18 @@ String join(String part1, [String part2, String part3, String part4, |
/// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt' |
String normalize(String path) => _builder.normalize(path); |
-/// Converts [path] to an equivalent relative path from the current directory. |
+/// Attempts to convert [path] to an equivalent relative path from the current |
+/// directory. |
/// |
/// // Given current directory is /root/path: |
/// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
/// path.relative('/root/other.dart'); // -> '../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); |
/// Removes a trailing extension from the last part of [path]. |
@@ -113,7 +121,8 @@ class Builder { |
/// Creates a new path builder for the given style and root directory. |
/// |
/// If [style] is omitted, it uses the host operating system's path style. If |
- /// [root] is omitted, it defaults to the current working directory. |
+ /// [root] is omitted, it defaults to the current working directory. If [root] |
+ /// is relative, it is considered relative to the current working directory. |
factory Builder({Style style, String root}) { |
if (style == null) { |
if (io.Platform.operatingSystem == 'windows') { |
@@ -123,7 +132,7 @@ class Builder { |
} |
} |
- if (root == null) root = new io.Directory.current().path; |
+ if (root == null) root = current; |
return new Builder._(style, root); |
} |
@@ -140,8 +149,22 @@ class Builder { |
/// this is `/`. On Windows, it's `\`. |
String get separator => style.separator; |
- /// Gets the file extension of [path]; the portion after the last `.` in the |
- /// [basename] of the path. |
+ /// Gets the part of [path] after the last separator on the builder's |
+ /// platform. |
+ /// |
+ /// builder.basename('path/to/foo.dart'); // -> 'foo.dart' |
+ /// builder.basename('path/to'); // -> 'to' |
+ String basename(String path) => _parse(path).basename; |
+ |
+ /// Gets the part of [path] after the last separator on the builder's |
+ /// platform, and without any trailing file extension. |
+ /// |
+ /// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
+ String basenameWithoutExtension(String path) => |
+ _parse(path).basenameWithoutExtension; |
+ |
+ /// Gets the file extension of [path]: the portion of [basename] from the last |
+ /// `.` to the end (including the `.` itself). |
/// |
/// builder.extension('path/to/foo.dart'); // -> '.dart' |
/// builder.extension('path/to/foo'); // -> '' |
@@ -151,33 +174,20 @@ class Builder { |
/// If the file name starts with a `.`, then it is not considered an |
/// extension: |
/// |
- /// builder.extension('~/.bashrc'); // -> '' |
+ /// builder.extension('~/.bashrc'); // -> '' |
+ /// builder.extension('~/.notes.txt'); // -> '.txt' |
String extension(String path) => _parse(path).extension; |
- /// Gets the part of [path] after the last separator on the builder's |
- /// platform. |
- /// |
- /// builder.filename('path/to/foo.dart'); // -> 'foo.dart' |
- /// builder.filename('path/to'); // -> 'to' |
- String filename(String path) => _parse(path).filename; |
- |
- /// Gets the part of [path] after the last separator on the builder's |
- /// platform, and without any trailing file extension. |
- /// |
- /// builder.filenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
- String filenameWithoutExtension(String path) => |
- _parse(path).filenameWithoutExtension; |
- |
/// Returns `true` if [path] is an absolute path and `false` if it is a |
- /// relative path. On Mac and Unix systems, relative paths start with a `/` |
- /// (forward slash). On Windows, an absolute path starts with `\\`, or a drive |
- /// letter followed by `:/` or `:\`. |
+ /// relative path. On POSIX systems, absolute paths start with a `/` (forward |
+ /// slash). On Windows, an absolute path starts with `\\`, or a drive letter |
+ /// followed by `:/` or `:\`. |
bool isAbsolute(String path) => _parse(path).isAbsolute; |
/// Returns `true` if [path] is a relative path and `false` if it is absolute. |
- /// On Mac and Unix systems, relative paths start with a `/` (forward slash). |
- /// On Windows, an absolute path starts with `\\`, or a drive letter followed |
- /// by `:/` or `:\`. |
+ /// On POSIX systems, absolute paths start with a `/` (forward slash). On |
+ /// Windows, an absolute path starts with `\\`, or a drive letter followed by |
+ /// `:/` or `:\`. |
bool isRelative(String path) => !isAbsolute(path); |
/// Joins the given path parts into a single path. Example: |
@@ -249,7 +259,7 @@ class Builder { |
/// Equivalent to [join()] with [root] as the first argument. Example: |
/// |
/// var builder = new Builder(root: 'root'); |
- /// builder.join('path', 'to', 'foo'); // -> 'root/path/to/foo' |
+ /// builder.resolve('path', 'to', 'foo'); // -> 'root/path/to/foo' |
String resolve(String part1, [String part2, String part3, String part4, |
String part5, String part6, String part7]) { |
if (!?part2) return join(root, part1); |
@@ -261,19 +271,28 @@ class Builder { |
return join(root, part1, part2, part3, part4, part5, part6, part7); |
} |
- /// Converts [path] to an equivalent relative path starting at [root]. |
+ /// Attempts to convert [path] to an equivalent relative path relative to |
+ /// [root]. |
/// |
/// var builder = new Builder(root: '/root/path'); |
/// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
/// builder.relative('/root/other.dart'); // -> '../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) { |
+ 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); |
// If the given path is relative, resolve it relative to the base. |
- path = this.join(base, path); |
+ if (this.isRelative(path)) return this.normalize(path); |
var baseParsed = _parse(base)..normalize(); |
var pathParsed = _parse(path)..normalize(); |
@@ -281,11 +300,13 @@ class Builder { |
// If the root prefixes don't match (for example, different drive letters |
// on Windows), then there is no relative path, so just return the absolute |
// 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(); |
// Strip off their common prefix. |
- while (baseParsed.parts.length > 0 && pathParsed.parts.length > 0) { |
- if (baseParsed.parts[0] != pathParsed.parts[0]) break; |
+ while (baseParsed.parts.length > 0 && pathParsed.parts.length > 0 && |
+ baseParsed.parts[0] == pathParsed.parts[0]) { |
baseParsed.parts.removeAt(0); |
baseParsed.separators.removeAt(0); |
pathParsed.parts.removeAt(0); |
@@ -312,14 +333,9 @@ class Builder { |
/// |
/// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
String withoutExtension(String path) { |
- var lastSeparator = path.lastIndexOf(separator); |
- var lastDot = path.lastIndexOf('.'); |
- |
- // Ignore '.' in anything but the last component. |
- if (lastSeparator != -1 && lastDot <= lastSeparator + 1) lastDot = -1; |
- |
- if (lastDot <= 0) return path; |
- return path.substring(0, lastDot); |
+ var parsed = _parse(path); |
+ parsed.extension = null; |
+ return parsed.toString(); |
} |
_ParsedPath _parse(String path) { |
@@ -373,10 +389,13 @@ class Style { |
/// Windows paths use "\" (backslash) as separators. Absolute paths start with |
/// a drive letter followed by a colon (example, "C:") or two backslashes |
/// ("\\") for UNC paths. |
+ // TODO(rnystrom): The UNC root prefix should include the drive name too, not |
+ // just the "\\". |
static final windows = new Style._('windows', '\\', r'[/\\]', |
r'\\\\|[a-zA-Z]:[/\\]'); |
- Style._(this.name, this.separator, String separatorPattern, String rootPattern) |
+ Style._(this.name, this.separator, String separatorPattern, |
+ String rootPattern) |
: separatorPattern = new RegExp(separatorPattern), |
_rootPattern = new RegExp('^$rootPattern'); |
@@ -442,13 +461,13 @@ class _ParsedPath { |
_ParsedPath(this.style, this.root, this.parts, this.separators, |
this.extension); |
- String get filename { |
+ String get basename { |
if (parts.length == 0) return extension; |
if (hasTrailingSeparator) return ''; |
return '${parts.last}$extension'; |
} |
- String get filenameWithoutExtension { |
+ String get basenameWithoutExtension { |
if (parts.length == 0) return ''; |
if (hasTrailingSeparator) return ''; |
return parts.last; |