| 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 * The type of an entity on the file system, such as a file, directory, or link. | 8 * The type of an entity on the file system, such as a file, directory, or link. |
| 9 * | 9 * |
| 10 * These constants are used by the [FileSystemEntity] class | 10 * These constants are used by the [FileSystemEntity] class |
| 11 * to indicate the object's type. | 11 * to indicate the object's type. |
| 12 * | 12 * |
| 13 */ | 13 */ |
| 14 | 14 |
| 15 class FileSystemEntityType { | 15 class FileSystemEntityType { |
| 16 static const FILE = const FileSystemEntityType._internal(0); | 16 static const FILE = const FileSystemEntityType._internal(0); |
| 17 static const DIRECTORY = const FileSystemEntityType._internal(1); | 17 static const DIRECTORY = const FileSystemEntityType._internal(1); |
| 18 static const LINK = const FileSystemEntityType._internal(2); | 18 static const LINK = const FileSystemEntityType._internal(2); |
| 19 static const NOT_FOUND = const FileSystemEntityType._internal(3); | 19 static const NOT_FOUND = const FileSystemEntityType._internal(3); |
| 20 static const _typeList = const [FileSystemEntityType.FILE, | 20 static const _typeList = const [ |
| 21 FileSystemEntityType.DIRECTORY, | 21 FileSystemEntityType.FILE, |
| 22 FileSystemEntityType.LINK, | 22 FileSystemEntityType.DIRECTORY, |
| 23 FileSystemEntityType.NOT_FOUND]; | 23 FileSystemEntityType.LINK, |
| 24 FileSystemEntityType.NOT_FOUND |
| 25 ]; |
| 24 final int _type; | 26 final int _type; |
| 25 | 27 |
| 26 const FileSystemEntityType._internal(this._type); | 28 const FileSystemEntityType._internal(this._type); |
| 27 | 29 |
| 28 static FileSystemEntityType _lookup(int type) => _typeList[type]; | 30 static FileSystemEntityType _lookup(int type) => _typeList[type]; |
| 29 String toString() => const ['FILE', 'DIRECTORY', 'LINK', 'NOT_FOUND'][_type]; | 31 String toString() => const ['FILE', 'DIRECTORY', 'LINK', 'NOT_FOUND'][_type]; |
| 30 } | 32 } |
| 31 | 33 |
| 32 /** | 34 /** |
| 33 * A FileStat object represents the result of calling the POSIX stat() function | 35 * A FileStat object represents the result of calling the POSIX stat() function |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 /** | 71 /** |
| 70 * The mode of the file system object. Permissions are encoded in the lower | 72 * The mode of the file system object. Permissions are encoded in the lower |
| 71 * 16 bits of this number, and can be decoded using the [modeString] getter. | 73 * 16 bits of this number, and can be decoded using the [modeString] getter. |
| 72 */ | 74 */ |
| 73 final int mode; | 75 final int mode; |
| 74 /** | 76 /** |
| 75 * The size of the file system object. | 77 * The size of the file system object. |
| 76 */ | 78 */ |
| 77 final int size; | 79 final int size; |
| 78 | 80 |
| 79 FileStat._internal(this.changed, | 81 FileStat._internal(this.changed, this.modified, this.accessed, this.type, |
| 80 this.modified, | 82 this.mode, this.size); |
| 81 this.accessed, | |
| 82 this.type, | |
| 83 this.mode, | |
| 84 this.size); | |
| 85 | 83 |
| 86 const FileStat._internalNotFound() : | 84 const FileStat._internalNotFound() |
| 87 changed = null, modified = null, accessed = null, | 85 : changed = null, |
| 88 type = FileSystemEntityType.NOT_FOUND, mode = 0, size = -1; | 86 modified = null, |
| 87 accessed = null, |
| 88 type = FileSystemEntityType.NOT_FOUND, |
| 89 mode = 0, |
| 90 size = -1; |
| 89 | 91 |
| 90 external static _statSync(String path); | 92 external static _statSync(String path); |
| 91 | 93 |
| 92 | |
| 93 /** | 94 /** |
| 94 * Calls the operating system's stat() function on [path]. | 95 * Calls the operating system's stat() function on [path]. |
| 95 * Returns a [FileStat] object containing the data returned by stat(). | 96 * Returns a [FileStat] object containing the data returned by stat(). |
| 96 * If the call fails, returns a [FileStat] object with .type set to | 97 * If the call fails, returns a [FileStat] object with .type set to |
| 97 * FileSystemEntityType.NOT_FOUND and the other fields invalid. | 98 * FileSystemEntityType.NOT_FOUND and the other fields invalid. |
| 98 */ | 99 */ |
| 99 static FileStat statSync(String path) { | 100 static FileStat statSync(String path) { |
| 100 // Trailing path is not supported on Windows. | 101 // Trailing path is not supported on Windows. |
| 101 if (Platform.isWindows) { | 102 if (Platform.isWindows) { |
| 102 path = FileSystemEntity._trimTrailingPathSeparators(path); | 103 path = FileSystemEntity._trimTrailingPathSeparators(path); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 * by prepending "(suid)", "(guid)", and/or "(sticky)" to the mode string. | 157 * by prepending "(suid)", "(guid)", and/or "(sticky)" to the mode string. |
| 157 */ | 158 */ |
| 158 String modeString() { | 159 String modeString() { |
| 159 var permissions = mode & 0xFFF; | 160 var permissions = mode & 0xFFF; |
| 160 var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx']; | 161 var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx']; |
| 161 var result = []; | 162 var result = []; |
| 162 if ((permissions & 0x800) != 0) result.add("(suid) "); | 163 if ((permissions & 0x800) != 0) result.add("(suid) "); |
| 163 if ((permissions & 0x400) != 0) result.add("(guid) "); | 164 if ((permissions & 0x400) != 0) result.add("(guid) "); |
| 164 if ((permissions & 0x200) != 0) result.add("(sticky) "); | 165 if ((permissions & 0x200) != 0) result.add("(sticky) "); |
| 165 result | 166 result |
| 166 ..add(codes[(permissions >> 6) & 0x7]) | 167 ..add(codes[(permissions >> 6) & 0x7]) |
| 167 ..add(codes[(permissions >> 3) & 0x7]) | 168 ..add(codes[(permissions >> 3) & 0x7]) |
| 168 ..add(codes[permissions & 0x7]); | 169 ..add(codes[permissions & 0x7]); |
| 169 return result.join(); | 170 return result.join(); |
| 170 } | 171 } |
| 171 } | 172 } |
| 172 | 173 |
| 173 | |
| 174 /** | 174 /** |
| 175 * The common super class for [File], [Directory], and [Link] objects. | 175 * The common super class for [File], [Directory], and [Link] objects. |
| 176 * | 176 * |
| 177 * [FileSystemEntity] objects are returned from directory listing | 177 * [FileSystemEntity] objects are returned from directory listing |
| 178 * operations. To determine if a FileSystemEntity is a [File], a | 178 * operations. To determine if a FileSystemEntity is a [File], a |
| 179 * [Directory], or a [Link] perform a type check: | 179 * [Directory], or a [Link] perform a type check: |
| 180 * | 180 * |
| 181 * if (entity is File) (entity as File).readAsStringSync(); | 181 * if (entity is File) (entity as File).readAsStringSync(); |
| 182 * | 182 * |
| 183 * You can also use the [type] or [typeSync] methods to determine | 183 * You can also use the [type] or [typeSync] methods to determine |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 * Renames this file system entity. Returns a `Future<FileSystemEntity>` | 257 * Renames this file system entity. Returns a `Future<FileSystemEntity>` |
| 258 * that completes with a [FileSystemEntity] instance for the renamed | 258 * that completes with a [FileSystemEntity] instance for the renamed |
| 259 * file system entity. | 259 * file system entity. |
| 260 * | 260 * |
| 261 * If [newPath] identifies an existing entity of the same type, that entity | 261 * If [newPath] identifies an existing entity of the same type, that entity |
| 262 * is replaced. If [newPath] identifies an existing entity of a different | 262 * is replaced. If [newPath] identifies an existing entity of a different |
| 263 * type, the operation fails and the future completes with an exception. | 263 * type, the operation fails and the future completes with an exception. |
| 264 */ | 264 */ |
| 265 Future<FileSystemEntity> rename(String newPath); | 265 Future<FileSystemEntity> rename(String newPath); |
| 266 | 266 |
| 267 /** | 267 /** |
| 268 * Synchronously renames this file system entity. Returns a [FileSystemEntity] | 268 * Synchronously renames this file system entity. Returns a [FileSystemEntity] |
| 269 * instance for the renamed entity. | 269 * instance for the renamed entity. |
| 270 * | 270 * |
| 271 * If [newPath] identifies an existing entity of the same type, that entity | 271 * If [newPath] identifies an existing entity of the same type, that entity |
| 272 * is replaced. If [newPath] identifies an existing entity of a different | 272 * is replaced. If [newPath] identifies an existing entity of a different |
| 273 * type, the operation fails and an exception is thrown. | 273 * type, the operation fails and an exception is thrown. |
| 274 */ | 274 */ |
| 275 FileSystemEntity renameSync(String newPath); | 275 FileSystemEntity renameSync(String newPath); |
| 276 | 276 |
| 277 /** | 277 /** |
| (...skipping 18 matching lines...) Expand all Loading... |
| 296 * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath(); | 296 * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath(); |
| 297 * if (path == '') path = '.'; | 297 * if (path == '') path = '.'; |
| 298 * new File(path).resolveSymbolicLinks().then((resolved) { | 298 * new File(path).resolveSymbolicLinks().then((resolved) { |
| 299 * print(resolved); | 299 * print(resolved); |
| 300 * }); | 300 * }); |
| 301 * | 301 * |
| 302 * since `Uri.resolve` removes `..` segments. This will result in the Windows | 302 * since `Uri.resolve` removes `..` segments. This will result in the Windows |
| 303 * behavior. | 303 * behavior. |
| 304 */ | 304 */ |
| 305 Future<String> resolveSymbolicLinks() { | 305 Future<String> resolveSymbolicLinks() { |
| 306 return _IOService._dispatch(_FILE_RESOLVE_SYMBOLIC_LINKS, [path]) | 306 return _IOService |
| 307 .then((response) { | 307 ._dispatch(_FILE_RESOLVE_SYMBOLIC_LINKS, [path]).then((response) { |
| 308 if (_isErrorResponse(response)) { | 308 if (_isErrorResponse(response)) { |
| 309 throw _exceptionFromResponse(response, | 309 throw _exceptionFromResponse( |
| 310 "Cannot resolve symbolic links", | 310 response, "Cannot resolve symbolic links", path); |
| 311 path); | 311 } |
| 312 } | 312 return response; |
| 313 return response; | 313 }); |
| 314 }); | |
| 315 } | 314 } |
| 316 | 315 |
| 317 /** | 316 /** |
| 318 * Resolves the path of a file system object relative to the | 317 * Resolves the path of a file system object relative to the |
| 319 * current working directory, resolving all symbolic links on | 318 * current working directory, resolving all symbolic links on |
| 320 * the path and resolving all `..` and `.` path segments. | 319 * the path and resolving all `..` and `.` path segments. |
| 321 * | 320 * |
| 322 * [resolveSymbolicLinksSync] uses the operating system's native | 321 * [resolveSymbolicLinksSync] uses the operating system's native |
| 323 * file system API to resolve the path, using the `realpath` function | 322 * file system API to resolve the path, using the `realpath` function |
| 324 * on linux and OS X, and the `GetFinalPathNameByHandle` function on | 323 * on linux and OS X, and the `GetFinalPathNameByHandle` function on |
| (...skipping 15 matching lines...) Expand all Loading... |
| 340 * | 339 * |
| 341 * since `Uri.resolve` removes `..` segments. This will result in the Windows | 340 * since `Uri.resolve` removes `..` segments. This will result in the Windows |
| 342 * behavior. | 341 * behavior. |
| 343 */ | 342 */ |
| 344 String resolveSymbolicLinksSync() { | 343 String resolveSymbolicLinksSync() { |
| 345 var result = _resolveSymbolicLinks(path); | 344 var result = _resolveSymbolicLinks(path); |
| 346 _throwIfError(result, "Cannot resolve symbolic links", path); | 345 _throwIfError(result, "Cannot resolve symbolic links", path); |
| 347 return result; | 346 return result; |
| 348 } | 347 } |
| 349 | 348 |
| 350 | |
| 351 /** | 349 /** |
| 352 * Calls the operating system's stat() function on the [path] of this | 350 * Calls the operating system's stat() function on the [path] of this |
| 353 * [FileSystemEntity]. Identical to [:FileStat.stat(this.path):]. | 351 * [FileSystemEntity]. Identical to [:FileStat.stat(this.path):]. |
| 354 * | 352 * |
| 355 * Returns a [:Future<FileStat>:] object containing the data returned by | 353 * Returns a [:Future<FileStat>:] object containing the data returned by |
| 356 * stat(). | 354 * stat(). |
| 357 * | 355 * |
| 358 * If the call fails, completes the future with a [FileStat] object | 356 * If the call fails, completes the future with a [FileStat] object |
| 359 * with .type set to | 357 * with .type set to |
| 360 * FileSystemEntityType.NOT_FOUND and the other fields invalid. | 358 * FileSystemEntityType.NOT_FOUND and the other fields invalid. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 384 * | 382 * |
| 385 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type | 383 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type |
| 386 * of the [FileSystemEntity] doesn't match the content of the file system. | 384 * of the [FileSystemEntity] doesn't match the content of the file system. |
| 387 * This behavior allows [delete] to be used to unconditionally delete any file | 385 * This behavior allows [delete] to be used to unconditionally delete any file |
| 388 * system object. | 386 * system object. |
| 389 * | 387 * |
| 390 * Returns a [:Future<FileSystemEntity>:] that completes with this | 388 * Returns a [:Future<FileSystemEntity>:] that completes with this |
| 391 * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity] | 389 * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity] |
| 392 * cannot be deleted, the future completes with an exception. | 390 * cannot be deleted, the future completes with an exception. |
| 393 */ | 391 */ |
| 394 Future<FileSystemEntity> delete({bool recursive: false}) | 392 Future<FileSystemEntity> delete({bool recursive: false}) => |
| 395 => _delete(recursive: recursive); | 393 _delete(recursive: recursive); |
| 396 | 394 |
| 397 /** | 395 /** |
| 398 * Synchronously deletes this [FileSystemEntity]. | 396 * Synchronously deletes this [FileSystemEntity]. |
| 399 * | 397 * |
| 400 * If the [FileSystemEntity] is a directory, and if [recursive] is false, | 398 * If the [FileSystemEntity] is a directory, and if [recursive] is false, |
| 401 * the directory must be empty. Otherwise, if [recursive] is true, the | 399 * the directory must be empty. Otherwise, if [recursive] is true, the |
| 402 * directory and all sub-directories and files in the directories are | 400 * directory and all sub-directories and files in the directories are |
| 403 * deleted. Links are not followed when deleting recursively. Only the link | 401 * deleted. Links are not followed when deleting recursively. Only the link |
| 404 * is deleted, not its target. | 402 * is deleted, not its target. |
| 405 * | 403 * |
| 406 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type | 404 * If [recursive] is true, the [FileSystemEntity] is deleted even if the type |
| 407 * of the [FileSystemEntity] doesn't match the content of the file system. | 405 * of the [FileSystemEntity] doesn't match the content of the file system. |
| 408 * This behavior allows [deleteSync] to be used to unconditionally delete any | 406 * This behavior allows [deleteSync] to be used to unconditionally delete any |
| 409 * file system object. | 407 * file system object. |
| 410 * | 408 * |
| 411 * Throws an exception if the [FileSystemEntity] cannot be deleted. | 409 * Throws an exception if the [FileSystemEntity] cannot be deleted. |
| 412 */ | 410 */ |
| 413 void deleteSync({bool recursive: false}) | 411 void deleteSync({bool recursive: false}) => _deleteSync(recursive: recursive); |
| 414 => _deleteSync(recursive: recursive); | |
| 415 | |
| 416 | 412 |
| 417 /** | 413 /** |
| 418 * Start watching the [FileSystemEntity] for changes. | 414 * Start watching the [FileSystemEntity] for changes. |
| 419 * | 415 * |
| 420 * The implementation uses platform-dependent event-based APIs for receiving | 416 * The implementation uses platform-dependent event-based APIs for receiving |
| 421 * file-system notifications, thus behavior depends on the platform. | 417 * file-system notifications, thus behavior depends on the platform. |
| 422 * | 418 * |
| 423 * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only | 419 * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only |
| 424 * supports watching directories. Recursive watching is supported. | 420 * supports watching directories. Recursive watching is supported. |
| 425 * * `Linux`: Uses `inotify`. The implementation supports watching both | 421 * * `Linux`: Uses `inotify`. The implementation supports watching both |
| (...skipping 12 matching lines...) Expand all Loading... |
| 438 * * The [Stream] is canceled, e.g. by calling `cancel` on the | 434 * * The [Stream] is canceled, e.g. by calling `cancel` on the |
| 439 * [StreamSubscription]. | 435 * [StreamSubscription]. |
| 440 * * The [FileSystemEntity] being watches, is deleted. | 436 * * The [FileSystemEntity] being watches, is deleted. |
| 441 * | 437 * |
| 442 * Use `events` to specify what events to listen for. The constants in | 438 * Use `events` to specify what events to listen for. The constants in |
| 443 * [FileSystemEvent] can be or'ed together to mix events. Default is | 439 * [FileSystemEvent] can be or'ed together to mix events. Default is |
| 444 * [FileSystemEvent.ALL]. | 440 * [FileSystemEvent.ALL]. |
| 445 * | 441 * |
| 446 * A move event may be reported as seperate delete and create events. | 442 * A move event may be reported as seperate delete and create events. |
| 447 */ | 443 */ |
| 448 Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL, | 444 Stream<FileSystemEvent> watch( |
| 449 bool recursive: false}) | 445 {int events: FileSystemEvent.ALL, bool recursive: false}) => |
| 450 => _FileSystemWatcher._watch(_trimTrailingPathSeparators(path), | 446 _FileSystemWatcher._watch( |
| 451 events, | 447 _trimTrailingPathSeparators(path), events, recursive); |
| 452 recursive); | |
| 453 | 448 |
| 454 Future<FileSystemEntity> _delete({bool recursive: false}); | 449 Future<FileSystemEntity> _delete({bool recursive: false}); |
| 455 void _deleteSync({bool recursive: false}); | 450 void _deleteSync({bool recursive: false}); |
| 456 | 451 |
| 457 /** | 452 /** |
| 458 * Checks whether two paths refer to the same object in the | 453 * Checks whether two paths refer to the same object in the |
| 459 * file system. Returns a [:Future<bool>:] that completes with the result. | 454 * file system. Returns a [:Future<bool>:] that completes with the result. |
| 460 * | 455 * |
| 461 * Comparing a link to its target returns false, as does comparing two links | 456 * Comparing a link to its target returns false, as does comparing two links |
| 462 * that point to the same target. To check the target of a link, use | 457 * that point to the same target. To check the target of a link, use |
| 463 * Link.target explicitly to fetch it. Directory links appearing | 458 * Link.target explicitly to fetch it. Directory links appearing |
| 464 * inside a path are followed, though, to find the file system object. | 459 * inside a path are followed, though, to find the file system object. |
| 465 * | 460 * |
| 466 * Completes the returned Future with an error if one of the paths points | 461 * Completes the returned Future with an error if one of the paths points |
| 467 * to an object that does not exist. | 462 * to an object that does not exist. |
| 468 */ | 463 */ |
| 469 static Future<bool> identical(String path1, String path2) { | 464 static Future<bool> identical(String path1, String path2) { |
| 470 return _IOService._dispatch(_FILE_IDENTICAL, [path1, path2]).then((response)
{ | 465 return _IOService |
| 466 ._dispatch(_FILE_IDENTICAL, [path1, path2]).then((response) { |
| 471 if (_isErrorResponse(response)) { | 467 if (_isErrorResponse(response)) { |
| 472 throw _exceptionFromResponse(response, | 468 throw _exceptionFromResponse(response, |
| 473 "Error in FileSystemEntity.identical($path1, $path2)", ""); | 469 "Error in FileSystemEntity.identical($path1, $path2)", ""); |
| 474 } | 470 } |
| 475 return response; | 471 return response; |
| 476 }); | 472 }); |
| 477 } | 473 } |
| 478 | 474 |
| 479 static final RegExp _absoluteWindowsPathPattern = | 475 static final RegExp _absoluteWindowsPathPattern = |
| 480 new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])'); | 476 new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])'); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 508 if (isAbsolute) return path; | 504 if (isAbsolute) return path; |
| 509 String current = Directory.current.path; | 505 String current = Directory.current.path; |
| 510 if (current.endsWith('/') || | 506 if (current.endsWith('/') || |
| 511 (Platform.isWindows && current.endsWith('\\'))) { | 507 (Platform.isWindows && current.endsWith('\\'))) { |
| 512 return '$current$path'; | 508 return '$current$path'; |
| 513 } else { | 509 } else { |
| 514 return '$current${Platform.pathSeparator}$path'; | 510 return '$current${Platform.pathSeparator}$path'; |
| 515 } | 511 } |
| 516 } | 512 } |
| 517 | 513 |
| 518 | |
| 519 /** | 514 /** |
| 520 * Synchronously checks whether two paths refer to the same object in the | 515 * Synchronously checks whether two paths refer to the same object in the |
| 521 * file system. | 516 * file system. |
| 522 * | 517 * |
| 523 * Comparing a link to its target returns false, as does comparing two links | 518 * Comparing a link to its target returns false, as does comparing two links |
| 524 * that point to the same target. To check the target of a link, use | 519 * that point to the same target. To check the target of a link, use |
| 525 * Link.target explicitly to fetch it. Directory links appearing | 520 * Link.target explicitly to fetch it. Directory links appearing |
| 526 * inside a path are followed, though, to find the file system object. | 521 * inside a path are followed, though, to find the file system object. |
| 527 * | 522 * |
| 528 * Throws an error if one of the paths points to an object that does not | 523 * Throws an error if one of the paths points to an object that does not |
| (...skipping 18 matching lines...) Expand all Loading... |
| 547 * | 542 * |
| 548 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, | 543 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, |
| 549 * LINK, and NOT_FOUND. [type] will return LINK only if the optional | 544 * LINK, and NOT_FOUND. [type] will return LINK only if the optional |
| 550 * named argument [followLinks] is false, and [path] points to a link. | 545 * named argument [followLinks] is false, and [path] points to a link. |
| 551 * If the path does not point to a file system object, or any other error | 546 * If the path does not point to a file system object, or any other error |
| 552 * occurs in looking up the path, NOT_FOUND is returned. The only | 547 * occurs in looking up the path, NOT_FOUND is returned. The only |
| 553 * error or exception that may be put on the returned future is ArgumentError, | 548 * error or exception that may be put on the returned future is ArgumentError, |
| 554 * caused by passing the wrong type of arguments to the function. | 549 * caused by passing the wrong type of arguments to the function. |
| 555 */ | 550 */ |
| 556 static Future<FileSystemEntityType> type(String path, | 551 static Future<FileSystemEntityType> type(String path, |
| 557 {bool followLinks: true}) | 552 {bool followLinks: true}) => |
| 558 => _getTypeAsync(path, followLinks).then(FileSystemEntityType._lookup); | 553 _getTypeAsync(path, followLinks).then(FileSystemEntityType._lookup); |
| 559 | 554 |
| 560 /** | 555 /** |
| 561 * Synchronously finds the type of file system object that a path points to. | 556 * Synchronously finds the type of file system object that a path points to. |
| 562 * Returns a [FileSystemEntityType]. | 557 * Returns a [FileSystemEntityType]. |
| 563 * | 558 * |
| 564 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, | 559 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY, |
| 565 * LINK, and NOT_FOUND. [type] will return LINK only if the optional | 560 * LINK, and NOT_FOUND. [type] will return LINK only if the optional |
| 566 * named argument [followLinks] is false, and [path] points to a link. | 561 * named argument [followLinks] is false, and [path] points to a link. |
| 567 * If the path does not point to a file system object, or any other error | 562 * If the path does not point to a file system object, or any other error |
| 568 * occurs in looking up the path, NOT_FOUND is returned. The only | 563 * occurs in looking up the path, NOT_FOUND is returned. The only |
| 569 * error or exception that may be thrown is ArgumentError, | 564 * error or exception that may be thrown is ArgumentError, |
| 570 * caused by passing the wrong type of arguments to the function. | 565 * caused by passing the wrong type of arguments to the function. |
| 571 */ | 566 */ |
| 572 static FileSystemEntityType typeSync(String path, {bool followLinks: true}) | 567 static FileSystemEntityType typeSync(String path, {bool followLinks: true}) => |
| 573 => FileSystemEntityType._lookup(_getTypeSync(path, followLinks)); | 568 FileSystemEntityType._lookup(_getTypeSync(path, followLinks)); |
| 574 | 569 |
| 575 /** | 570 /** |
| 576 * Checks if type(path, followLinks: false) returns | 571 * Checks if type(path, followLinks: false) returns |
| 577 * FileSystemEntityType.LINK. | 572 * FileSystemEntityType.LINK. |
| 578 */ | 573 */ |
| 579 static Future<bool> isLink(String path) => _getTypeAsync(path, false) | 574 static Future<bool> isLink(String path) => _getTypeAsync(path, false) |
| 580 .then((type) => (type == FileSystemEntityType.LINK._type)); | 575 .then((type) => (type == FileSystemEntityType.LINK._type)); |
| 581 | 576 |
| 582 /** | 577 /** |
| 583 * Checks if type(path) returns FileSystemEntityType.FILE. | 578 * Checks if type(path) returns FileSystemEntityType.FILE. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 610 * FileSystemEntityType.DIRECTORY. | 605 * FileSystemEntityType.DIRECTORY. |
| 611 */ | 606 */ |
| 612 static bool isDirectorySync(String path) => | 607 static bool isDirectorySync(String path) => |
| 613 (_getTypeSync(path, true) == FileSystemEntityType.DIRECTORY._type); | 608 (_getTypeSync(path, true) == FileSystemEntityType.DIRECTORY._type); |
| 614 | 609 |
| 615 external static _getType(String path, bool followLinks); | 610 external static _getType(String path, bool followLinks); |
| 616 external static _identical(String path1, String path2); | 611 external static _identical(String path1, String path2); |
| 617 external static _resolveSymbolicLinks(String path); | 612 external static _resolveSymbolicLinks(String path); |
| 618 | 613 |
| 619 // Finds the next-to-last component when dividing at path separators. | 614 // Finds the next-to-last component when dividing at path separators. |
| 620 static final RegExp _parentRegExp = Platform.isWindows ? | 615 static final RegExp _parentRegExp = Platform.isWindows |
| 621 new RegExp(r'[^/\\][/\\]+[^/\\]') : | 616 ? new RegExp(r'[^/\\][/\\]+[^/\\]') |
| 622 new RegExp(r'[^/]/+[^/]'); | 617 : new RegExp(r'[^/]/+[^/]'); |
| 623 | 618 |
| 624 /** | 619 /** |
| 625 * Removes the final path component of a path, using the platform's | 620 * Removes the final path component of a path, using the platform's |
| 626 * path separator to split the path. Will not remove the root component | 621 * path separator to split the path. Will not remove the root component |
| 627 * of a Windows path, like "C:\\" or "\\\\server_name\\". | 622 * of a Windows path, like "C:\\" or "\\\\server_name\\". |
| 628 * Ignores trailing path separators, and leaves no trailing path separators. | 623 * Ignores trailing path separators, and leaves no trailing path separators. |
| 629 */ | 624 */ |
| 630 static String parentOf(String path) { | 625 static String parentOf(String path) { |
| 631 int rootEnd = -1; | 626 int rootEnd = -1; |
| 632 if (Platform.isWindows) { | 627 if (Platform.isWindows) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 657 */ | 652 */ |
| 658 Directory get parent => new Directory(parentOf(path)); | 653 Directory get parent => new Directory(parentOf(path)); |
| 659 | 654 |
| 660 static int _getTypeSync(String path, bool followLinks) { | 655 static int _getTypeSync(String path, bool followLinks) { |
| 661 var result = _getType(path, followLinks); | 656 var result = _getType(path, followLinks); |
| 662 _throwIfError(result, 'Error getting type of FileSystemEntity'); | 657 _throwIfError(result, 'Error getting type of FileSystemEntity'); |
| 663 return result; | 658 return result; |
| 664 } | 659 } |
| 665 | 660 |
| 666 static Future<int> _getTypeAsync(String path, bool followLinks) { | 661 static Future<int> _getTypeAsync(String path, bool followLinks) { |
| 667 return _IOService._dispatch(_FILE_TYPE, [path, followLinks]) | 662 return _IOService |
| 668 .then((response) { | 663 ._dispatch(_FILE_TYPE, [path, followLinks]).then((response) { |
| 669 if (_isErrorResponse(response)) { | 664 if (_isErrorResponse(response)) { |
| 670 throw _exceptionFromResponse(response, "Error getting type", path); | 665 throw _exceptionFromResponse(response, "Error getting type", path); |
| 671 } | 666 } |
| 672 return response; | 667 return response; |
| 673 }); | 668 }); |
| 674 } | 669 } |
| 675 | 670 |
| 676 static _throwIfError(Object result, String msg, [String path]) { | 671 static _throwIfError(Object result, String msg, [String path]) { |
| 677 if (result is OSError) { | 672 if (result is OSError) { |
| 678 throw new FileSystemException(msg, path, result); | 673 throw new FileSystemException(msg, path, result); |
| 679 } else if (result is ArgumentError) { | 674 } else if (result is ArgumentError) { |
| 680 throw result; | 675 throw result; |
| 681 } | 676 } |
| 682 } | 677 } |
| 683 | 678 |
| 684 static String _trimTrailingPathSeparators(String path) { | 679 static String _trimTrailingPathSeparators(String path) { |
| 685 // Don't handle argument errors here. | 680 // Don't handle argument errors here. |
| 686 if (path is! String) return path; | 681 if (path is! String) return path; |
| 687 if (Platform.isWindows) { | 682 if (Platform.isWindows) { |
| 688 while (path.length > 1 && | 683 while (path.length > 1 && |
| 689 (path.endsWith(Platform.pathSeparator) || | 684 (path.endsWith(Platform.pathSeparator) || path.endsWith('/'))) { |
| 690 path.endsWith('/'))) { | |
| 691 path = path.substring(0, path.length - 1); | 685 path = path.substring(0, path.length - 1); |
| 692 } | 686 } |
| 693 } else { | 687 } else { |
| 694 while (path.length > 1 && path.endsWith(Platform.pathSeparator)) { | 688 while (path.length > 1 && path.endsWith(Platform.pathSeparator)) { |
| 695 path = path.substring(0, path.length - 1); | 689 path = path.substring(0, path.length - 1); |
| 696 } | 690 } |
| 697 } | 691 } |
| 698 return path; | 692 return path; |
| 699 } | 693 } |
| 700 | 694 |
| 701 static String _ensureTrailingPathSeparators(String path) { | 695 static String _ensureTrailingPathSeparators(String path) { |
| 702 // Don't handle argument errors here. | 696 // Don't handle argument errors here. |
| 703 if (path is! String) return path; | 697 if (path is! String) return path; |
| 704 if (path.isEmpty) path = '.'; | 698 if (path.isEmpty) path = '.'; |
| 705 if (Platform.isWindows) { | 699 if (Platform.isWindows) { |
| 706 while (!path.endsWith(Platform.pathSeparator) && !path.endsWith('/')) { | 700 while (!path.endsWith(Platform.pathSeparator) && !path.endsWith('/')) { |
| 707 path = "$path${Platform.pathSeparator}"; | 701 path = "$path${Platform.pathSeparator}"; |
| 708 } | 702 } |
| 709 } else { | 703 } else { |
| 710 while (!path.endsWith(Platform.pathSeparator)) { | 704 while (!path.endsWith(Platform.pathSeparator)) { |
| 711 path = "$path${Platform.pathSeparator}"; | 705 path = "$path${Platform.pathSeparator}"; |
| 712 } | 706 } |
| 713 } | 707 } |
| 714 return path; | 708 return path; |
| 715 } | 709 } |
| 716 } | 710 } |
| 717 | 711 |
| 718 | |
| 719 /** | 712 /** |
| 720 * Base event class emitted by [FileSystemEntity.watch]. | 713 * Base event class emitted by [FileSystemEntity.watch]. |
| 721 */ | 714 */ |
| 722 class FileSystemEvent { | 715 class FileSystemEvent { |
| 723 /** | 716 /** |
| 724 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s. | 717 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s. |
| 725 */ | 718 */ |
| 726 static const int CREATE = 1 << 0; | 719 static const int CREATE = 1 << 0; |
| 727 | 720 |
| 728 /** | 721 /** |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 final String path; | 755 final String path; |
| 763 | 756 |
| 764 /** | 757 /** |
| 765 * Is `true` if the event target was a directory. | 758 * Is `true` if the event target was a directory. |
| 766 */ | 759 */ |
| 767 final bool isDirectory; | 760 final bool isDirectory; |
| 768 | 761 |
| 769 FileSystemEvent._(this.type, this.path, this.isDirectory); | 762 FileSystemEvent._(this.type, this.path, this.isDirectory); |
| 770 } | 763 } |
| 771 | 764 |
| 772 | |
| 773 /** | 765 /** |
| 774 * File system event for newly created file system objects. | 766 * File system event for newly created file system objects. |
| 775 */ | 767 */ |
| 776 class FileSystemCreateEvent extends FileSystemEvent { | 768 class FileSystemCreateEvent extends FileSystemEvent { |
| 777 FileSystemCreateEvent._(path, isDirectory) | 769 FileSystemCreateEvent._(path, isDirectory) |
| 778 : super._(FileSystemEvent.CREATE, path, isDirectory); | 770 : super._(FileSystemEvent.CREATE, path, isDirectory); |
| 779 | 771 |
| 780 String toString() => "FileSystemCreateEvent('$path')"; | 772 String toString() => "FileSystemCreateEvent('$path')"; |
| 781 } | 773 } |
| 782 | 774 |
| 783 | |
| 784 /** | 775 /** |
| 785 * File system event for modifications of file system objects. | 776 * File system event for modifications of file system objects. |
| 786 */ | 777 */ |
| 787 class FileSystemModifyEvent extends FileSystemEvent { | 778 class FileSystemModifyEvent extends FileSystemEvent { |
| 788 /** | 779 /** |
| 789 * If the content was changed and not only the attributes, [contentChanged] | 780 * If the content was changed and not only the attributes, [contentChanged] |
| 790 * is `true`. | 781 * is `true`. |
| 791 */ | 782 */ |
| 792 final bool contentChanged; | 783 final bool contentChanged; |
| 793 | 784 |
| 794 FileSystemModifyEvent._(path, isDirectory, this.contentChanged) | 785 FileSystemModifyEvent._(path, isDirectory, this.contentChanged) |
| 795 : super._(FileSystemEvent.MODIFY, path, isDirectory); | 786 : super._(FileSystemEvent.MODIFY, path, isDirectory); |
| 796 | 787 |
| 797 String toString() => | 788 String toString() => |
| 798 "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; | 789 "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; |
| 799 } | 790 } |
| 800 | 791 |
| 801 | |
| 802 /** | 792 /** |
| 803 * File system event for deletion of file system objects. | 793 * File system event for deletion of file system objects. |
| 804 */ | 794 */ |
| 805 class FileSystemDeleteEvent extends FileSystemEvent { | 795 class FileSystemDeleteEvent extends FileSystemEvent { |
| 806 FileSystemDeleteEvent._(path, isDirectory) | 796 FileSystemDeleteEvent._(path, isDirectory) |
| 807 : super._(FileSystemEvent.DELETE, path, isDirectory); | 797 : super._(FileSystemEvent.DELETE, path, isDirectory); |
| 808 | 798 |
| 809 String toString() => "FileSystemDeleteEvent('$path')"; | 799 String toString() => "FileSystemDeleteEvent('$path')"; |
| 810 } | 800 } |
| 811 | 801 |
| 812 | |
| 813 /** | 802 /** |
| 814 * File system event for moving of file system objects. | 803 * File system event for moving of file system objects. |
| 815 */ | 804 */ |
| 816 class FileSystemMoveEvent extends FileSystemEvent { | 805 class FileSystemMoveEvent extends FileSystemEvent { |
| 817 /** | 806 /** |
| 818 * If the underlying implementation is able to identify the destination of | 807 * If the underlying implementation is able to identify the destination of |
| 819 * the moved file, [destination] will be set. Otherwise, it will be `null`. | 808 * the moved file, [destination] will be set. Otherwise, it will be `null`. |
| 820 */ | 809 */ |
| 821 final String destination; | 810 final String destination; |
| 822 | 811 |
| 823 FileSystemMoveEvent._(path, isDirectory, this.destination) | 812 FileSystemMoveEvent._(path, isDirectory, this.destination) |
| 824 : super._(FileSystemEvent.MOVE, path, isDirectory); | 813 : super._(FileSystemEvent.MOVE, path, isDirectory); |
| 825 | 814 |
| 826 String toString() { | 815 String toString() { |
| 827 var buffer = new StringBuffer(); | 816 var buffer = new StringBuffer(); |
| 828 buffer.write("FileSystemMoveEvent('$path'"); | 817 buffer.write("FileSystemMoveEvent('$path'"); |
| 829 if (destination != null) buffer.write(", '$destination'"); | 818 if (destination != null) buffer.write(", '$destination'"); |
| 830 buffer.write(')'); | 819 buffer.write(')'); |
| 831 return buffer.toString(); | 820 return buffer.toString(); |
| 832 } | 821 } |
| 833 } | 822 } |
| 834 | 823 |
| 835 | |
| 836 class _FileSystemWatcher { | 824 class _FileSystemWatcher { |
| 837 external static Stream<FileSystemEvent> _watch( | 825 external static Stream<FileSystemEvent> _watch( |
| 838 String path, int events, bool recursive); | 826 String path, int events, bool recursive); |
| 839 external static bool get isSupported; | 827 external static bool get isSupported; |
| 840 } | 828 } |
| OLD | NEW |