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 |