Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2791)

Unified Diff: sdk/lib/_internal/pub/lib/src/io.dart

Issue 14924006: Add a function to pub for finding the canonical path of a file. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/_internal/pub/lib/src/path_source.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/pub/lib/src/io.dart
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 1620837c2b2f3362997abbf78ac581a52b543dab..061908c5cc1272c8da28b8ae570a2566833be77e 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -40,6 +40,41 @@ bool linkExists(String link) => new Link(link).existsSync();
/// for a symlink only if that symlink is unbroken and points to a file.
bool fileExists(String file) => new File(file).existsSync();
+/// Returns the canonical path for [pathString]. This is the normalized,
+/// absolute path, with symlinks resolved. As in [transitiveTarget], broken or
+/// recursive symlinks will not be fully resolved.
+///
+/// This doesn't require [pathString] to point to a path that exists on the
+/// filesystem; nonexistent or unreadable path entries are treated as normal
+/// directories.
+String canonicalize(String pathString) {
+ var components = path.split(path.normalize(path.absolute(pathString)));
+ var newPath = components.removeAt(0);
+ // Rebuild the path one level at a time, resolving the symlinks for each level
+ // in turn.
+ for (var component in components) {
+ newPath = transitiveTarget(path.join(newPath, component));
+ }
+ return newPath;
+}
+
+/// Returns the transitive target of [link] (if A links to B which links to C,
+/// this will return C). If [link] is part of a symlink loop (e.g. A links to B
+/// which links back to A), this returns the path to the first repeated link (so
+/// `transitiveTarget("A")` would return `"A"` and `transitiveTarget("A")` would
+/// return `"B"`).
+///
+/// This accepts paths to non-links or broken links, and returns them as-is.
+String transitiveTarget(String link) {
+ var seen = new Set<String>();
+ while (linkExists(link) && !seen.contains(link)) {
+ seen.add(link);
+ link = path.normalize(path.join(
+ path.dirname(link), new Link(link).targetSync()));
+ }
+ return link;
+}
+
/// Reads the contents of the text file [file].
String readTextFile(String file) =>
new File(file).readAsStringSync(encoding: Encoding.UTF_8);
@@ -137,7 +172,7 @@ List<String> listDir(String dir, {bool recursive: false,
var contents = <String>[];
// Avoid recursive symlinks.
- var resolvedPath = new File(dir).fullPathSync();
+ var resolvedPath = canonicalize(dir);
if (listedDirectories.contains(resolvedPath)) return [];
listedDirectories = new Set<String>.from(listedDirectories);
« no previous file with comments | « no previous file | sdk/lib/_internal/pub/lib/src/path_source.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698