| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library resource; | 5 library resource; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:io' as io; | 9 import 'dart:io' as io; |
| 10 | 10 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 * Return a list of existing direct children [Resource]s (folders and files) | 40 * Return a list of existing direct children [Resource]s (folders and files) |
| 41 * in this folder, in no particular order. | 41 * in this folder, in no particular order. |
| 42 */ | 42 */ |
| 43 List<Resource> getChildren(); | 43 List<Resource> getChildren(); |
| 44 | 44 |
| 45 /** | 45 /** |
| 46 * Watch for changes to the files inside this folder (and in any nested | 46 * Watch for changes to the files inside this folder (and in any nested |
| 47 * folders, including folders reachable via links). | 47 * folders, including folders reachable via links). |
| 48 */ | 48 */ |
| 49 Stream<WatchEvent> get changes; | 49 Stream<WatchEvent> get changes; |
| 50 |
| 51 /** |
| 52 * If the path [path] is a relative path, convert it to an absolute path |
| 53 * by interpreting it relative to this folder. If it is already an aboslute |
| 54 * path, then don't change it. |
| 55 * |
| 56 * However, regardless of whether [path] is relative or absolute, normalize |
| 57 * it by removing path components of the form '.' or '..'. |
| 58 */ |
| 59 String canonicalizePath(String path); |
| 50 } | 60 } |
| 51 | 61 |
| 52 | 62 |
| 53 /** | 63 /** |
| 54 * The abstract class [Resource] is an abstraction of file or folder. | 64 * The abstract class [Resource] is an abstraction of file or folder. |
| 55 */ | 65 */ |
| 56 abstract class Resource { | 66 abstract class Resource { |
| 57 /** | 67 /** |
| 58 * Return `true` if this resource exists. | 68 * Return `true` if this resource exists. |
| 59 */ | 69 */ |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 241 |
| 232 | 242 |
| 233 /** | 243 /** |
| 234 * An in-memory implementation of [Folder]. | 244 * An in-memory implementation of [Folder]. |
| 235 */ | 245 */ |
| 236 class _MemoryFolder extends _MemoryResource implements Folder { | 246 class _MemoryFolder extends _MemoryResource implements Folder { |
| 237 _MemoryFolder(MemoryResourceProvider provider, String path) : | 247 _MemoryFolder(MemoryResourceProvider provider, String path) : |
| 238 super(provider, path); | 248 super(provider, path); |
| 239 @override | 249 @override |
| 240 Resource getChild(String relPath) { | 250 Resource getChild(String relPath) { |
| 241 relPath = posix.normalize(relPath); | 251 String childPath = canonicalizePath(relPath); |
| 242 String childPath = posix.join(path, relPath); | |
| 243 childPath = posix.normalize(childPath); | |
| 244 _MemoryResource resource = _provider._pathToResource[childPath]; | 252 _MemoryResource resource = _provider._pathToResource[childPath]; |
| 245 if (resource == null) { | 253 if (resource == null) { |
| 246 resource = new _MemoryFile(_provider, childPath); | 254 resource = new _MemoryFile(_provider, childPath); |
| 247 } | 255 } |
| 248 return resource; | 256 return resource; |
| 249 } | 257 } |
| 250 | 258 |
| 251 @override | 259 @override |
| 252 List<Resource> getChildren() { | 260 List<Resource> getChildren() { |
| 253 List<Resource> children = <Resource>[]; | 261 List<Resource> children = <Resource>[]; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 267 } | 275 } |
| 268 _provider._pathToWatchers[path].add(streamController); | 276 _provider._pathToWatchers[path].add(streamController); |
| 269 streamController.done.then((_) { | 277 streamController.done.then((_) { |
| 270 _provider._pathToWatchers[path].remove(streamController); | 278 _provider._pathToWatchers[path].remove(streamController); |
| 271 if (_provider._pathToWatchers[path].isEmpty) { | 279 if (_provider._pathToWatchers[path].isEmpty) { |
| 272 _provider._pathToWatchers.remove(path); | 280 _provider._pathToWatchers.remove(path); |
| 273 } | 281 } |
| 274 }); | 282 }); |
| 275 return streamController.stream; | 283 return streamController.stream; |
| 276 } | 284 } |
| 285 |
| 286 @override |
| 287 String canonicalizePath(String relPath) { |
| 288 relPath = posix.normalize(relPath); |
| 289 String childPath = posix.join(path, relPath); |
| 290 childPath = posix.normalize(childPath); |
| 291 return childPath; |
| 292 } |
| 277 } | 293 } |
| 278 | 294 |
| 279 | 295 |
| 280 /** | 296 /** |
| 281 * An in-memory implementation of [ResourceProvider]. | 297 * An in-memory implementation of [ResourceProvider]. |
| 282 * Use `/` as a path separator. | 298 * Use `/` as a path separator. |
| 283 */ | 299 */ |
| 284 class MemoryResourceProvider implements ResourceProvider { | 300 class MemoryResourceProvider implements ResourceProvider { |
| 285 final HashMap<String, _MemoryResource> _pathToResource = | 301 final HashMap<String, _MemoryResource> _pathToResource = |
| 286 new HashMap<String, _MemoryResource>(); | 302 new HashMap<String, _MemoryResource>(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 | 406 |
| 391 | 407 |
| 392 /** | 408 /** |
| 393 * A `dart:io` based implementation of [Folder]. | 409 * A `dart:io` based implementation of [Folder]. |
| 394 */ | 410 */ |
| 395 class _PhysicalFolder extends _PhysicalResource implements Folder { | 411 class _PhysicalFolder extends _PhysicalResource implements Folder { |
| 396 _PhysicalFolder(io.Directory directory) : super(directory); | 412 _PhysicalFolder(io.Directory directory) : super(directory); |
| 397 | 413 |
| 398 @override | 414 @override |
| 399 Resource getChild(String relPath) { | 415 Resource getChild(String relPath) { |
| 400 String childPath = join(_entry.absolute.path, relPath); | 416 return PhysicalResourceProvider.INSTANCE.getResource(canonicalizePath(relPat
h)); |
| 401 return PhysicalResourceProvider.INSTANCE.getResource(childPath); | |
| 402 } | 417 } |
| 403 | 418 |
| 404 @override | 419 @override |
| 405 List<Resource> getChildren() { | 420 List<Resource> getChildren() { |
| 406 List<Resource> children = <Resource>[]; | 421 List<Resource> children = <Resource>[]; |
| 407 io.Directory directory = _entry as io.Directory; | 422 io.Directory directory = _entry as io.Directory; |
| 408 List<io.FileSystemEntity> entries = directory.listSync(recursive: false); | 423 List<io.FileSystemEntity> entries = directory.listSync(recursive: false); |
| 409 int numEntries = entries.length; | 424 int numEntries = entries.length; |
| 410 for (int i = 0; i < numEntries; i++) { | 425 for (int i = 0; i < numEntries; i++) { |
| 411 io.FileSystemEntity entity = entries[i]; | 426 io.FileSystemEntity entity = entries[i]; |
| 412 if (entity is io.Directory) { | 427 if (entity is io.Directory) { |
| 413 children.add(new _PhysicalFolder(entity)); | 428 children.add(new _PhysicalFolder(entity)); |
| 414 } else if (entity is io.File) { | 429 } else if (entity is io.File) { |
| 415 children.add(new _PhysicalFile(entity)); | 430 children.add(new _PhysicalFile(entity)); |
| 416 } | 431 } |
| 417 } | 432 } |
| 418 return children; | 433 return children; |
| 419 } | 434 } |
| 420 | 435 |
| 421 @override | 436 @override |
| 422 Stream<WatchEvent> get changes => new DirectoryWatcher(_entry.path).events; | 437 Stream<WatchEvent> get changes => new DirectoryWatcher(_entry.path).events; |
| 438 |
| 439 @override |
| 440 String canonicalizePath(String relPath) { |
| 441 return normalize(join(_entry.absolute.path, relPath)); |
| 442 } |
| 423 } | 443 } |
| 424 | 444 |
| 425 | 445 |
| 426 /** | 446 /** |
| 427 * A `dart:io` based implementation of [Resource]. | 447 * A `dart:io` based implementation of [Resource]. |
| 428 */ | 448 */ |
| 429 abstract class _PhysicalResource implements Resource { | 449 abstract class _PhysicalResource implements Resource { |
| 430 final io.FileSystemEntity _entry; | 450 final io.FileSystemEntity _entry; |
| 431 | 451 |
| 432 _PhysicalResource(this._entry); | 452 _PhysicalResource(this._entry); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 } | 538 } |
| 519 | 539 |
| 520 /** | 540 /** |
| 521 * Return `true` if the given URI is a `file` URI. | 541 * Return `true` if the given URI is a `file` URI. |
| 522 * | 542 * |
| 523 * @param uri the URI being tested | 543 * @param uri the URI being tested |
| 524 * @return `true` if the given URI is a `file` URI | 544 * @return `true` if the given URI is a `file` URI |
| 525 */ | 545 */ |
| 526 static bool _isFileUri(Uri uri) => uri.scheme == _FILE_SCHEME; | 546 static bool _isFileUri(Uri uri) => uri.scheme == _FILE_SCHEME; |
| 527 } | 547 } |
| OLD | NEW |