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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/io/file_system_entity.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.io;
6
7 /**
8 * The type of an entity on the file system, such as a file, directory, or link.
9 *
10 * These constants are used by the [FileSystemEntity] class
11 * to indicate the object's type.
12 *
13 */
14
15 class FileSystemEntityType {
16 static const FILE = const FileSystemEntityType._internal(0);
17 static const DIRECTORY = const FileSystemEntityType._internal(1);
18 static const LINK = const FileSystemEntityType._internal(2);
19 static const NOT_FOUND = const FileSystemEntityType._internal(3);
20 static const _typeList = const [FileSystemEntityType.FILE,
21 FileSystemEntityType.DIRECTORY,
22 FileSystemEntityType.LINK,
23 FileSystemEntityType.NOT_FOUND];
24 final int _type;
25
26 const FileSystemEntityType._internal(this._type);
27
28 static FileSystemEntityType _lookup(int type) => _typeList[type];
29 String toString() => const ['FILE', 'DIRECTORY', 'LINK', 'NOT_FOUND'][_type];
30 }
31
32 /**
33 * A FileStat object represents the result of calling the POSIX stat() function
34 * on a file system object. It is an immutable object, representing the
35 * snapshotted values returned by the stat() call.
36 */
37 class FileStat {
38 // These must agree with enum FileStat in file.h.
39 static const _TYPE = 0;
40 static const _CHANGED_TIME = 1;
41 static const _MODIFIED_TIME = 2;
42 static const _ACCESSED_TIME = 3;
43 static const _MODE = 4;
44 static const _SIZE = 5;
45
46 static const _notFound = const FileStat._internalNotFound();
47
48 /**
49 * The time of the last change to the data or metadata of the file system
50 * object. On Windows platforms, this is instead the file creation time.
51 */
52 final DateTime changed;
53 /**
54 * The time of the last change to the data of the file system
55 * object.
56 */
57 final DateTime modified;
58 /**
59 * The time of the last access to the data of the file system
60 * object. On Windows platforms, this may have 1 day granularity, and be
61 * out of date by an hour.
62 */
63 final DateTime accessed;
64 /**
65 * The type of the object (file, directory, or link). If the call to
66 * stat() fails, the type of the returned object is NOT_FOUND.
67 */
68 final FileSystemEntityType type;
69 /**
70 * 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.
72 */
73 final int mode;
74 /**
75 * The size of the file system object.
76 */
77 final int size;
78
79 FileStat._internal(this.changed,
80 this.modified,
81 this.accessed,
82 this.type,
83 this.mode,
84 this.size);
85
86 const FileStat._internalNotFound() :
87 changed = null, modified = null, accessed = null,
88 type = FileSystemEntityType.NOT_FOUND, mode = 0, size = -1;
89
90 external static _statSync(String path);
91
92
93 /**
94 * Calls the operating system's stat() function on [path].
95 * Returns a [FileStat] object containing the data returned by stat().
96 * If the call fails, returns a [FileStat] object with .type set to
97 * FileSystemEntityType.NOT_FOUND and the other fields invalid.
98 */
99 static FileStat statSync(String path) {
100 // Trailing path is not supported on Windows.
101 if (Platform.isWindows) {
102 path = FileSystemEntity._trimTrailingPathSeparators(path);
103 }
104 var data = _statSync(path);
105 if (data is OSError) return FileStat._notFound;
106 return new FileStat._internal(
107 new DateTime.fromMillisecondsSinceEpoch(data[_CHANGED_TIME]),
108 new DateTime.fromMillisecondsSinceEpoch(data[_MODIFIED_TIME]),
109 new DateTime.fromMillisecondsSinceEpoch(data[_ACCESSED_TIME]),
110 FileSystemEntityType._lookup(data[_TYPE]),
111 data[_MODE],
112 data[_SIZE]);
113 }
114
115 /**
116 * Asynchronously calls the operating system's stat() function on [path].
117 * Returns a Future which completes with a [FileStat] object containing
118 * the data returned by stat().
119 * If the call fails, completes the future with a [FileStat] object with
120 * .type set to FileSystemEntityType.NOT_FOUND and the other fields invalid.
121 */
122 static Future<FileStat> stat(String path) {
123 // Trailing path is not supported on Windows.
124 if (Platform.isWindows) {
125 path = FileSystemEntity._trimTrailingPathSeparators(path);
126 }
127 return _IOService._dispatch(_FILE_STAT, [path]).then((response) {
128 if (_isErrorResponse(response)) {
129 return FileStat._notFound;
130 }
131 // Unwrap the real list from the "I'm not an error" wrapper.
132 List data = response[1];
133 return new FileStat._internal(
134 new DateTime.fromMillisecondsSinceEpoch(data[_CHANGED_TIME]),
135 new DateTime.fromMillisecondsSinceEpoch(data[_MODIFIED_TIME]),
136 new DateTime.fromMillisecondsSinceEpoch(data[_ACCESSED_TIME]),
137 FileSystemEntityType._lookup(data[_TYPE]),
138 data[_MODE],
139 data[_SIZE]);
140 });
141 }
142
143 String toString() => """
144 FileStat: type $type
145 changed $changed
146 modified $modified
147 accessed $accessed
148 mode ${modeString()}
149 size $size""";
150
151 /**
152 * Returns the mode value as a human-readable string, in the format
153 * "rwxrwxrwx", reflecting the user, group, and world permissions to
154 * read, write, and execute the file system object, with "-" replacing the
155 * letter for missing permissions. Extra permission bits may be represented
156 * by prepending "(suid)", "(guid)", and/or "(sticky)" to the mode string.
157 */
158 String modeString() {
159 var permissions = mode & 0xFFF;
160 var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
161 var result = [];
162 if ((permissions & 0x800) != 0) result.add("(suid) ");
163 if ((permissions & 0x400) != 0) result.add("(guid) ");
164 if ((permissions & 0x200) != 0) result.add("(sticky) ");
165 result
166 ..add(codes[(permissions >> 6) & 0x7])
167 ..add(codes[(permissions >> 3) & 0x7])
168 ..add(codes[permissions & 0x7]);
169 return result.join();
170 }
171 }
172
173
174 /**
175 * The common super class for [File], [Directory], and [Link] objects.
176 *
177 * [FileSystemEntity] objects are returned from directory listing
178 * operations. To determine if a FileSystemEntity is a [File], a
179 * [Directory], or a [Link] perform a type check:
180 *
181 * if (entity is File) (entity as File).readAsStringSync();
182 *
183 * You can also use the [type] or [typeSync] methods to determine
184 * the type of a file system object.
185 *
186 * Most methods in this class occur in synchronous and asynchronous pairs,
187 * for example, [exists] and [existsSync].
188 * Unless you have a specific reason for using the synchronous version
189 * of a method, prefer the asynchronous version to avoid blocking your program.
190 *
191 * Here's the exists method in action:
192 *
193 * entity.exists().then((isThere) {
194 * isThere ? print('exists') : print('non-existent');
195 * });
196 *
197 *
198 * ## Other resources
199 *
200 * * [Dart by
201 * Example](https://www.dartlang.org/dart-by-example/#files-directories-and-sy mlinks)
202 * provides additional task-oriented code samples that show how to use various
203 * API from the [Directory] class and the [File] class, both subclasses of
204 * FileSystemEntity.
205 *
206 * * [I/O for Command-Line
207 * Apps](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio--- io-for-command-line-apps),
208 * a section from _A Tour of the Dart Libraries_ covers files and directories.
209 *
210 * * [Write Command-Line Apps](https://www.dartlang.org/docs/tutorials/cmdline/) ,
211 * a tutorial about writing command-line apps, includes information about
212 * files and directories.
213 */
214 abstract class FileSystemEntity {
215 String get path;
216
217 /**
218 * Returns a [Uri] representing the file system entity's location.
219 *
220 * The returned URI's scheme is always "file" if the entity's [path] is
221 * absolute, otherwise the scheme will be empty.
222 */
223 Uri get uri => new Uri.file(path);
224
225 /**
226 * Checks whether the file system entity with this path exists. Returns
227 * a [:Future<bool>:] that completes with the result.
228 *
229 * Since FileSystemEntity is abstract, every FileSystemEntity object
230 * is actually an instance of one of the subclasses [File],
231 * [Directory], and [Link]. Calling [exists] on an instance of one
232 * of these subclasses checks whether the object exists in the file
233 * system object exists and is of the correct type (file, directory,
234 * or link). To check whether a path points to an object on the
235 * file system, regardless of the object's type, use the [type]
236 * static method.
237 *
238 */
239 Future<bool> exists();
240
241 /**
242 * Synchronously checks whether the file system entity with this path
243 * exists.
244 *
245 * Since FileSystemEntity is abstract, every FileSystemEntity object
246 * is actually an instance of one of the subclasses [File],
247 * [Directory], and [Link]. Calling [existsSync] on an instance of
248 * one of these subclasses checks whether the object exists in the
249 * file system object exists and is of the correct type (file,
250 * directory, or link). To check whether a path points to an object
251 * on the file system, regardless of the object's type, use the
252 * [typeSync] static method.
253 */
254 bool existsSync();
255
256 /**
257 * Renames this file system entity. Returns a `Future<FileSystemEntity>`
258 * that completes with a [FileSystemEntity] instance for the renamed
259 * file system entity.
260 *
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
263 * type, the operation fails and the future completes with an exception.
264 */
265 Future<FileSystemEntity> rename(String newPath);
266
267 /**
268 * Synchronously renames this file system entity. Returns a [FileSystemEntity]
269 * instance for the renamed entity.
270 *
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
273 * type, the operation fails and an exception is thrown.
274 */
275 FileSystemEntity renameSync(String newPath);
276
277 /**
278 * Resolves the path of a file system object relative to the
279 * current working directory, resolving all symbolic links on
280 * the path and resolving all `..` and `.` path segments.
281 *
282 * [resolveSymbolicLinks] uses the operating system's native
283 * file system API to resolve the path, using the `realpath` function
284 * on linux and OS X, and the `GetFinalPathNameByHandle` function on
285 * Windows. If the path does not point to an existing file system object,
286 * `resolveSymbolicLinks` throws a `FileSystemException`.
287 *
288 * On Windows the `..` segments are resolved _before_ resolving the symbolic
289 * link, and on other platforms the symbolic links are _resolved to their
290 * target_ before applying a `..` that follows.
291 *
292 * To ensure the same behavior on all platforms resolve `..` segments before
293 * calling `resolveSymbolicLinks`. One way of doing this is with the `Uri`
294 * class:
295 *
296 * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();
297 * if (path == '') path = '.';
298 * new File(path).resolveSymbolicLinks().then((resolved) {
299 * print(resolved);
300 * });
301 *
302 * since `Uri.resolve` removes `..` segments. This will result in the Windows
303 * behavior.
304 */
305 Future<String> resolveSymbolicLinks() {
306 return _IOService._dispatch(_FILE_RESOLVE_SYMBOLIC_LINKS, [path])
307 .then((response) {
308 if (_isErrorResponse(response)) {
309 throw _exceptionFromResponse(response,
310 "Cannot resolve symbolic links",
311 path);
312 }
313 return response;
314 });
315 }
316
317 /**
318 * Resolves the path of a file system object relative to the
319 * current working directory, resolving all symbolic links on
320 * the path and resolving all `..` and `.` path segments.
321 *
322 * [resolveSymbolicLinksSync] uses the operating system's native
323 * file system API to resolve the path, using the `realpath` function
324 * on linux and OS X, and the `GetFinalPathNameByHandle` function on
325 * Windows. If the path does not point to an existing file system object,
326 * `resolveSymbolicLinksSync` throws a `FileSystemException`.
327 *
328 * On Windows the `..` segments are resolved _before_ resolving the symbolic
329 * link, and on other platforms the symbolic links are _resolved to their
330 * target_ before applying a `..` that follows.
331 *
332 * To ensure the same behavior on all platforms resolve `..` segments before
333 * calling `resolveSymbolicLinksSync`. One way of doing this is with the `Uri`
334 * class:
335 *
336 * var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();
337 * if (path == '') path = '.';
338 * var resolved = new File(path).resolveSymbolicLinksSync();
339 * print(resolved);
340 *
341 * since `Uri.resolve` removes `..` segments. This will result in the Windows
342 * behavior.
343 */
344 String resolveSymbolicLinksSync() {
345 var result = _resolveSymbolicLinks(path);
346 _throwIfError(result, "Cannot resolve symbolic links", path);
347 return result;
348 }
349
350
351 /**
352 * Calls the operating system's stat() function on the [path] of this
353 * [FileSystemEntity]. Identical to [:FileStat.stat(this.path):].
354 *
355 * Returns a [:Future<FileStat>:] object containing the data returned by
356 * stat().
357 *
358 * If the call fails, completes the future with a [FileStat] object
359 * with .type set to
360 * FileSystemEntityType.NOT_FOUND and the other fields invalid.
361 */
362 Future<FileStat> stat();
363
364 /**
365 * Synchronously calls the operating system's stat() function on the
366 * [path] of this [FileSystemEntity].
367 * Identical to [:FileStat.statSync(this.path):].
368 *
369 * Returns a [FileStat] object containing the data returned by stat().
370 *
371 * If the call fails, returns a [FileStat] object with .type set to
372 * FileSystemEntityType.NOT_FOUND and the other fields invalid.
373 */
374 FileStat statSync();
375
376 /**
377 * Deletes this [FileSystemEntity].
378 *
379 * If the [FileSystemEntity] is a directory, and if [recursive] is false,
380 * the directory must be empty. Otherwise, if [recursive] is true, the
381 * directory and all sub-directories and files in the directories are
382 * deleted. Links are not followed when deleting recursively. Only the link
383 * is deleted, not its target.
384 *
385 * 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.
387 * This behavior allows [delete] to be used to unconditionally delete any file
388 * system object.
389 *
390 * Returns a [:Future<FileSystemEntity>:] that completes with this
391 * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity]
392 * cannot be deleted, the future completes with an exception.
393 */
394 Future<FileSystemEntity> delete({bool recursive: false})
395 => _delete(recursive: recursive);
396
397 /**
398 * Synchronously deletes this [FileSystemEntity].
399 *
400 * If the [FileSystemEntity] is a directory, and if [recursive] is false,
401 * the directory must be empty. Otherwise, if [recursive] is true, the
402 * directory and all sub-directories and files in the directories are
403 * deleted. Links are not followed when deleting recursively. Only the link
404 * is deleted, not its target.
405 *
406 * 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.
408 * This behavior allows [deleteSync] to be used to unconditionally delete any
409 * file system object.
410 *
411 * Throws an exception if the [FileSystemEntity] cannot be deleted.
412 */
413 void deleteSync({bool recursive: false})
414 => _deleteSync(recursive: recursive);
415
416
417 /**
418 * Start watching the [FileSystemEntity] for changes.
419 *
420 * The implementation uses platform-dependent event-based APIs for receiving
421 * file-system notifications, thus behavior depends on the platform.
422 *
423 * * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only
424 * supports watching directories. Recursive watching is supported.
425 * * `Linux`: Uses `inotify`. The implementation supports watching both
426 * files and directories. Recursive watching is not supported.
427 * Note: When watching files directly, delete events might not happen
428 * as expected.
429 * * `OS X`: Uses `FSEvents`. The implementation supports watching both
430 * files and directories. Recursive watching is supported.
431 *
432 * The system will start listening for events once the returned [Stream] is
433 * being listened to, not when the call to [watch] is issued.
434 *
435 * The returned value is an endless broadcast [Stream], that only stops when
436 * one of the following happens:
437 *
438 * * The [Stream] is canceled, e.g. by calling `cancel` on the
439 * [StreamSubscription].
440 * * The [FileSystemEntity] being watches, is deleted.
441 *
442 * Use `events` to specify what events to listen for. The constants in
443 * [FileSystemEvent] can be or'ed together to mix events. Default is
444 * [FileSystemEvent.ALL].
445 *
446 * A move event may be reported as seperate delete and create events.
447 */
448 Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL,
449 bool recursive: false})
450 => _FileSystemWatcher._watch(_trimTrailingPathSeparators(path),
451 events,
452 recursive);
453
454 Future<FileSystemEntity> _delete({bool recursive: false});
455 void _deleteSync({bool recursive: false});
456
457 /**
458 * Checks whether two paths refer to the same object in the
459 * file system. Returns a [:Future<bool>:] that completes with the result.
460 *
461 * 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
463 * Link.target explicitly to fetch it. Directory links appearing
464 * inside a path are followed, though, to find the file system object.
465 *
466 * Completes the returned Future with an error if one of the paths points
467 * to an object that does not exist.
468 */
469 static Future<bool> identical(String path1, String path2) {
470 return _IOService._dispatch(_FILE_IDENTICAL, [path1, path2]).then((response) {
471 if (_isErrorResponse(response)) {
472 throw _exceptionFromResponse(response,
473 "Error in FileSystemEntity.identical($path1, $path2)", "");
474 }
475 return response;
476 });
477 }
478
479 static final RegExp _absoluteWindowsPathPattern =
480 new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])');
481
482 /**
483 * Returns a [bool] indicating whether this object's path is absolute.
484 *
485 * On Windows, a path is absolute if it starts with \\ or a drive letter
486 * between a and z (upper or lower case) followed by :\ or :/.
487 * On non-Windows, a path is absolute if it starts with /.
488 */
489 bool get isAbsolute {
490 if (Platform.isWindows) {
491 return path.startsWith(_absoluteWindowsPathPattern);
492 } else {
493 return path.startsWith('/');
494 }
495 }
496
497 /**
498 * Returns a [FileSystemEntity] whose path is the absolute path to [this].
499 * The type of the returned instance is the type of [this].
500 *
501 * The absolute path is computed by prefixing
502 * a relative path with the current working directory, and returning
503 * an absolute path unchanged.
504 */
505 FileSystemEntity get absolute;
506
507 String get _absolutePath {
508 if (isAbsolute) return path;
509 String current = Directory.current.path;
510 if (current.endsWith('/') ||
511 (Platform.isWindows && current.endsWith('\\'))) {
512 return '$current$path';
513 } else {
514 return '$current${Platform.pathSeparator}$path';
515 }
516 }
517
518
519 /**
520 * Synchronously checks whether two paths refer to the same object in the
521 * file system.
522 *
523 * 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
525 * Link.target explicitly to fetch it. Directory links appearing
526 * inside a path are followed, though, to find the file system object.
527 *
528 * Throws an error if one of the paths points to an object that does not
529 * exist.
530 */
531 static bool identicalSync(String path1, String path2) {
532 var result = _identical(path1, path2);
533 _throwIfError(result, 'Error in FileSystemEntity.identicalSync');
534 return result;
535 }
536
537 /**
538 * Test if [watch] is supported on the current system.
539 *
540 * OS X 10.6 and below is not supported.
541 */
542 static bool get isWatchSupported => _FileSystemWatcher.isSupported;
543
544 /**
545 * Finds the type of file system object that a path points to. Returns
546 * a [:Future<FileSystemEntityType>:] that completes with the result.
547 *
548 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY,
549 * LINK, and NOT_FOUND. [type] will return LINK only if the optional
550 * 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
552 * 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,
554 * caused by passing the wrong type of arguments to the function.
555 */
556 static Future<FileSystemEntityType> type(String path,
557 {bool followLinks: true})
558 => _getTypeAsync(path, followLinks).then(FileSystemEntityType._lookup);
559
560 /**
561 * Synchronously finds the type of file system object that a path points to.
562 * Returns a [FileSystemEntityType].
563 *
564 * [FileSystemEntityType] has the constant instances FILE, DIRECTORY,
565 * LINK, and NOT_FOUND. [type] will return LINK only if the optional
566 * 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
568 * occurs in looking up the path, NOT_FOUND is returned. The only
569 * error or exception that may be thrown is ArgumentError,
570 * caused by passing the wrong type of arguments to the function.
571 */
572 static FileSystemEntityType typeSync(String path, {bool followLinks: true})
573 => FileSystemEntityType._lookup(_getTypeSync(path, followLinks));
574
575 /**
576 * Checks if type(path, followLinks: false) returns
577 * FileSystemEntityType.LINK.
578 */
579 static Future<bool> isLink(String path) => _getTypeAsync(path, false)
580 .then((type) => (type == FileSystemEntityType.LINK._type));
581
582 /**
583 * Checks if type(path) returns FileSystemEntityType.FILE.
584 */
585 static Future<bool> isFile(String path) => _getTypeAsync(path, true)
586 .then((type) => (type == FileSystemEntityType.FILE._type));
587
588 /**
589 * Checks if type(path) returns FileSystemEntityType.DIRECTORY.
590 */
591 static Future<bool> isDirectory(String path) => _getTypeAsync(path, true)
592 .then((type) => (type == FileSystemEntityType.DIRECTORY._type));
593
594 /**
595 * Synchronously checks if typeSync(path, followLinks: false) returns
596 * FileSystemEntityType.LINK.
597 */
598 static bool isLinkSync(String path) =>
599 (_getTypeSync(path, false) == FileSystemEntityType.LINK._type);
600
601 /**
602 * Synchronously checks if typeSync(path) returns
603 * FileSystemEntityType.FILE.
604 */
605 static bool isFileSync(String path) =>
606 (_getTypeSync(path, true) == FileSystemEntityType.FILE._type);
607
608 /**
609 * Synchronously checks if typeSync(path) returns
610 * FileSystemEntityType.DIRECTORY.
611 */
612 static bool isDirectorySync(String path) =>
613 (_getTypeSync(path, true) == FileSystemEntityType.DIRECTORY._type);
614
615 external static _getType(String path, bool followLinks);
616 external static _identical(String path1, String path2);
617 external static _resolveSymbolicLinks(String path);
618
619 // Finds the next-to-last component when dividing at path separators.
620 static final RegExp _parentRegExp = Platform.isWindows ?
621 new RegExp(r'[^/\\][/\\]+[^/\\]') :
622 new RegExp(r'[^/]/+[^/]');
623
624 /**
625 * 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
627 * of a Windows path, like "C:\" or "\\server_name\".
628 * Ignores trailing path separators, and leaves no trailing path separators.
629 */
630 static String parentOf(String path) {
631 int rootEnd = -1;
632 if (Platform.isWindows) {
633 if (path.startsWith(_absoluteWindowsPathPattern)) {
634 // Root ends at first / or \ after the first two characters.
635 rootEnd = path.indexOf(new RegExp(r'[/\\]'), 2);
636 if (rootEnd == -1) return path;
637 } else if (path.startsWith('\\') || path.startsWith('/')) {
638 rootEnd = 0;
639 }
640 } else if (path.startsWith('/')) {
641 rootEnd = 0;
642 }
643 // Ignore trailing slashes.
644 // All non-trivial cases have separators between two non-separators.
645 int pos = path.lastIndexOf(_parentRegExp);
646 if (pos > rootEnd) {
647 return path.substring(0, pos + 1);
648 } else if (rootEnd > -1) {
649 return path.substring(0, rootEnd + 1);
650 } else {
651 return '.';
652 }
653 }
654
655 /**
656 * The directory containing [this]. If [this] is a root
657 * directory, returns [this].
658 */
659 Directory get parent => new Directory(parentOf(path));
660
661 static int _getTypeSync(String path, bool followLinks) {
662 var result = _getType(path, followLinks);
663 _throwIfError(result, 'Error getting type of FileSystemEntity');
664 return result;
665 }
666
667 static Future<int> _getTypeAsync(String path, bool followLinks) {
668 return _IOService._dispatch(_FILE_TYPE, [path, followLinks])
669 .then((response) {
670 if (_isErrorResponse(response)) {
671 throw _exceptionFromResponse(response, "Error getting type", path);
672 }
673 return response;
674 });
675 }
676
677 static _throwIfError(Object result, String msg, [String path]) {
678 if (result is OSError) {
679 throw new FileSystemException(msg, path, result);
680 } else if (result is ArgumentError) {
681 throw result;
682 }
683 }
684
685 static String _trimTrailingPathSeparators(String path) {
686 // Don't handle argument errors here.
687 if (path is! String) return path;
688 if (Platform.isWindows) {
689 while (path.length > 1 &&
690 (path.endsWith(Platform.pathSeparator) ||
691 path.endsWith('/'))) {
692 path = path.substring(0, path.length - 1);
693 }
694 } else {
695 while (path.length > 1 && path.endsWith(Platform.pathSeparator)) {
696 path = path.substring(0, path.length - 1);
697 }
698 }
699 return path;
700 }
701
702 static String _ensureTrailingPathSeparators(String path) {
703 // Don't handle argument errors here.
704 if (path is! String) return path;
705 if (path.isEmpty) path = '.';
706 if (Platform.isWindows) {
707 while (!path.endsWith(Platform.pathSeparator) && !path.endsWith('/')) {
708 path = "$path${Platform.pathSeparator}";
709 }
710 } else {
711 while (!path.endsWith(Platform.pathSeparator)) {
712 path = "$path${Platform.pathSeparator}";
713 }
714 }
715 return path;
716 }
717 }
718
719
720 /**
721 * Base event class emitted by [FileSystemEntity.watch].
722 */
723 class FileSystemEvent {
724 /**
725 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s.
726 */
727 static const int CREATE = 1 << 0;
728
729 /**
730 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemModifyEvent]s.
731 */
732 static const int MODIFY = 1 << 1;
733
734 /**
735 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemDeleteEvent]s.
736 */
737 static const int DELETE = 1 << 2;
738
739 /**
740 * Bitfield for [FileSystemEntity.watch], to enable [FileSystemMoveEvent]s.
741 */
742 static const int MOVE = 1 << 3;
743
744 /**
745 * Bitfield for [FileSystemEntity.watch], for enabling all of [CREATE],
746 * [MODIFY], [DELETE] and [MOVE].
747 */
748 static const int ALL = CREATE | MODIFY | DELETE | MOVE;
749
750 static const int _MODIFY_ATTRIBUTES = 1 << 4;
751 static const int _DELETE_SELF = 1 << 5;
752 static const int _IS_DIR = 1 << 6;
753
754 /**
755 * The type of event. See [FileSystemEvent] for a list of events.
756 */
757 final int type;
758
759 /**
760 * The path that triggered the event. Depending on the platform and the
761 * FileSystemEntity, the path may be relative.
762 */
763 final String path;
764
765 /**
766 * Is `true` if the event target was a directory.
767 */
768 final bool isDirectory;
769
770 FileSystemEvent._(this.type, this.path, this.isDirectory);
771 }
772
773
774 /**
775 * File system event for newly created file system objects.
776 */
777 class FileSystemCreateEvent extends FileSystemEvent {
778 FileSystemCreateEvent._(path, isDirectory)
779 : super._(FileSystemEvent.CREATE, path, isDirectory);
780
781 String toString() => "FileSystemCreateEvent('$path')";
782 }
783
784
785 /**
786 * File system event for modifications of file system objects.
787 */
788 class FileSystemModifyEvent extends FileSystemEvent {
789 /**
790 * If the content was changed and not only the attributes, [contentChanged]
791 * is `true`.
792 */
793 final bool contentChanged;
794
795 FileSystemModifyEvent._(path, isDirectory, this.contentChanged)
796 : super._(FileSystemEvent.MODIFY, path, isDirectory);
797
798 String toString() =>
799 "FileSystemModifyEvent('$path', contentChanged=$contentChanged)";
800 }
801
802
803 /**
804 * File system event for deletion of file system objects.
805 */
806 class FileSystemDeleteEvent extends FileSystemEvent {
807 FileSystemDeleteEvent._(path, isDirectory)
808 : super._(FileSystemEvent.DELETE, path, isDirectory);
809
810 String toString() => "FileSystemDeleteEvent('$path')";
811 }
812
813
814 /**
815 * File system event for moving of file system objects.
816 */
817 class FileSystemMoveEvent extends FileSystemEvent {
818 /**
819 * If the underlaying implementation is able to identify the destination of
820 * the moved file, [destination] will be set. Otherwise, it will be `null`.
821 */
822 final String destination;
823
824 FileSystemMoveEvent._(path, isDirectory, this.destination)
825 : super._(FileSystemEvent.MOVE, path, isDirectory);
826
827 String toString() {
828 var buffer = new StringBuffer();
829 buffer.write("FileSystemMoveEvent('$path'");
830 if (destination != null) buffer.write(", '$destination'");
831 buffer.write(')');
832 return buffer.toString();
833 }
834 }
835
836
837 class _FileSystemWatcher {
838 external static Stream<FileSystemEvent> _watch(
839 String path, int events, bool recursive);
840 external static bool get isSupported;
841 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/lib/io/file_impl.dart ('k') | pkg/dev_compiler/tool/input_sdk/lib/io/http.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698