OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 * [Link] objects are references to filesystem links. | 8 * [Link] objects are references to filesystem links. |
9 * | 9 * |
10 */ | 10 */ |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 /** | 94 /** |
95 * Renames this link. Returns a `Future<Link>` that completes | 95 * Renames this link. Returns a `Future<Link>` that completes |
96 * with a [Link] instance for the renamed link. | 96 * with a [Link] instance for the renamed link. |
97 * | 97 * |
98 * If [newPath] identifies an existing link, that link is | 98 * If [newPath] identifies an existing link, that link is |
99 * replaced. If [newPath] identifies an existing file or directory, | 99 * replaced. If [newPath] identifies an existing file or directory, |
100 * the operation fails and the future completes with an exception. | 100 * the operation fails and the future completes with an exception. |
101 */ | 101 */ |
102 Future<Link> rename(String newPath); | 102 Future<Link> rename(String newPath); |
103 | 103 |
104 /** | 104 /** |
105 * Synchronously renames this link. Returns a [Link] | 105 * Synchronously renames this link. Returns a [Link] |
106 * instance for the renamed link. | 106 * instance for the renamed link. |
107 * | 107 * |
108 * If [newPath] identifies an existing link, that link is | 108 * If [newPath] identifies an existing link, that link is |
109 * replaced. If [newPath] identifies an existing file or directory | 109 * replaced. If [newPath] identifies an existing file or directory |
110 * the operation fails and an exception is thrown. | 110 * the operation fails and an exception is thrown. |
111 */ | 111 */ |
112 Link renameSync(String newPath); | 112 Link renameSync(String newPath); |
113 | 113 |
114 /** | 114 /** |
(...skipping 21 matching lines...) Expand all Loading... |
136 * Synchronously gets the target of the link. Returns the path to the target. | 136 * Synchronously gets the target of the link. Returns the path to the target. |
137 * | 137 * |
138 * If the returned target is a relative path, it is relative to the | 138 * If the returned target is a relative path, it is relative to the |
139 * directory containing the link. | 139 * directory containing the link. |
140 * | 140 * |
141 * If the link does not exist, or is not a link, throws a FileSystemException. | 141 * If the link does not exist, or is not a link, throws a FileSystemException. |
142 */ | 142 */ |
143 String targetSync(); | 143 String targetSync(); |
144 } | 144 } |
145 | 145 |
146 | |
147 class _Link extends FileSystemEntity implements Link { | 146 class _Link extends FileSystemEntity implements Link { |
148 final String path; | 147 final String path; |
149 | 148 |
150 _Link(this.path) { | 149 _Link(this.path) { |
151 if (path is! String) { | 150 if (path is! String) { |
152 throw new ArgumentError('${Error.safeToString(path)} ' | 151 throw new ArgumentError('${Error.safeToString(path)} ' |
153 'is not a String'); | 152 'is not a String'); |
154 } | 153 } |
155 } | 154 } |
156 | 155 |
157 String toString() => "Link: '$path'"; | 156 String toString() => "Link: '$path'"; |
158 | 157 |
159 Future<bool> exists() => FileSystemEntity.isLink(path); | 158 Future<bool> exists() => FileSystemEntity.isLink(path); |
160 | 159 |
161 bool existsSync() => FileSystemEntity.isLinkSync(path); | 160 bool existsSync() => FileSystemEntity.isLinkSync(path); |
162 | 161 |
163 Link get absolute => new Link(_absolutePath); | 162 Link get absolute => new Link(_absolutePath); |
164 | 163 |
165 Future<Link> create(String target, {bool recursive: false}) { | 164 Future<Link> create(String target, {bool recursive: false}) { |
166 if (Platform.isWindows) { | 165 if (Platform.isWindows) { |
167 target = _makeWindowsLinkTarget(target); | 166 target = _makeWindowsLinkTarget(target); |
168 } | 167 } |
169 var result = recursive ? parent.create(recursive: true) | 168 var result = |
170 : new Future.value(null); | 169 recursive ? parent.create(recursive: true) : new Future.value(null); |
171 return result | 170 return result |
172 .then((_) => _IOService._dispatch(_FILE_CREATE_LINK, [path, target])) | 171 .then((_) => _IOService._dispatch(_FILE_CREATE_LINK, [path, target])) |
173 .then((response) { | 172 .then((response) { |
174 if (_isErrorResponse(response)) { | 173 if (_isErrorResponse(response)) { |
175 throw _exceptionFromResponse( | 174 throw _exceptionFromResponse( |
176 response, "Cannot create link to target '$target'", path); | 175 response, "Cannot create link to target '$target'", path); |
177 } | 176 } |
178 return this; | 177 return this; |
179 }); | 178 }); |
180 } | 179 } |
181 | 180 |
182 void createSync(String target, {bool recursive: false}) { | 181 void createSync(String target, {bool recursive: false}) { |
183 if (recursive) { | 182 if (recursive) { |
184 parent.createSync(recursive: true); | 183 parent.createSync(recursive: true); |
185 } | 184 } |
186 if (Platform.isWindows) { | 185 if (Platform.isWindows) { |
187 target = _makeWindowsLinkTarget(target); | 186 target = _makeWindowsLinkTarget(target); |
188 } | 187 } |
189 var result = _File._createLink(path, target); | 188 var result = _File._createLink(path, target); |
190 throwIfError(result, "Cannot create link", path); | 189 throwIfError(result, "Cannot create link", path); |
191 } | 190 } |
192 | 191 |
193 // Put target into the form "\??\C:\my\target\dir". | 192 // Put target into the form "\??\C:\my\target\dir". |
194 String _makeWindowsLinkTarget(String target) { | 193 String _makeWindowsLinkTarget(String target) { |
195 Uri base = new Uri.file('${Directory.current.path}\\'); | 194 Uri base = new Uri.file('${Directory.current.path}\\'); |
196 Uri link = new Uri.file(path); | 195 Uri link = new Uri.file(path); |
197 Uri destination = new Uri.file(target); | 196 Uri destination = new Uri.file(target); |
198 String result = base.resolveUri(link).resolveUri(destination).toFilePath(); | 197 String result = base.resolveUri(link).resolveUri(destination).toFilePath(); |
199 if (result.length > 3 && result[1] == ':' && result[2] == '\\') { | 198 if (result.length > 3 && result[1] == ':' && result[2] == '\\') { |
200 return '\\??\\$result'; | 199 return '\\??\\$result'; |
201 } else { | 200 } else { |
202 throw new FileSystemException( | 201 throw new FileSystemException( |
203 'Target $result of Link.create on Windows cannot be converted' + | 202 'Target $result of Link.create on Windows cannot be converted' + |
204 ' to start with a drive letter. Unexpected error.'); | 203 ' to start with a drive letter. Unexpected error.'); |
205 } | 204 } |
206 } | 205 } |
207 | 206 |
208 void updateSync(String target) { | 207 void updateSync(String target) { |
209 // TODO(12414): Replace with atomic update, where supported by platform. | 208 // TODO(12414): Replace with atomic update, where supported by platform. |
210 // Atomically changing a link can be done by creating the new link, with | 209 // Atomically changing a link can be done by creating the new link, with |
211 // a different name, and using the rename() posix call to move it to | 210 // a different name, and using the rename() posix call to move it to |
212 // the old name atomically. | 211 // the old name atomically. |
213 deleteSync(); | 212 deleteSync(); |
214 createSync(target); | 213 createSync(target); |
(...skipping 21 matching lines...) Expand all Loading... |
236 | 235 |
237 void _deleteSync({bool recursive: false}) { | 236 void _deleteSync({bool recursive: false}) { |
238 if (recursive) { | 237 if (recursive) { |
239 return new Directory(path).deleteSync(recursive: true); | 238 return new Directory(path).deleteSync(recursive: true); |
240 } | 239 } |
241 var result = _File._deleteLinkNative(path); | 240 var result = _File._deleteLinkNative(path); |
242 throwIfError(result, "Cannot delete link", path); | 241 throwIfError(result, "Cannot delete link", path); |
243 } | 242 } |
244 | 243 |
245 Future<Link> rename(String newPath) { | 244 Future<Link> rename(String newPath) { |
246 return _IOService._dispatch(_FILE_RENAME_LINK, [path, newPath]) | 245 return _IOService |
247 .then((response) { | 246 ._dispatch(_FILE_RENAME_LINK, [path, newPath]).then((response) { |
248 if (_isErrorResponse(response)) { | 247 if (_isErrorResponse(response)) { |
249 throw _exceptionFromResponse( | 248 throw _exceptionFromResponse( |
250 response, "Cannot rename link to '$newPath'", path); | 249 response, "Cannot rename link to '$newPath'", path); |
251 } | 250 } |
252 return new Link(newPath); | 251 return new Link(newPath); |
253 }); | 252 }); |
254 } | 253 } |
255 | 254 |
256 Link renameSync(String newPath) { | 255 Link renameSync(String newPath) { |
257 var result = _File._renameLink(path, newPath); | 256 var result = _File._renameLink(path, newPath); |
258 throwIfError(result, "Cannot rename link '$path' to '$newPath'"); | 257 throwIfError(result, "Cannot rename link '$path' to '$newPath'"); |
259 return new Link(newPath); | 258 return new Link(newPath); |
260 } | 259 } |
261 | 260 |
262 Future<String> target() { | 261 Future<String> target() { |
263 return _IOService._dispatch(_FILE_LINK_TARGET, [path]).then((response) { | 262 return _IOService._dispatch(_FILE_LINK_TARGET, [path]).then((response) { |
(...skipping 21 matching lines...) Expand all Loading... |
285 return response is List && response[0] != _SUCCESS_RESPONSE; | 284 return response is List && response[0] != _SUCCESS_RESPONSE; |
286 } | 285 } |
287 | 286 |
288 _exceptionFromResponse(response, String message, String path) { | 287 _exceptionFromResponse(response, String message, String path) { |
289 assert(_isErrorResponse(response)); | 288 assert(_isErrorResponse(response)); |
290 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { | 289 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { |
291 case _ILLEGAL_ARGUMENT_RESPONSE: | 290 case _ILLEGAL_ARGUMENT_RESPONSE: |
292 return new ArgumentError(); | 291 return new ArgumentError(); |
293 case _OSERROR_RESPONSE: | 292 case _OSERROR_RESPONSE: |
294 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], | 293 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], |
295 response[_OSERROR_RESPONSE_ERROR_CODE]); | 294 response[_OSERROR_RESPONSE_ERROR_CODE]); |
296 return new FileSystemException(message, path, err); | 295 return new FileSystemException(message, path, err); |
297 default: | 296 default: |
298 return new Exception("Unknown error"); | 297 return new Exception("Unknown error"); |
299 } | 298 } |
300 } | 299 } |
301 } | 300 } |
OLD | NEW |