Chromium Code Reviews| 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..c5adb8dd7afe6c6302fbf13864aafbea55e34a9d 100644 |
| --- a/sdk/lib/_internal/pub/lib/src/io.dart |
| +++ b/sdk/lib/_internal/pub/lib/src/io.dart |
| @@ -40,6 +40,36 @@ 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); |
|
Bob Nystrom
2013/05/07 17:36:14
A comment explaining how this works would help. So
nweiz
2013/05/07 20:40:15
Done.
|
| + for (var component in components) { |
| + newPath = transitiveTarget(path.join(newPath, component)); |
| + } |
| + return newPath; |
| +} |
| + |
| +/// Returns the transitive target of [link]. If [link] is recursive, this |
|
Bob Nystrom
2013/05/07 17:36:14
"transitive target" doesn't mean anything to me, s
nweiz
2013/05/07 20:40:15
I think "transitive target" is pretty clear; symli
Bob Nystrom
2013/05/07 20:43:07
Maybe, but I think "resolved" is the more common t
|
| +/// returns the path to the first repeated link. |
| +/// |
| +/// 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 +167,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); |