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 class FileSystemEntityType { | 7 class FileSystemEntityType { |
8 static const FILE = const FileSystemEntityType._internal(0); | 8 static const FILE = const FileSystemEntityType._internal(0); |
9 static const DIRECTORY = const FileSystemEntityType._internal(1); | 9 static const DIRECTORY = const FileSystemEntityType._internal(1); |
10 static const LINK = const FileSystemEntityType._internal(2); | 10 static const LINK = const FileSystemEntityType._internal(2); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 * | 161 * |
162 * [FileSystemEntity] objects are returned from directory listing | 162 * [FileSystemEntity] objects are returned from directory listing |
163 * operations. To determine if a FileSystemEntity is a [File] or a | 163 * operations. To determine if a FileSystemEntity is a [File] or a |
164 * [Directory], perform a type check: | 164 * [Directory], perform a type check: |
165 * | 165 * |
166 * if (entity is File) (entity as File).readAsStringSync(); | 166 * if (entity is File) (entity as File).readAsStringSync(); |
167 */ | 167 */ |
168 abstract class FileSystemEntity { | 168 abstract class FileSystemEntity { |
169 String get path; | 169 String get path; |
170 | 170 |
171 external static _getType(String path, bool followLinks); | |
172 external static _identical(String path1, String path2); | |
173 | |
174 static int _getTypeSync(String path, bool followLinks) { | |
175 var result = _getType(path, followLinks); | |
176 _throwIfError(result, 'Error getting type of FileSystemEntity'); | |
177 return result; | |
178 } | |
179 | |
180 static Future<int> _getTypeAsync(String path, bool followLinks) { | |
181 // Get a new file service port for each request. We could also cache one. | |
182 var service = _FileUtils._newServicePort(); | |
183 List request = new List(3); | |
184 request[0] = _TYPE_REQUEST; | |
185 request[1] = path; | |
186 request[2] = followLinks; | |
187 return service.call(request).then((response) { | |
188 if (_isErrorResponse(response)) { | |
189 throw _exceptionFromResponse(response, "Error getting type", path); | |
190 } | |
191 return response; | |
192 }); | |
193 } | |
194 | |
195 /** | |
196 * Synchronously checks whether two paths refer to the same object in the | |
197 * file system. Returns a [:Future<bool>:] that completes with the result. | |
198 * | |
199 * Comparing a link to its target returns false, as does comparing two links | |
200 * that point to the same target. To check the target of a link, use | |
201 * Link.target explicitly to fetch it. Directory links appearing | |
202 * inside a path are followed, though, to find the file system object. | |
203 * | |
204 * Completes the returned Future with an error if one of the paths points | |
205 * to an object that does not exist. | |
206 */ | |
207 static Future<bool> identical(String path1, String path2) { | |
208 // Get a new file service port for each request. We could also cache one. | |
209 var service = _FileUtils._newServicePort(); | |
210 List request = new List(3); | |
211 request[0] = _IDENTICAL_REQUEST; | |
212 request[1] = path1; | |
213 request[2] = path2; | |
214 return service.call(request).then((response) { | |
215 if (_isErrorResponse(response)) { | |
216 throw _exceptionFromResponse(response, | |
217 "Error in FileSystemEntity.identical($path1, $path2)", ""); | |
218 } | |
219 return response; | |
220 }); | |
221 } | |
222 | |
223 | |
224 /** | |
225 * Synchronously checks whether two paths refer to the same object in the | |
226 * file system. | |
227 * | |
228 * Comparing a link to its target returns false, as does comparing two links | |
229 * that point to the same target. To check the target of a link, use | |
230 * Link.target explicitly to fetch it. Directory links appearing | |
231 * inside a path are followed, though, to find the file system object. | |
232 * | |
233 * Throws an error if one of the paths points to an object that does not | |
234 * exist. | |
235 */ | |
236 static bool identicalSync(String path1, String path2) { | |
237 var result = _identical(path1, path2); | |
238 _throwIfError(result, 'Error in FileSystemEntity.identicalSync'); | |
239 return result; | |
240 } | |
241 | |
242 /** | 171 /** |
243 * Checks whether the file system entity with this path exists. Returns | 172 * Checks whether the file system entity with this path exists. Returns |
244 * a [:Future<bool>:] that completes with the result. | 173 * a [:Future<bool>:] that completes with the result. |
245 * | 174 * |
246 * Since FileSystemEntity is abstract, every FileSystemEntity object | 175 * Since FileSystemEntity is abstract, every FileSystemEntity object |
247 * is actually an instance of one of the subclasses [File], | 176 * is actually an instance of one of the subclasses [File], |
248 * [Directory], and [Link]. Calling [exists] on an instance of one | 177 * [Directory], and [Link]. Calling [exists] on an instance of one |
249 * of these subclasses checks whether the object exists in the file | 178 * of these subclasses checks whether the object exists in the file |
250 * system object exists and is of the correct type (file, directory, | 179 * system object exists and is of the correct type (file, directory, |
251 * or link). To check whether a path points to an object on the | 180 * or link). To check whether a path points to an object on the |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 * [path] of this [FileSystemEntity]. | 238 * [path] of this [FileSystemEntity]. |
310 * Identical to [:FileStat.statSync(this.path):]. | 239 * Identical to [:FileStat.statSync(this.path):]. |
311 * | 240 * |
312 * Returns a [FileStat] object containing the data returned by stat(). | 241 * Returns a [FileStat] object containing the data returned by stat(). |
313 * | 242 * |
314 * If the call fails, returns a [FileStat] object with .type set to | 243 * If the call fails, returns a [FileStat] object with .type set to |
315 * FileSystemEntityType.NOT_FOUND and the other fields invalid. | 244 * FileSystemEntityType.NOT_FOUND and the other fields invalid. |
316 */ | 245 */ |
317 FileStat statSync(); | 246 FileStat statSync(); |
318 | 247 |
| 248 /** |
| 249 * Deletes this [FileSystemEntity]. |
| 250 * |
| 251 * If the [FileSystemEntity] is a directory, and if [recursive] is false, |
| 252 * the directory must be empty. Otherwise, if [recursive] is true, the |
| 253 * directory and all sub-directories and files in the directories are |
| 254 * deleted. Links are not followed when deleting recursively. Only the link |
| 255 * is deleted, not its target. |
| 256 * |
| 257 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type |
| 258 * of the [FileSystemEntity] doesn't match the content of the file system. |
| 259 * This behavior allows [delete] to be used to unconditionally delete any file |
| 260 * system object. |
| 261 * |
| 262 * Returns a [:Future<FileSystemEntity>:] that completes with this |
| 263 * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity] |
| 264 * cannot be deleted, the future completes with an exception. |
| 265 */ |
| 266 Future<FileSystemEntity> delete({recursive: false}) |
| 267 => _delete(recursive: recursive); |
| 268 |
| 269 /** |
| 270 * Synchronously deletes this [FileSystemEntity]. |
| 271 * |
| 272 * If the [FileSystemEntity] is a directory, and if [recursive] is false, |
| 273 * the directory must be empty. Otherwise, if [recursive] is true, the |
| 274 * directory and all sub-directories and files in the directories are |
| 275 * deleted. Links are not followed when deleting recursively. Only the link |
| 276 * is deleted, not its target. |
| 277 * |
| 278 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type |
| 279 * of the [FileSystemEntity] doesn't match the content of the file system. |
| 280 * This behavior allows [deleteSync] to be used to unconditionally delete any |
| 281 * file system object. |
| 282 * |
| 283 * Throws an exception if the [FileSystemEntity] cannot be deleted. |
| 284 */ |
| 285 void deleteSync({recursive: false}) |
| 286 => _deleteSync(recursive: recursive); |
319 | 287 |
320 | 288 |
321 /** | 289 /** |
322 * Start watch the [FileSystemEntity] for changes. | 290 * Start watch the [FileSystemEntity] for changes. |
323 * | 291 * |
324 * The implementation uses platform-depending event-based APIs for receiving | 292 * The implementation uses platform-depending event-based APIs for receiving |
325 * file-system notifixations, thus behvaiour depends on the platform. | 293 * file-system notifixations, thus behvaiour depends on the platform. |
326 * | 294 * |
327 * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation supports | 295 * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation supports |
328 * only watching dirctories but supports recursive watching. | 296 * only watching dirctories but supports recursive watching. |
329 * * `Linux`: Uses `inotify`. The implementation supports watching both | 297 * * `Linux`: Uses `inotify`. The implementation supports watching both |
330 * files and dirctories, but doesn't support recursive watching. | 298 * files and dirctories, but doesn't support recursive watching. |
331 * * `Mac OS`: Uses `FSEvents`. The implementation supports watching both | 299 * * `Mac OS`: Uses `FSEvents`. The implementation supports watching both |
332 * files and dirctories, and also recursive watching. Note that FSEvents | 300 * files and dirctories, and also recursive watching. Note that FSEvents |
333 * always use recursion internally, so when disabled, some events are | 301 * always use recursion internally, so when disabled, some events are |
334 * ignored. | 302 * ignored. |
335 * | 303 * |
336 * The system will start listen for events once the returned [Stream] is | 304 * The system will start listen for events once the returned [Stream] is |
337 * being listened to, not when the call to [watch] is issued. Note that the | 305 * being listened to, not when the call to [watch] is issued. Note that the |
338 * returned [Stream] is endless. To stop the [Stream], simply cancel the | 306 * returned [Stream] is endless. To stop the [Stream], simply cancel the |
339 * subscription. | 307 * subscription. |
340 */ | 308 */ |
341 Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL, | 309 Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL, |
342 bool recursive: false}) | 310 bool recursive: false}) |
343 => new _FileSystemWatcher(_trimTrailingPathSeparators(path), | 311 => new _FileSystemWatcher(_trimTrailingPathSeparators(path), |
344 events, | 312 events, |
345 recursive).stream; | 313 recursive).stream; |
346 | 314 |
| 315 Future<FileSystemEntity> _delete({recursive: false}); |
| 316 void _deleteSync({recursive: false}); |
| 317 |
| 318 /** |
| 319 * Synchronously checks whether two paths refer to the same object in the |
| 320 * file system. Returns a [:Future<bool>:] that completes with the result. |
| 321 * |
| 322 * Comparing a link to its target returns false, as does comparing two links |
| 323 * that point to the same target. To check the target of a link, use |
| 324 * Link.target explicitly to fetch it. Directory links appearing |
| 325 * inside a path are followed, though, to find the file system object. |
| 326 * |
| 327 * Completes the returned Future with an error if one of the paths points |
| 328 * to an object that does not exist. |
| 329 */ |
| 330 static Future<bool> identical(String path1, String path2) { |
| 331 // Get a new file service port for each request. We could also cache one. |
| 332 var service = _FileUtils._newServicePort(); |
| 333 List request = new List(3); |
| 334 request[0] = _IDENTICAL_REQUEST; |
| 335 request[1] = path1; |
| 336 request[2] = path2; |
| 337 return service.call(request).then((response) { |
| 338 if (_isErrorResponse(response)) { |
| 339 throw _exceptionFromResponse(response, |
| 340 "Error in FileSystemEntity.identical($path1, $path2)", ""); |
| 341 } |
| 342 return response; |
| 343 }); |
| 344 } |
| 345 |
| 346 |
| 347 /** |
| 348 * Synchronously checks whether two paths refer to the same object in the |
| 349 * file system. |
| 350 * |
| 351 * Comparing a link to its target returns false, as does comparing two links |
| 352 * that point to the same target. To check the target of a link, use |
| 353 * Link.target explicitly to fetch it. Directory links appearing |
| 354 * inside a path are followed, though, to find the file system object. |
| 355 * |
| 356 * Throws an error if one of the paths points to an object that does not |
| 357 * exist. |
| 358 */ |
| 359 static bool identicalSync(String path1, String path2) { |
| 360 var result = _identical(path1, path2); |
| 361 _throwIfError(result, 'Error in FileSystemEntity.identicalSync'); |
| 362 return result; |
| 363 } |
| 364 |
347 /** | 365 /** |
348 * Test if [watch] is supported on the current system. | 366 * Test if [watch] is supported on the current system. |
349 * | 367 * |
350 * Mac OS 10.6 and below is not supported. | 368 * Mac OS 10.6 and below is not supported. |
351 */ | 369 */ |
352 static bool get isWatchSupported => _FileSystemWatcher.isSupported; | 370 static bool get isWatchSupported => _FileSystemWatcher.isSupported; |
353 | 371 |
354 | |
355 /** | 372 /** |
356 * Finds the type of file system object that a path points to. Returns | 373 * Finds the type of file system object that a path points to. Returns |
357 * a [:Future<FileSystemEntityType>:] that completes with the result. | 374 * a [:Future<FileSystemEntityType>:] that completes with the result. |
358 * | 375 * |
359 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, | 376 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, |
360 * LINK, and NOT_FOUND. [type] will return LINK only if the optional | 377 * LINK, and NOT_FOUND. [type] will return LINK only if the optional |
361 * named argument [followLinks] is false, and [path] points to a link. | 378 * named argument [followLinks] is false, and [path] points to a link. |
362 * If the path does not point to a file system object, or any other error | 379 * If the path does not point to a file system object, or any other error |
363 * occurs in looking up the path, NOT_FOUND is returned. The only | 380 * occurs in looking up the path, NOT_FOUND is returned. The only |
364 * error or exception that may be put on the returned future is ArgumentError, | 381 * error or exception that may be put on the returned future is ArgumentError, |
(...skipping 11 matching lines...) Expand all Loading... |
376 * LINK, and NOT_FOUND. [type] will return LINK only if the optional | 393 * LINK, and NOT_FOUND. [type] will return LINK only if the optional |
377 * named argument [followLinks] is false, and [path] points to a link. | 394 * named argument [followLinks] is false, and [path] points to a link. |
378 * If the path does not point to a file system object, or any other error | 395 * If the path does not point to a file system object, or any other error |
379 * occurs in looking up the path, NOT_FOUND is returned. The only | 396 * occurs in looking up the path, NOT_FOUND is returned. The only |
380 * error or exception that may be thrown is ArgumentError, | 397 * error or exception that may be thrown is ArgumentError, |
381 * caused by passing the wrong type of arguments to the function. | 398 * caused by passing the wrong type of arguments to the function. |
382 */ | 399 */ |
383 static FileSystemEntityType typeSync(String path, {bool followLinks: true}) | 400 static FileSystemEntityType typeSync(String path, {bool followLinks: true}) |
384 => FileSystemEntityType._lookup(_getTypeSync(path, followLinks)); | 401 => FileSystemEntityType._lookup(_getTypeSync(path, followLinks)); |
385 | 402 |
386 | |
387 /** | 403 /** |
388 * Checks if type(path, followLinks: false) returns | 404 * Checks if type(path, followLinks: false) returns |
389 * FileSystemEntityType.LINK. | 405 * FileSystemEntityType.LINK. |
390 */ | 406 */ |
391 static Future<bool> isLink(String path) => _getTypeAsync(path, false) | 407 static Future<bool> isLink(String path) => _getTypeAsync(path, false) |
392 .then((type) => (type == FileSystemEntityType.LINK._type)); | 408 .then((type) => (type == FileSystemEntityType.LINK._type)); |
393 | 409 |
394 /** | 410 /** |
395 * Checks if type(path) returns FileSystemEntityType.FILE. | 411 * Checks if type(path) returns FileSystemEntityType.FILE. |
396 */ | 412 */ |
(...skipping 20 matching lines...) Expand all Loading... |
417 static bool isFileSync(String path) => | 433 static bool isFileSync(String path) => |
418 (_getTypeSync(path, true) == FileSystemEntityType.FILE._type); | 434 (_getTypeSync(path, true) == FileSystemEntityType.FILE._type); |
419 | 435 |
420 /** | 436 /** |
421 * Synchronously checks if typeSync(path) returns | 437 * Synchronously checks if typeSync(path) returns |
422 * FileSystemEntityType.DIRECTORY. | 438 * FileSystemEntityType.DIRECTORY. |
423 */ | 439 */ |
424 static bool isDirectorySync(String path) => | 440 static bool isDirectorySync(String path) => |
425 (_getTypeSync(path, true) == FileSystemEntityType.DIRECTORY._type); | 441 (_getTypeSync(path, true) == FileSystemEntityType.DIRECTORY._type); |
426 | 442 |
| 443 external static _getType(String path, bool followLinks); |
| 444 external static _identical(String path1, String path2); |
| 445 |
| 446 static int _getTypeSync(String path, bool followLinks) { |
| 447 var result = _getType(path, followLinks); |
| 448 _throwIfError(result, 'Error getting type of FileSystemEntity'); |
| 449 return result; |
| 450 } |
| 451 |
| 452 static Future<int> _getTypeAsync(String path, bool followLinks) { |
| 453 // Get a new file service port for each request. We could also cache one. |
| 454 var service = _FileUtils._newServicePort(); |
| 455 List request = new List(3); |
| 456 request[0] = _TYPE_REQUEST; |
| 457 request[1] = path; |
| 458 request[2] = followLinks; |
| 459 return service.call(request).then((response) { |
| 460 if (_isErrorResponse(response)) { |
| 461 throw _exceptionFromResponse(response, "Error getting type", path); |
| 462 } |
| 463 return response; |
| 464 }); |
| 465 } |
427 | 466 |
428 static _throwIfError(Object result, String msg, [String path]) { | 467 static _throwIfError(Object result, String msg, [String path]) { |
429 if (result is OSError) { | 468 if (result is OSError) { |
430 throw new FileException(msg, path, result); | 469 throw new FileException(msg, path, result); |
431 } else if (result is ArgumentError) { | 470 } else if (result is ArgumentError) { |
432 throw result; | 471 throw result; |
433 } | 472 } |
434 } | 473 } |
435 | 474 |
436 static String _trimTrailingPathSeparators(String path) { | 475 static String _trimTrailingPathSeparators(String path) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 } | 580 } |
542 } | 581 } |
543 | 582 |
544 | 583 |
545 abstract class _FileSystemWatcher { | 584 abstract class _FileSystemWatcher { |
546 external factory _FileSystemWatcher(String path, int events, bool recursive); | 585 external factory _FileSystemWatcher(String path, int events, bool recursive); |
547 external static bool get isSupported; | 586 external static bool get isSupported; |
548 | 587 |
549 Stream<FileSystemEvent> get stream; | 588 Stream<FileSystemEvent> get stream; |
550 } | 589 } |
OLD | NEW |