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

Side by Side Diff: pkg/docgen/lib/src/io.dart

Issue 17611006: Change to use Pathos (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« pkg/docgen/lib/docgen.dart ('K') | « pkg/docgen/lib/docgen.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 library io;
2 /// This is a helper library to make working with io easier.
3 // TODO(janicejl): listDir, canonicalize, resolveLink, and linkExists are from
4 // pub/lib/src/io.dart. If the io.dart file becomes a package, should remove
5 // copy of the functions.
6
7 import 'dart:collection';
8 import 'dart:io';
9 import 'package:pathos/path.dart' as path;
10
11 /// Lists the contents of [dir]. If [recursive] is `true`, lists subdirectory
12 /// contents (defaults to `false`). If [includeHidden] is `true`, includes files
13 /// and directories beginning with `.` (defaults to `false`).
14 ///
15 /// The returned paths are guaranteed to begin with [dir].
16 List<String> listDir(String dir, {bool recursive: false,
17 bool includeHidden: false}) {
18 List<String> doList(String dir, Set<String> listedDirectories) {
19 var contents = <String>[];
20
21 // Avoid recursive symlinks.
22 var resolvedPath = canonicalize(dir);
23 if (listedDirectories.contains(resolvedPath)) return [];
24
25 listedDirectories = new Set<String>.from(listedDirectories);
26 listedDirectories.add(resolvedPath);
27
28 var children = <String>[];
29 for (var entity in new Directory(dir).listSync()) {
30 if (!includeHidden && path.basename(entity.path).startsWith('.')) {
31 continue;
32 }
33
34 contents.add(entity.path);
35 if (entity is Directory) {
36 // TODO(nweiz): don't manually recurse once issue 4794 is fixed.
37 // Note that once we remove the manual recursion, we'll need to
38 // explicitly filter out files in hidden directories.
39 if (recursive) {
40 children.addAll(doList(entity.path, listedDirectories));
41 }
42 }
43 }
44
45 contents.addAll(children);
46 return contents;
47 }
48
49 return doList(dir, new Set<String>());
50 }
51
52 /// Returns the canonical path for [pathString]. This is the normalized,
53 /// absolute path, with symlinks resolved. As in [transitiveTarget], broken or
54 /// recursive symlinks will not be fully resolved.
55 ///
56 /// This doesn't require [pathString] to point to a path that exists on the
57 /// filesystem; nonexistent or unreadable path entries are treated as normal
58 /// directories.
59 String canonicalize(String pathString) {
60 var seen = new Set<String>();
61 var components = new Queue<String>.from(
62 path.split(path.normalize(path.absolute(pathString))));
63
64 // The canonical path, built incrementally as we iterate through [components].
65 var newPath = components.removeFirst();
66
67 // Move through the components of the path, resolving each one's symlinks as
68 // necessary. A resolved component may also add new components that need to be
69 // resolved in turn.
70 while (!components.isEmpty) {
71 seen.add(path.join(newPath, path.joinAll(components)));
72 var resolvedPath = resolveLink(
73 path.join(newPath, components.removeFirst()));
74 var relative = path.relative(resolvedPath, from: newPath);
75
76 // If the resolved path of the component relative to `newPath` is just ".",
77 // that means component was a symlink pointing to its parent directory. We
78 // can safely ignore such components.
79 if (relative == '.') continue;
80
81 var relativeComponents = new Queue<String>.from(path.split(relative));
82
83 // If the resolved path is absolute relative to `newPath`, that means it's
84 // on a different drive. We need to canonicalize the entire target of that
85 // symlink again.
86 if (path.isAbsolute(relative)) {
87 // If we've already tried to canonicalize the new path, we've encountered
88 // a symlink loop. Avoid going infinite by treating the recursive symlink
89 // as the canonical path.
90 if (seen.contains(relative)) {
91 newPath = relative;
92 } else {
93 newPath = relativeComponents.removeFirst();
94 relativeComponents.addAll(components);
95 components = relativeComponents;
96 }
97 continue;
98 }
99
100 // Pop directories off `newPath` if the component links upwards in the
101 // directory hierarchy.
102 while (relativeComponents.first == '..') {
103 newPath = path.dirname(newPath);
104 relativeComponents.removeFirst();
105 }
106
107 // If there's only one component left, [resolveLink] guarantees that it's
108 // not a link (or is a broken link). We can just add it to `newPath` and
109 // continue resolving the remaining components.
110 if (relativeComponents.length == 1) {
111 newPath = path.join(newPath, relativeComponents.single);
112 continue;
113 }
114
115 // If we've already tried to canonicalize the new path, we've encountered a
116 // symlink loop. Avoid going infinite by treating the recursive symlink as
117 // the canonical path.
118 var newSubPath = path.join(newPath, path.joinAll(relativeComponents));
119 if (seen.contains(newSubPath)) {
120 newPath = newSubPath;
121 continue;
122 }
123
124 // If there are multiple new components to resolve, add them to the
125 // beginning of the queue.
126 relativeComponents.addAll(components);
127 components = relativeComponents;
128 }
129 return newPath;
130 }
131
132 /// Returns the transitive target of [link] (if A links to B which links to C,
133 /// this will return C). If [link] is part of a symlink loop (e.g. A links to B
134 /// which links back to A), this returns the path to the first repeated link (so
135 /// `transitiveTarget("A")` would return `"A"` and `transitiveTarget("A")` would
136 /// return `"B"`).
137 ///
138 /// This accepts paths to non-links or broken links, and returns them as-is.
139 String resolveLink(String link) {
140 var seen = new Set<String>();
141 while (linkExists(link) && !seen.contains(link)) {
142 seen.add(link);
143 link = path.normalize(path.join(
144 path.dirname(link), new Link(link).targetSync()));
145 }
146 return link;
147 }
148
149 /// Returns whether [link] exists on the file system. This will return `true`
150 /// for any symlink, regardless of what it points at or whether it's broken.
151 bool linkExists(String link) => new Link(link).existsSync();
OLDNEW
« pkg/docgen/lib/docgen.dart ('K') | « pkg/docgen/lib/docgen.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698