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

Side by Side Diff: utils/pub/path.dart

Issue 11553005: Move path-manipulation code from io.dart into path.dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// A comprehensive, cross-platform path manipulation library. 5 /// A comprehensive, cross-platform path manipulation library.
6 library path; 6 library path;
7 7
8 import 'dart:io' as io; 8 import 'dart:io' as io;
9 9
10 /// An internal builder for the current OS so we can provide a straight 10 /// An internal builder for the current OS so we can provide a straight
11 /// functional interface and not require users to create one. 11 /// functional interface and not require users to create one.
12 final _builder = new Builder(); 12 final _builder = new Builder();
13 13
14 /// Gets the path to the current working directory. 14 /// Gets the path to the current working directory.
15 String get current => new io.Directory.current().path; 15 String get current => new io.Directory.current().path;
16 16
17 /// Gets the path separator for the current platform. On Mac and Linux, this 17 /// Gets the path separator for the current platform. On Mac and Linux, this
18 /// is `/`. On Windows, it's `\`. 18 /// is `/`. On Windows, it's `\`.
19 String get separator => _builder.separator; 19 String get separator => _builder.separator;
20 20
21 /// Converts [path] to an absolute path by resolving it relative to the current 21 /// Converts [path] to an absolute path by resolving it relative to the current
22 /// working directory. If [path] is already an absolute path, just returns it. 22 /// working directory. If [path] is already an absolute path, just returns it.
23 /// 23 ///
24 /// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt 24 /// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt
25 String absolute(String path) => join(current, path); 25 String absolute(String path) => join(current, path);
26 26
27 /// Gets the part of [path] before the last separator.
28 ///
29 /// path.dirname('path/to/foo.dart'); // -> 'path/to'
30 /// path.dirname('path/to'); // -> 'to'
31 String dirname(String path) => _builder.dirname(path);
32
27 /// Gets the part of [path] after the last separator. 33 /// Gets the part of [path] after the last separator.
28 /// 34 ///
29 /// path.basename('path/to/foo.dart'); // -> 'foo.dart' 35 /// path.basename('path/to/foo.dart'); // -> 'foo.dart'
30 /// path.basename('path/to'); // -> 'to' 36 /// path.basename('path/to'); // -> 'to'
31 String basename(String path) => _builder.basename(path); 37 String basename(String path) => _builder.basename(path);
32 38
33 /// Gets the part of [path] after the last separator, and without any trailing 39 /// Gets the part of [path] after the last separator, and without any trailing
34 /// file extension. 40 /// file extension.
35 /// 41 ///
36 /// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' 42 /// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
37 String basenameWithoutExtension(String path) => 43 String basenameWithoutExtension(String path) =>
38 _builder.basenameWithoutExtension(path); 44 _builder.basenameWithoutExtension(path);
39 45
40 /// Gets the file extension of [path]: the portion of [basename] from the last 46 /// Gets the file extension of [path]: the portion of [basename] from the last
41 /// `.` to the end (including the `.` itself). 47 /// `.` to the end (including the `.` itself).
42 /// 48 ///
43 /// path.extension('path/to/foo.dart'); // -> '.dart' 49 /// path.extension('path/to/foo.dart'); // -> '.dart'
44 /// path.extension('path/to/foo'); // -> '' 50 /// path.extension('path/to/foo'); // -> ''
45 /// path.extension('path.to/foo'); // -> '' 51 /// path.extension('path.to/foo'); // -> ''
46 /// path.extension('path/to/foo.dart.js'); // -> '.js' 52 /// path.extension('path/to/foo.dart.js'); // -> '.js'
47 /// 53 ///
48 /// If the file name starts with a `.`, then that is not considered the 54 /// If the file name starts with a `.`, then that is not considered the
49 /// extension: 55 /// extension:
50 /// 56 ///
51 /// path.extension('~/.bashrc'); // -> '' 57 /// path.extension('~/.bashrc'); // -> ''
52 /// path.extension('~/.notes.txt'); // -> '.txt' 58 /// path.extension('~/.notes.txt'); // -> '.txt'
53 String extension(String path) => _builder.extension(path); 59 String extension(String path) => _builder.extension(path);
54 60
61 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
62 /// Returns the root of [path], if it's absolute, or `null` if it's relative.
Bob Nystrom 2012/12/12 00:01:20 Generally, this library returns empty strings inst
nweiz 2012/12/12 00:50:37 I based it on the ParsedPath API, which also retur
Bob Nystrom 2012/12/12 01:02:13 That's part of the reason ParsedPath is still priv
nweiz 2012/12/12 02:45:57 Done.
63 ///
64 /// // Unix
65 /// path.rootOf('path/to/foo'); // -> null
66 /// path.rootOf('/path/to/foo'); // -> '/'
67 ///
68 /// // Windows
69 /// path.rootOf(r'path\to\foo'); // -> null
70 /// path.rootOf(r'C:\path\to\foo'); // -> r'C:\'
71 String rootOf(String path) => _builder.rootOf(path);
Bob Nystrom 2012/12/12 00:01:20 "rootOf" -> "root", I think. I like English-like A
nweiz 2012/12/12 00:50:37 I had it as "root" originally, but that causes a n
Bob Nystrom 2012/12/12 01:02:13 maybe rootPrefix?
nweiz 2012/12/12 02:45:57 Done.
72
55 /// Returns `true` if [path] is an absolute path and `false` if it is a 73 /// Returns `true` if [path] is an absolute path and `false` if it is a
56 /// relative path. On POSIX systems, absolute paths start with a `/` (forward 74 /// relative path. On POSIX systems, absolute paths start with a `/` (forward
57 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter 75 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter
58 /// followed by `:/` or `:\`. 76 /// followed by `:/` or `:\`.
59 bool isAbsolute(String path) => _builder.isAbsolute(path); 77 bool isAbsolute(String path) => _builder.isAbsolute(path);
60 78
61 /// Returns `true` if [path] is a relative path and `false` if it is absolute. 79 /// Returns `true` if [path] is a relative path and `false` if it is absolute.
62 /// On POSIX systems, absolute paths start with a `/` (forward slash). On 80 /// On POSIX systems, absolute paths start with a `/` (forward slash). On
63 /// Windows, an absolute path starts with `\\`, or a drive letter followed by 81 /// Windows, an absolute path starts with `\\`, or a drive letter followed by
64 /// `:/` or `:\`. 82 /// `:/` or `:\`.
65 bool isRelative(String path) => _builder.isRelative(path); 83 bool isRelative(String path) => _builder.isRelative(path);
66 84
67 /// Joins the given path parts into a single path using the current platform's 85 /// Joins the given path parts into a single path using the current platform's
68 /// [separator]. Example: 86 /// [separator]. Example:
69 /// 87 ///
70 /// path.join('path', 'to', 'foo'); // -> 'path/to/foo' 88 /// path.join('path', 'to', 'foo'); // -> 'path/to/foo'
71 /// 89 ///
72 /// If any part ends in a path separator, then a redundant separator will not 90 /// If any part ends in a path separator, then a redundant separator will not
73 /// be added: 91 /// be added:
74 /// 92 ///
75 /// path.join('path/', 'to', 'foo'); // -> 'path/to/foo 93 /// path.join('path/', 'to', 'foo'); // -> 'path/to/foo
76 /// 94 ///
77 /// If a part is an absolute path, then anything before that will be ignored: 95 /// If a part is an absolute path, then anything before that will be ignored:
78 /// 96 ///
79 /// path.join('path', '/to', 'foo'); // -> '/to/foo' 97 /// path.join('path', '/to', 'foo'); // -> '/to/foo'
80 String join(String part1, [String part2, String part3, String part4, 98 String join(String part1, [String part2, String part3, String part4,
81 String part5, String part6, String part7, String part8]) { 99 String part5, String part6, String part7, String part8]) =>
82 if (!?part2) return _builder.join(part1); 100 _builder.join(part1, part2, part3, part4, part5, part6, part7, part8);
83 if (!?part3) return _builder.join(part1, part2); 101
84 if (!?part4) return _builder.join(part1, part2, part3); 102 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
85 if (!?part5) return _builder.join(part1, part2, part3, part4); 103 /// Splits [path] into its components using the current platform's [separator].
86 if (!?part6) return _builder.join(part1, part2, part3, part4, part5); 104 /// Example:
87 if (!?part7) return _builder.join(part1, part2, part3, part4, part5, part6); 105 ///
88 if (!?part8) return _builder.join(part1, part2, part3, part4, part5, part6, 106 /// path.split('path/to/foo'); // -> ['path', 'to', 'foo']
89 part7); 107 ///
90 return _builder.join(part1, part2, part3, part4, part5, part6, part7, part8); 108 /// If [path] is absolute, the root directory will be the first element in the
91 } 109 /// array. Example:
110 ///
111 /// // Unix
112 /// path.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
113 ///
114 /// // Windows
115 /// path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
116 List<String> split(String path) => _builder.split(path);
Bob Nystrom 2012/12/12 00:01:20 Heh, my preflight patch has an implementation of t
nweiz 2012/12/12 00:50:37 I like this version better, since it lists all dir
Bob Nystrom 2012/12/12 01:02:13 Ah, good call. Works for me.
92 117
93 /// Normalizes [path], simplifying it by handling `..`, and `.`, and 118 /// Normalizes [path], simplifying it by handling `..`, and `.`, and
94 /// removing redundant path separators whenever possible. 119 /// removing redundant path separators whenever possible.
95 /// 120 ///
96 /// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt' 121 /// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
97 String normalize(String path) => _builder.normalize(path); 122 String normalize(String path) => _builder.normalize(path);
98 123
99 /// Attempts to convert [path] to an equivalent relative path from the current 124 /// Attempts to convert [path] to an equivalent relative path from the current
100 /// directory. 125 /// directory.
101 /// 126 ///
102 /// // Given current directory is /root/path: 127 /// // Given current directory is /root/path:
103 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' 128 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
104 /// path.relative('/root/other.dart'); // -> '../other.dart' 129 /// path.relative('/root/other.dart'); // -> '../other.dart'
105 /// 130 ///
131 /// If the [to] argument is passed, [path] is made relative to that instead.
Bob Nystrom 2012/12/12 00:01:20 I don't like reinterpreting one argument based on
nweiz 2012/12/12 00:50:37 The idea is that it returns "path" relative to "to
Bob Nystrom 2012/12/12 01:02:13 Before I accidentally lost the implementation, I w
nweiz 2012/12/12 02:45:57 That reads as "'foo/bar' relative from 'foo'" to m
Bob Nystrom 2012/12/12 04:52:33 Yeah, I like it a bit more. I read it as "get a pa
132 ///
133 /// path.relative('/root/path/a/b.dart', to: '/root/path'); // -> 'a/b.dart'
134 /// path.relative('/root/other.dart',
135 /// to: '/root/path'); // -> '../other.dart'
136 ///
106 /// Since there is no relative path from one drive letter to another on Windows, 137 /// Since there is no relative path from one drive letter to another on Windows,
107 /// this will return an absolute path in that case. 138 /// this will return an absolute path in that case.
108 /// 139 ///
109 /// // Given current directory is C:\home: 140 /// path.relative(r'D:\other', to: r'C:\home'); // -> 'D:\other'
110 /// path.relative(r'D:\other'); // -> 'D:\other' 141 String relative(String path, {String to}) => _builder.relative(path, to: to);
111 String relative(String path) => _builder.relative(path);
112 142
113 /// Removes a trailing extension from the last part of [path]. 143 /// Removes a trailing extension from the last part of [path].
114 /// 144 ///
115 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' 145 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
116 String withoutExtension(String path) => _builder.withoutExtension(path); 146 String withoutExtension(String path) => _builder.withoutExtension(path);
117 147
118 /// An instantiable class for manipulating paths. Unlike the top-level 148 /// An instantiable class for manipulating paths. Unlike the top-level
119 /// functions, this lets you explicitly select what platform the paths will use. 149 /// functions, this lets you explicitly select what platform the paths will use.
120 class Builder { 150 class Builder {
121 /// Creates a new path builder for the given style and root directory. 151 /// Creates a new path builder for the given style and root directory.
(...skipping 20 matching lines...) Expand all
142 /// The style of path that this builder works with. 172 /// The style of path that this builder works with.
143 final Style style; 173 final Style style;
144 174
145 /// The root directory that relative paths will be relative to. 175 /// The root directory that relative paths will be relative to.
146 final String root; 176 final String root;
147 177
148 /// Gets the path separator for the builder's [style]. On Mac and Linux, 178 /// Gets the path separator for the builder's [style]. On Mac and Linux,
149 /// this is `/`. On Windows, it's `\`. 179 /// this is `/`. On Windows, it's `\`.
150 String get separator => style.separator; 180 String get separator => style.separator;
151 181
182 /// Gets the part of [path] before the last separator.
183 ///
184 /// builder.dirname('path/to/foo.dart'); // -> 'path/to'
185 /// builder.dirname('path/to'); // -> 'to'
Bob Nystrom 2012/12/12 00:01:20 Show an example of what happens if there's a trail
nweiz 2012/12/12 00:50:37 I left that out intentionally because I want to ch
186 String dirname(String path) {
Bob Nystrom 2012/12/12 00:01:20 Nit, but can you move this after basenameWithoutEx
nweiz 2012/12/12 00:50:37 Done.
187 var parsed = _parse(path);
188 if (parsed.parts.isEmpty) return '.';
Bob Nystrom 2012/12/12 00:01:20 You'll need to handle absolute paths here. If ther
nweiz 2012/12/12 00:50:37 Done.
189 if (parsed.separators.last == '') {
Bob Nystrom 2012/12/12 00:01:20 !parsed.hasTrailingSeparator
nweiz 2012/12/12 00:50:37 Done.
190 if (parsed.parts.length == 1) return '.';
Bob Nystrom 2012/12/12 00:01:20 I think you should be able to skip this check.
nweiz 2012/12/12 00:50:37 It dirname("a") should return ".", not "".
Bob Nystrom 2012/12/12 01:02:13 Right, but I believe toString() handles that, does
nweiz 2012/12/12 02:45:57 No, it would just return ''.
191 parsed.parts.removeLast();
192 parsed.separators.removeLast();
193 }
194 parsed.separators[parsed.separators.length - 1] = '';
Bob Nystrom 2012/12/12 00:01:20 What's this for?
nweiz 2012/12/12 00:50:37 For paths with trailing separators, this makes dir
Bob Nystrom 2012/12/12 01:02:13 Yeah, consistency is what matters most to me here.
195 return parsed.toString();
196 }
197
152 /// Gets the part of [path] after the last separator on the builder's 198 /// Gets the part of [path] after the last separator on the builder's
153 /// platform. 199 /// platform.
154 /// 200 ///
155 /// builder.basename('path/to/foo.dart'); // -> 'foo.dart' 201 /// builder.basename('path/to/foo.dart'); // -> 'foo.dart'
156 /// builder.basename('path/to'); // -> 'to' 202 /// builder.basename('path/to'); // -> 'to'
157 String basename(String path) => _parse(path).basename; 203 String basename(String path) => _parse(path).basename;
158 204
159 /// Gets the part of [path] after the last separator on the builder's 205 /// Gets the part of [path] after the last separator on the builder's
160 /// platform, and without any trailing file extension. 206 /// platform, and without any trailing file extension.
161 /// 207 ///
162 /// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' 208 /// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
163 String basenameWithoutExtension(String path) => 209 String basenameWithoutExtension(String path) =>
164 _parse(path).basenameWithoutExtension; 210 _parse(path).basenameWithoutExtension;
165 211
166 /// Gets the file extension of [path]: the portion of [basename] from the last 212 /// Gets the file extension of [path]: the portion of [basename] from the last
167 /// `.` to the end (including the `.` itself). 213 /// `.` to the end (including the `.` itself).
168 /// 214 ///
169 /// builder.extension('path/to/foo.dart'); // -> '.dart' 215 /// builder.extension('path/to/foo.dart'); // -> '.dart'
170 /// builder.extension('path/to/foo'); // -> '' 216 /// builder.extension('path/to/foo'); // -> ''
171 /// builder.extension('path.to/foo'); // -> '' 217 /// builder.extension('path.to/foo'); // -> ''
172 /// builder.extension('path/to/foo.dart.js'); // -> '.js' 218 /// builder.extension('path/to/foo.dart.js'); // -> '.js'
173 /// 219 ///
174 /// If the file name starts with a `.`, then it is not considered an 220 /// If the file name starts with a `.`, then it is not considered an
175 /// extension: 221 /// extension:
176 /// 222 ///
177 /// builder.extension('~/.bashrc'); // -> '' 223 /// builder.extension('~/.bashrc'); // -> ''
178 /// builder.extension('~/.notes.txt'); // -> '.txt' 224 /// builder.extension('~/.notes.txt'); // -> '.txt'
179 String extension(String path) => _parse(path).extension; 225 String extension(String path) => _parse(path).extension;
180 226
227 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
228 /// Returns the root of [path], if it's absolute, or `null` if it's relative.
229 ///
230 /// // Unix
231 /// builder.rootOf('path/to/foo'); // -> null
232 /// builder.rootOf('/path/to/foo'); // -> '/'
233 ///
234 /// // Windows
235 /// builder.rootOf(r'path\to\foo'); // -> null
236 /// builder.rootOf(r'C:\path\to\foo'); // -> r'C:\'
237 String rootOf(String path) => _parse(path).root;
238
181 /// Returns `true` if [path] is an absolute path and `false` if it is a 239 /// Returns `true` if [path] is an absolute path and `false` if it is a
182 /// relative path. On POSIX systems, absolute paths start with a `/` (forward 240 /// relative path. On POSIX systems, absolute paths start with a `/` (forward
183 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter 241 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter
184 /// followed by `:/` or `:\`. 242 /// followed by `:/` or `:\`.
185 bool isAbsolute(String path) => _parse(path).isAbsolute; 243 bool isAbsolute(String path) => _parse(path).isAbsolute;
186 244
187 /// Returns `true` if [path] is a relative path and `false` if it is absolute. 245 /// Returns `true` if [path] is a relative path and `false` if it is absolute.
188 /// On POSIX systems, absolute paths start with a `/` (forward slash). On 246 /// On POSIX systems, absolute paths start with a `/` (forward slash). On
189 /// Windows, an absolute path starts with `\\`, or a drive letter followed by 247 /// Windows, an absolute path starts with `\\`, or a drive letter followed by
190 /// `:/` or `:\`. 248 /// `:/` or `:\`.
(...skipping 10 matching lines...) Expand all
201 /// 259 ///
202 /// If a part is an absolute path, then anything before that will be ignored: 260 /// If a part is an absolute path, then anything before that will be ignored:
203 /// 261 ///
204 /// builder.join('path', '/to', 'foo'); // -> '/to/foo' 262 /// builder.join('path', '/to', 'foo'); // -> '/to/foo'
205 /// 263 ///
206 String join(String part1, [String part2, String part3, String part4, 264 String join(String part1, [String part2, String part3, String part4,
207 String part5, String part6, String part7, String part8]) { 265 String part5, String part6, String part7, String part8]) {
208 var buffer = new StringBuffer(); 266 var buffer = new StringBuffer();
209 var needsSeparator = false; 267 var needsSeparator = false;
210 268
211 addPart(condition, part) { 269 var parts = [part1, part2, part3, part4, part5, part6, part7, part8];
212 if (!condition) return; 270 for (var i = 1; i < parts.length; i++) {
271 if (parts[i] == null || parts[i - 1] != null) continue;
Bob Nystrom 2012/12/12 00:01:20 I'd find this more intuitive if you flipped the lo
nweiz 2012/12/12 00:50:37 Done.
272 throw new ArgumentError("join(): part ${i - 1} was null, but part $i was "
273 "not.");
274 }
275
276 for (var part in parts) {
277 if (part == null) continue;
213 278
214 if (this.isAbsolute(part)) { 279 if (this.isAbsolute(part)) {
215 // An absolute path discards everything before it. 280 // An absolute path discards everything before it.
216 buffer.clear(); 281 buffer.clear();
217 buffer.add(part); 282 buffer.add(part);
218 } else { 283 } else {
219 if (part.length > 0 && style.separatorPattern.hasMatch(part[0])) { 284 if (part.length > 0 && style.separatorPattern.hasMatch(part[0])) {
220 // The part starts with a separator, so we don't need to add one. 285 // The part starts with a separator, so we don't need to add one.
221 } else if (needsSeparator) { 286 } else if (needsSeparator) {
222 buffer.add(separator); 287 buffer.add(separator);
223 } 288 }
224 289
225 buffer.add(part); 290 buffer.add(part);
226 } 291 }
227 292
228 // Unless this part ends with a separator, we'll need to add one before 293 // Unless this part ends with a separator, we'll need to add one before
229 // the next part. 294 // the next part.
230 needsSeparator = part.length > 0 && 295 needsSeparator = part.length > 0 &&
231 !style.separatorPattern.hasMatch(part[part.length - 1]); 296 !style.separatorPattern.hasMatch(part[part.length - 1]);
232 } 297 }
233 298
234 addPart(true, part1); 299 return buffer.toString();
235 addPart(?part2, part2); 300 }
236 addPart(?part3, part3);
237 addPart(?part4, part4);
238 addPart(?part5, part5);
239 addPart(?part6, part6);
240 addPart(?part7, part7);
241 addPart(?part8, part8);
242 301
243 return buffer.toString(); 302 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
303 /// Splits [path] into its components using the current platform's [separator] .
Bob Nystrom 2012/12/12 00:01:20 Long line.
nweiz 2012/12/12 00:50:37 Done.
304 /// Example:
305 ///
306 /// builder.split('path/to/foo'); // -> ['path', 'to', 'foo']
307 ///
308 /// If [path] is absolute, the root directory will be the first element in the
309 /// array. Example:
310 ///
311 /// // Unix
312 /// builder.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
313 ///
314 /// // Windows
315 /// builder.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
316 List<String> split(String path) {
317 var parsed = _parse(path);
318 // Filter out empty parts that exist due to multiple separators in a row.
319 parsed.parts = parsed.parts.filter((part) => part != '');
320 if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root);
321 return parsed.parts;
244 } 322 }
245 323
246 /// Normalizes [path], simplifying it by handling `..`, and `.`, and 324 /// Normalizes [path], simplifying it by handling `..`, and `.`, and
247 /// removing redundant path separators whenever possible. 325 /// removing redundant path separators whenever possible.
248 /// 326 ///
249 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt' 327 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
250 String normalize(String path) { 328 String normalize(String path) {
251 if (path == '') return path; 329 if (path == '') return path;
252 330
253 var parsed = _parse(path); 331 var parsed = _parse(path);
(...skipping 17 matching lines...) Expand all
271 return join(root, part1, part2, part3, part4, part5, part6, part7); 349 return join(root, part1, part2, part3, part4, part5, part6, part7);
272 } 350 }
273 351
274 /// Attempts to convert [path] to an equivalent relative path relative to 352 /// Attempts to convert [path] to an equivalent relative path relative to
275 /// [root]. 353 /// [root].
276 /// 354 ///
277 /// var builder = new Builder(root: '/root/path'); 355 /// var builder = new Builder(root: '/root/path');
278 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' 356 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
279 /// builder.relative('/root/other.dart'); // -> '../other.dart' 357 /// builder.relative('/root/other.dart'); // -> '../other.dart'
280 /// 358 ///
359 /// If the [to] argument is passed, [path] is made relative to that instead.
360 ///
361 /// builder.relative('/root/path/a/b.dart',
362 /// to: '/root/path'); // -> 'a/b.dart'
363 /// builder.relative('/root/other.dart',
364 /// to: '/root/path'); // -> '../other.dart'
365 ///
281 /// Since there is no relative path from one drive letter to another on 366 /// Since there is no relative path from one drive letter to another on
282 /// Windows, this will return an absolute path in that case. 367 /// Windows, this will return an absolute path in that case.
283 /// 368 ///
284 /// var builder = new Builder(root: r'C:\home'); 369 /// builder.relative(r'D:\other', to: r'C:\other'); // -> 'D:\other'
285 /// builder.relative(r'D:\other'); // -> 'D:\other' 370 String relative(String path, {String to}) {
286 String relative(String path) {
287 if (path == '') return '.'; 371 if (path == '') return '.';
288 372
289 // If the base path is relative, resolve it relative to the current 373 // If the base path is relative, resolve it relative to the current
290 // directory. 374 // directory.
291 var base = root; 375 var base = to == null ? root : to;
292 if (this.isRelative(base)) base = absolute(base); 376 if (this.isRelative(base)) base = absolute(base);
293 377
294 // If the given path is relative, resolve it relative to the base. 378 // If the given path is relative, resolve it relative to the base.
295 if (this.isRelative(path)) return this.normalize(path); 379 if (this.isRelative(path)) return this.normalize(path);
296 380
297 var baseParsed = _parse(base)..normalize(); 381 var baseParsed = _parse(base)..normalize();
298 var pathParsed = _parse(path)..normalize(); 382 var pathParsed = _parse(path)..normalize();
299 383
300 // If the root prefixes don't match (for example, different drive letters 384 // If the root prefixes don't match (for example, different drive letters
301 // on Windows), then there is no relative path, so just return the absolute 385 // on Windows), then there is no relative path, so just return the absolute
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 610
527 var lastDot = file.lastIndexOf('.'); 611 var lastDot = file.lastIndexOf('.');
528 612
529 // If there is no dot, or it's the first character, like '.bashrc', it 613 // If there is no dot, or it's the first character, like '.bashrc', it
530 // doesn't count. 614 // doesn't count.
531 if (lastDot <= 0) return [file, '']; 615 if (lastDot <= 0) return [file, ''];
532 616
533 return [file.substring(0, lastDot), file.substring(lastDot)]; 617 return [file.substring(0, lastDot), file.substring(lastDot)];
534 } 618 }
535 } 619 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698