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

Side by Side Diff: sdk/lib/io/path.dart

Issue 11968012: Fix Path.relativeTo and add support for relative paths as input. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: #Just say '/' instead of 'path separator' in the doc comments. Created 7 years, 11 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
« no previous file with comments | « no previous file | sdk/lib/io/path_impl.dart » ('j') | sdk/lib/io/path_impl.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of dart.io; 5 part of dart.io;
6 6
7 /** 7 /**
8 * A Path is an immutable wrapper of a String, with additional member functions 8 * A Path is an immutable wrapper of a String, with additional member functions
9 * for useful path manipulations and queries. 9 * for useful path manipulations and queries.
10 * On the Windows platform, Path also converts from and to native paths. 10 * On the Windows platform, Path also converts from native paths to paths using
11 * '/' as a path separator, and vice versa.
11 * 12 *
12 * Joining of paths and path normalization handle '.' and '..' in the usual way. 13 * Joining of paths and path normalization handle '.' and '..' in the usual way.
13 */ 14 */
14 abstract class Path { 15 abstract class Path {
15 /** 16 /**
16 * Creates a Path from a String that uses the native filesystem's conventions. 17 * Creates a Path from a String that uses the native filesystem's conventions.
17 * 18 *
18 * On Windows, this converts '\' to '/' and has special handling for drive 19 * On Windows, this converts '\' to '/' and has special handling for drive
19 * letters and shares. 20 * letters and shares.
20 * 21 *
21 * If the path starts with a drive letter, like 'C:', a '/' is added 22 * If the path starts with a drive letter, like 'C:', a '/' is added
22 * before the drive letter. 23 * before the drive letter.
23 * 24 *
24 * new Path(r'c:\a\b').toString() == '/c:/a/b' 25 * new Path(r'c:\a\b').toString() == '/c:/a/b'
25 * 26 *
26 * A path starting with '/c:/' (or any other character instead of 'c') is 27 * A path starting with a drive letter is
27 * treated specially. Backwards links ('..') cannot cancel the drive letter. 28 * treated specially. Backwards links ('..') cannot cancel the drive letter.
28 * 29 *
29 * If the path is a share path this is recorded in the Path object and 30 * If the path is a share path this is recorded in the Path object and
30 * maintained in operations on the Path object. 31 * maintained in operations on the Path object.
31 * 32 *
32 * var share = new Path(r'\\share\a\b\c'); 33 * var share = new Path(r'\\share\a\b\c');
33 * share.isWindowsShare == true 34 * share.isWindowsShare == true
34 * share.toString() == '/share/a/b/c' 35 * share.toString() == '/share/a/b/c'
35 * share.toNativePath() == r'\\share\a\b\c' 36 * share.toNativePath() == r'\\share\a\b\c'
36 * share.append('final').isWindowsShare == true 37 * share.append('final').isWindowsShare == true
37 */ 38 */
38 factory Path(String source) => new _Path(source); 39 factory Path(String source) => new _Path(source);
39 40
40 /** 41 /**
41 * Creates a Path from the String [source]. [source] is used as-is, so if 42 * Creates a Path from the String [source]. [source] is used as-is, so if
42 * the string does not consist of segments separated by forward slashes, the 43 * the string does not consist of segments separated by forward slashes, the
43 * behavior may not be as expected. Paths are immutable. 44 * behavior may not be as expected. Paths are immutable.
44 */ 45 */
45 factory Path.raw(String source) => new _Path.raw(source); 46 factory Path.raw(String source) => new _Path.raw(source);
46 47
47 /** 48 /**
48 * Is this path the empty string? 49 * Is this path the empty string?
49 */ 50 */
50 bool get isEmpty; 51 bool get isEmpty;
51 52
52 /** 53 /**
53 * Is this path an absolute path, beginning with a path separator? 54 * Is this path an absolute path, beginning with a '/'? Note that
55 * Windows paths beginning with '\' or with a drive letter are absolute,
56 * and a leading '/' is added when they are converted to a Path.
54 */ 57 */
55 bool get isAbsolute; 58 bool get isAbsolute;
56 59
57 /** 60 /**
58 * Is this path a Windows share path? 61 * Is this path a Windows share path?
59 */ 62 */
60 bool get isWindowsShare; 63 bool get isWindowsShare;
61 64
62 /** 65 /**
63 * Does this path end with a path separator? 66 * Does this path end with a '/'?
64 */ 67 */
65 bool get hasTrailingSeparator; 68 bool get hasTrailingSeparator;
66 69
67 /** 70 /**
68 * Does this path contain no consecutive path separators, no segments that 71 * Does this path contain no consecutive '/'s, no segments that
69 * are '.' unless the path is exactly '.', and segments that are '..' only 72 * are '.' unless the path is exactly '.', and segments that are '..' only
70 * as the leading segments on a relative path? 73 * as the leading segments on a relative path?
71 */ 74 */
72 bool get isCanonical; 75 bool get isCanonical;
73 76
74 /** 77 /**
75 * Make a path canonical by dropping segments that are '.', cancelling 78 * Make a path canonical by dropping segments that are '.', cancelling
76 * segments that are '..' with preceding segments, if possible, 79 * segments that are '..' with preceding segments, if possible,
77 * and combining consecutive path separators. Leading '..' segments 80 * and combining consecutive '/'s. Leading '..' segments
78 * are kept on relative paths, and dropped from absolute paths. 81 * are kept on relative paths, and dropped from absolute paths.
79 */ 82 */
80 Path canonicalize(); 83 Path canonicalize();
81 84
82 /** 85 /**
83 * Joins the relative path [further] to this path. Canonicalizes the 86 * Joins the relative path [further] to this path. Canonicalizes the
84 * resulting joined path using [canonicalize], 87 * resulting joined path using [canonicalize],
85 * interpreting '.' and '..' as directory traversal commands, and removing 88 * interpreting '.' and '..' as directory traversal commands, and removing
86 * consecutive path separators. 89 * consecutive '/'s.
87 * 90 *
88 * If [further] is an absolute path, an IllegalArgument exception is thrown. 91 * If [further] is an absolute path, an IllegalArgument exception is thrown.
89 * 92 *
90 * Examples: 93 * Examples:
91 * `new Path('/a/b/c').join(new Path('d/e'))` returns the Path object 94 * `new Path('/a/b/c').join(new Path('d/e'))` returns the Path object
92 * containing `'a/b/c/d/e'`. 95 * containing `'a/b/c/d/e'`.
93 * 96 *
94 * `new Path('a/b/../c/').join(new Path('d/./e//')` returns the Path 97 * `new Path('a/b/../c/').join(new Path('d/./e//')` returns the Path
95 * containing `'a/c/d/e/'`. 98 * containing `'a/c/d/e/'`.
96 * 99 *
97 * `new Path('a/b/c').join(new Path('d/../../e')` returns the Path 100 * `new Path('a/b/c').join(new Path('d/../../e')` returns the Path
98 * containing `'a/b/e'`. 101 * containing `'a/b/e'`.
99 * 102 *
100 * Note that the join operation does not drop the last segment of the 103 * Note that the join operation does not drop the last segment of the
101 * base path, the way URL joining does. That would be accomplished with 104 * base path, the way URL joining does. To join basepath to further using
102 * basepath.directoryPath.join(further). 105 * URL semantics, use
106 * [:basepath.directoryPath.join(further):].
103 * 107 *
104 * If you want to avoid joins that traverse 108 * If you want to avoid joins that traverse
105 * parent directories in the base, you can check whether 109 * parent directories in the base, you can check whether
106 * `further.canonicalize()` starts with '../' or equals '..'. 110 * `further.canonicalize()` starts with '../' or equals '..'.
107 */ 111 */
108 Path join(Path further); 112 Path join(Path further);
109 113
110 114
111 /** 115 /**
112 * Returns a path [:relative:] such that 116 * Returns a path [:relative:] such that
113 * [:base.join(relative) == this.canonicalize():]. 117 * [:base.join(relative) == this.canonicalize():].
114 * Throws an exception if such a path is impossible. 118 * Throws an exception if such a path is impossible.
115 * For example, if [base] is '../../a/b' and [this] is '.'. 119 * For example, if [base] is '../../a/b' and [this] is '.'.
116 * The computation is independent of the file system and current directory. 120 * The computation is independent of the file system and current directory.
121 *
122 * To compute a relative path using URL semantics, where the final
123 * path component of the base is dropped unless it ends with a slash,
124 * call [: a.relativeTo(b.directoryPath) :] instead of [: a.relativeTo(b) :].
117 */ 125 */
118 Path relativeTo(Path base); 126 Path relativeTo(Path base);
119 127
120 /** 128 /**
121 * Converts a path to a string using the native filesystem's conventions. 129 * Converts a path to a string using the native filesystem's conventions.
122 * 130 *
123 * On Windows, converts path separators to backwards slashes, and removes 131 * On Windows, converts '/'s to backwards slashes, and removes
124 * the leading path separator if the path starts with a drive specification. 132 * the leading '/' if the path starts with a drive specification.
125 * For most valid Windows paths, this should be the inverse of the 133 * For most valid Windows paths, this should be the inverse of the
126 * constructor Path.fromNative. 134 * conversion that the constructor new Path() performs. If the path is
135 * a Windows share, restores the '\\' at the start of the path.
127 */ 136 */
128 String toNativePath(); 137 String toNativePath();
129 138
130 /** 139 /**
131 * Returns the path as a string. If this path is constructed using 140 * Returns the path as a string. If this path is constructed using
132 * new Path.raw(), or new Path() on a non-Windows system, the 141 * new Path.raw(), or new Path() on a non-Windows system, the
133 * returned value is the original string argument to the constructor. 142 * returned value is the original string argument to the constructor.
134 */ 143 */
135 String toString(); 144 String toString();
136 145
137 /** 146 /**
138 * Gets the segments of a Path. Paths beginning or ending with the 147 * Gets the segments of a Path. The segments are just the result of
139 * path separator do not have leading or terminating empty segments. 148 * splitting the path on any '/' characters, except that a '/' at the
140 * Other than that, the segments are just the result of splitting the 149 * beginning does not create an empty segment before it, and a '/' at
141 * path on the path separator. 150 * the end does not create an empty segment after it.
142 * 151 *
143 * new Path('/a/b/c/d').segments() == ['a', 'b', 'c', d']; 152 * new Path('/a/b/c/d').segments() == ['a', 'b', 'c', d'];
144 * new Path(' foo bar //../') == [' foo bar ', '', '..']; 153 * new Path(' foo bar //../') == [' foo bar ', '', '..'];
145 */ 154 */
146 List<String> segments(); 155 List<String> segments();
147 156
148 /** 157 /**
149 * Appends [finalSegment] to a path as a new segment. Adds a path separator 158 * Appends [finalSegment] to a path as a new segment. Adds a '/'
150 * between the path and [finalSegment] if the path does not already end in 159 * between the path and [finalSegment] if the path does not already end in
151 * a path separator. The path is not canonicalized, and [finalSegment] may 160 * a '/'. The path is not canonicalized, and [finalSegment] may
152 * contain path separators. 161 * contain '/'s.
153 */ 162 */
154 Path append(String finalSegment); 163 Path append(String finalSegment);
155 164
156 /** 165 /**
157 * Drops the final path separator and whatever follows it from this Path, 166 * Drops the final '/' and whatever follows it from this Path,
158 * and returns the resulting Path object. If the only path separator in 167 * and returns the resulting Path object. If the only '/' in
159 * this Path is the first character, returns '/' instead of the empty string. 168 * this Path is the first character, returns '/' instead of the empty string.
160 * If there is no path separator in the Path, returns the empty string. 169 * If there is no '/' in the Path, returns the empty string.
161 * 170 *
162 * new Path('../images/dot.gif').directoryPath == '../images' 171 * new Path('../images/dot.gif').directoryPath == '../images'
163 * new Path('/usr/geoffrey/www/').directoryPath == '/usr/geoffrey/www' 172 * new Path('/usr/geoffrey/www/').directoryPath == '/usr/geoffrey/www'
164 * new Path('lost_file_old').directoryPath == '' 173 * new Path('lost_file_old').directoryPath == ''
165 * new Path('/src').directoryPath == '/' 174 * new Path('/src').directoryPath == '/'
166 * Note: new Path('/D:/src').directoryPath == '/D:' 175 * Note: new Path('/D:/src').directoryPath == '/D:'
167 */ 176 */
168 Path get directoryPath; 177 Path get directoryPath;
169 178
170 /** 179 /**
171 * The part of the path after the last path separator, or the entire path if 180 * The part of the path after the last '/', or the entire path if
172 * it contains no path separator. 181 * it contains no '/'.
173 * 182 *
174 * new Path('images/DSC_0027.jpg).filename == 'DSC_0027.jpg' 183 * new Path('images/DSC_0027.jpg).filename == 'DSC_0027.jpg'
175 * new Path('users/fred/').filename == '' 184 * new Path('users/fred/').filename == ''
176 */ 185 */
177 String get filename; 186 String get filename;
178 187
179 /** 188 /**
180 * The part of [filename] before the last '.', or the entire filename if it 189 * The part of [filename] before the last '.', or the entire filename if it
181 * contains no '.'. If [filename] is '.' or '..' it is unchanged. 190 * contains no '.'. If [filename] is '.' or '..' it is unchanged.
182 * 191 *
183 * new Path('/c:/My Documents/Heidi.txt').filenameWithoutExtension 192 * new Path('/c:/My Documents/Heidi.txt').filenameWithoutExtension
184 * would return 'Heidi'. 193 * would return 'Heidi'.
185 * new Path('not what I would call a path').filenameWithoutExtension 194 * new Path('not what I would call a path').filenameWithoutExtension
186 * would return 'not what I would call a path'. 195 * would return 'not what I would call a path'.
187 */ 196 */
188 String get filenameWithoutExtension; 197 String get filenameWithoutExtension;
189 198
190 /** 199 /**
191 * The part of [filename] after the last '.', or '' if [filename] 200 * The part of [filename] after the last '.', or '' if [filename]
192 * contains no '.'. If [filename] is '.' or '..', returns ''. 201 * contains no '.'. If [filename] is '.' or '..', returns ''.
193 * 202 *
194 * new Path('tiger.svg').extension == 'svg' 203 * new Path('tiger.svg').extension == 'svg'
195 * new Path('/src/dart/dart_secrets').extension == '' 204 * new Path('/src/dart/dart_secrets').extension == ''
196 */ 205 */
197 String get extension; 206 String get extension;
198 } 207 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/path_impl.dart » ('j') | sdk/lib/io/path_impl.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698