Index: utils/pub/io.dart |
diff --git a/utils/pub/io.dart b/utils/pub/io.dart |
index 968f3546fbc4bcf77b02797f0ab46dc99357435c..1fa5a818d8f9b20f319fc9e0332836924fe01042 100644 |
--- a/utils/pub/io.dart |
+++ b/utils/pub/io.dart |
@@ -13,17 +13,15 @@ import 'dart:uri'; |
// TODO(nweiz): Make this import better. |
import '../../pkg/http/lib/http.dart' as http; |
-import 'utils.dart'; |
import 'curl_client.dart'; |
+import 'utils.dart'; |
+import 'path.dart' as path; |
bool _isGitInstalledCache; |
/// The cached Git command. |
String _gitCommandCache; |
-/** Gets the current working directory. */ |
-String get currentWorkingDir => new File('.').fullPathSync(); |
- |
final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?"); |
/** |
@@ -41,55 +39,32 @@ void printError(value) { |
* [File] objects. |
*/ |
String join(part1, [part2, part3, part4]) { |
- final parts = sanitizePath(part1).split('/'); |
- |
- for (final part in [part2, part3, part4]) { |
- if (part == null) continue; |
- |
- for (final piece in _getPath(part).split('/')) { |
- if (piece == '..' && parts.length > 0 && |
- parts.last != '.' && parts.last != '..') { |
- parts.removeLast(); |
- } else if (piece != '') { |
- if (parts.length > 0 && parts.last == '.') { |
- parts.removeLast(); |
- } |
- parts.add(piece); |
- } |
- } |
- } |
- |
- return Strings.join(parts, Platform.pathSeparator); |
-} |
- |
-/// Splits [path] into its individual components. |
-List<String> splitPath(path) => sanitizePath(path).split('/'); |
- |
-/** |
- * Gets the basename, the file name without any leading directory path, for |
- * [file], which can either be a [String], [File], or [Directory]. |
- */ |
-// TODO(rnystrom): Copied from file_system (so that we don't have to add |
-// file_system to the SDK). Should unify. |
-String basename(file) { |
- file = sanitizePath(file); |
- |
- int lastSlash = file.lastIndexOf('/', file.length); |
- if (lastSlash == -1) { |
- return file; |
+ part1 = _getPath(part1); |
+ if (part2 != null) part2 = _getPath(part2); |
+ if (part3 != null) part3 = _getPath(part3); |
+ if (part4 != null) part4 = _getPath(part4); |
+ |
+ // 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 file.substring(lastSlash + 1); |
+ return path.join(part1); |
} |
} |
-/** |
- * Gets the the leading directory path for [file], which can either be a |
- * [String], [File], or [Directory]. |
- */ |
-// TODO(nweiz): Copied from file_system (so that we don't have to add |
-// file_system to the SDK). Should unify. |
+/// 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.filename(_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); |
+ file = _sanitizePath(file); |
int lastSlash = file.lastIndexOf('/', file.length); |
if (lastSlash == -1) { |
@@ -99,10 +74,21 @@ String dirname(file) { |
} |
} |
+// TODO(nweiz): move this into path.dart. |
+/// Splits [path] into its individual components. |
+List<String> splitPath(path) => _sanitizePath(path).split('/'); |
+ |
/// Returns whether or not [entry] is nested somewhere within [dir]. This just |
/// performs a path comparison; it doesn't look at the actual filesystem. |
-bool isBeneath(entry, dir) => |
- sanitizePath(entry).startsWith('${sanitizePath(dir)}/'); |
+bool isBeneath(entry, dir) { |
+ var relative = relativeTo(entry, dir); |
+ return !path.isAbsolute(relative) && !relative.startsWith('..'); |
+} |
+ |
+// 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); |
/** |
* Asynchronously determines if [path], which can be a [String] file path, a |
@@ -399,52 +385,25 @@ Future<File> createPackageSymlink(String name, from, to, |
/// Given [entry] which may be a [String], [File], or [Directory] relative to |
/// the current working directory, returns its full canonicalized path. |
-String getFullPath(entry) { |
- var path = _getPath(entry); |
- |
- // Don't do anything if it's already absolute. |
- if (isAbsolute(path)) return path; |
- |
- // Using Path.join here instead of File().fullPathSync() because the former |
- // does not require an actual file to exist at that path. |
- return new Path.fromNative(currentWorkingDir).join(new Path(path)) |
- .toNativePath(); |
-} |
+String getFullPath(entry) => path.absolute(_getPath(entry)); |
/// Returns whether or not [entry] is an absolute path. |
-bool isAbsolute(entry) => _splitAbsolute(entry).first != null; |
+bool isAbsolute(entry) => path.isAbsolute(_getPath(entry)); |
-/// 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)); |
-} |
- |
-/// Resolves [path] relative to the location of pub.dart. |
-String relativeToPub(String path) { |
+/// Resolves [target] relative to the location of pub.dart. |
+String relativeToPub(String target) { |
var scriptPath = new File(new Options().script).fullPathSync(); |
// Walk up until we hit the "util(s)" directory. This lets us figure out where |
// we are if this function is called from pub.dart, or one of the tests, |
// which also live under "utils", or from the SDK where pub is in "util". |
- var utilDir = new Path.fromNative(scriptPath).directoryPath; |
- while (utilDir.filename != 'utils' && utilDir.filename != 'util') { |
- if (utilDir.filename == '') throw 'Could not find path to pub.'; |
- utilDir = utilDir.directoryPath; |
+ var utilDir = dirname(scriptPath); |
+ while (basename(utilDir) != 'utils' && basename(utilDir) != 'util') { |
+ if (basename(utilDir) == '') throw 'Could not find path to pub.'; |
+ utilDir = dirname(utilDir); |
} |
- return utilDir.append('pub').append(path).canonicalize().toNativePath(); |
+ return path.normalize(join(utilDir, 'pub', target)); |
} |
/// A StringInputStream reading from stdin. |
@@ -862,7 +821,7 @@ Future<bool> _extractTarGzWindows(InputStream stream, String destination) { |
}).chain((files) { |
var tarFile; |
for (var file in files) { |
- if (new Path(file).extension == 'tar') { |
+ if (path.extension(file) == '.tar') { |
tarFile = file; |
break; |
} |
@@ -894,15 +853,14 @@ InputStream createTarGz(List contents, {baseDir}) { |
// exit codes). See issue 3657. |
var stream = new ListInputStream(); |
- if (baseDir == null) baseDir = currentWorkingDir; |
+ if (baseDir == null) baseDir = path.current; |
baseDir = getFullPath(baseDir); |
contents = contents.map((entry) { |
entry = getFullPath(entry); |
if (!isBeneath(entry, baseDir)) { |
throw 'Entry $entry is not inside $baseDir.'; |
} |
- return new Path.fromNative(entry).relativeTo(new Path.fromNative(baseDir)) |
- .toNativePath(); |
+ return relativeTo(entry, baseDir); |
}); |
if (Platform.operatingSystem != "windows") { |
@@ -996,7 +954,7 @@ String _getPath(entry) { |
/// Gets the path string for [entry], normalizing backslashes to forward slashes |
/// on Windows. |
-String sanitizePath(entry) { |
+String _sanitizePath(entry) { |
entry = _getPath(entry); |
if (Platform.operatingSystem != 'windows') return entry; |
@@ -1010,6 +968,23 @@ String sanitizePath(entry) { |
'${split.last.replaceAll('\\', '/')}'; |
} |
+/// Splits [entry] into two components: the absolute path prefix and the |
+/// remaining path. Takes into account Windows' quirky absolute paths syntaxes. |
Bob Nystrom
2012/12/08 03:36:53
Add a TODO to move this (or something similar) int
nweiz
2012/12/08 03:43:45
Done.
|
+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]. |