| 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 glob.list_tree; | 5 library glob.list_tree; |
| 6 | 6 |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 | 9 |
| 10 import 'package:path/path.dart' as p; | 10 import 'package:path/path.dart' as p; |
| 11 | 11 |
| 12 import 'ast.dart'; | 12 import 'ast.dart'; |
| 13 import 'stream_pool.dart'; | 13 import 'stream_pool.dart'; |
| 14 import 'utils.dart'; | 14 import 'utils.dart'; |
| 15 | 15 |
| 16 /// The errno for a file or directory not existing. | 16 /// The errno for a file or directory not existing on Mac and Linux. |
| 17 /// | |
| 18 /// This is consistent across platforms. | |
| 19 const _ENOENT = 2; | 17 const _ENOENT = 2; |
| 20 | 18 |
| 19 /// Another errno we see on Windows when trying to list a non-existent |
| 20 /// directory. |
| 21 const _ENOENT_WIN = 3; |
| 22 |
| 21 /// A structure built from a glob that efficiently lists filesystem entities | 23 /// A structure built from a glob that efficiently lists filesystem entities |
| 22 /// that match that glob. | 24 /// that match that glob. |
| 23 /// | 25 /// |
| 24 /// This structure is designed to list the minimal number of physical | 26 /// This structure is designed to list the minimal number of physical |
| 25 /// directories necessary to find everything that matches the glob. For example, | 27 /// directories necessary to find everything that matches the glob. For example, |
| 26 /// for the glob `foo/{bar,baz}/*`, there's no need to list the working | 28 /// for the glob `foo/{bar,baz}/*`, there's no need to list the working |
| 27 /// directory or even `foo/`; only `foo/bar` and `foo/baz` should be listed. | 29 /// directory or even `foo/`; only `foo/bar` and `foo/baz` should be listed. |
| 28 /// | 30 /// |
| 29 /// This works by creating a tree of [_ListTreeNode]s, each of which corresponds | 31 /// This works by creating a tree of [_ListTreeNode]s, each of which corresponds |
| 30 /// to a single of directory nesting in the source glob. Each node has child | 32 /// to a single of directory nesting in the source glob. Each node has child |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 children.forEach((sequence, child) { | 326 children.forEach((sequence, child) { |
| 325 if (entity is! Directory) return; | 327 if (entity is! Directory) return; |
| 326 if (!sequence.matches(basename)) return; | 328 if (!sequence.matches(basename)) return; |
| 327 var stream = child.list(p.join(dir, basename), followLinks: followLinks) | 329 var stream = child.list(p.join(dir, basename), followLinks: followLinks) |
| 328 .handleError((_) {}, test: (error) { | 330 .handleError((_) {}, test: (error) { |
| 329 // Ignore errors from directories not existing. We do this here so | 331 // Ignore errors from directories not existing. We do this here so |
| 330 // that we only ignore warnings below wild cards. For example, the | 332 // that we only ignore warnings below wild cards. For example, the |
| 331 // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but | 333 // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but |
| 332 // succeed if "foo/bar/qux/baz" doesn't exist. | 334 // succeed if "foo/bar/qux/baz" doesn't exist. |
| 333 return error is FileSystemException && | 335 return error is FileSystemException && |
| 334 error.osError.errorCode == _ENOENT; | 336 (error.osError.errorCode == _ENOENT || |
| 337 error.osError.errorCode == _ENOENT_WIN); |
| 335 }); | 338 }); |
| 336 resultPool.add(stream); | 339 resultPool.add(stream); |
| 337 }); | 340 }); |
| 338 }, | 341 }, |
| 339 onError: resultController.addError, | 342 onError: resultController.addError, |
| 340 onDone: resultController.close); | 343 onDone: resultController.close); |
| 341 | 344 |
| 342 resultPool.closeWhenEmpty(); | 345 resultPool.closeWhenEmpty(); |
| 343 return resultPool.stream; | 346 return resultPool.stream; |
| 344 } | 347 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 375 .where((sequence) => sequence.matches(basename)) | 378 .where((sequence) => sequence.matches(basename)) |
| 376 .expand((sequence) { | 379 .expand((sequence) { |
| 377 try { | 380 try { |
| 378 return children[sequence].listSync( | 381 return children[sequence].listSync( |
| 379 p.join(dir, basename), followLinks: followLinks).toList(); | 382 p.join(dir, basename), followLinks: followLinks).toList(); |
| 380 } on FileSystemException catch (error) { | 383 } on FileSystemException catch (error) { |
| 381 // Ignore errors from directories not existing. We do this here so | 384 // Ignore errors from directories not existing. We do this here so |
| 382 // that we only ignore warnings below wild cards. For example, the | 385 // that we only ignore warnings below wild cards. For example, the |
| 383 // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but | 386 // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but |
| 384 // succeed if "foo/bar/qux/baz" doesn't exist. | 387 // succeed if "foo/bar/qux/baz" doesn't exist. |
| 385 if (error.osError.errorCode == _ENOENT) { | 388 if (error.osError.errorCode == _ENOENT || |
| 389 error.osError.errorCode == _ENOENT_WIN) { |
| 386 return const []; | 390 return const []; |
| 387 } else { | 391 } else { |
| 388 rethrow; | 392 rethrow; |
| 389 } | 393 } |
| 390 } | 394 } |
| 391 })); | 395 })); |
| 392 | 396 |
| 393 return entities; | 397 return entities; |
| 394 }); | 398 }); |
| 395 } | 399 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 407 /// a path separator. | 411 /// a path separator. |
| 408 SequenceNode _join(Iterable<AstNode> components) { | 412 SequenceNode _join(Iterable<AstNode> components) { |
| 409 var componentsList = components.toList(); | 413 var componentsList = components.toList(); |
| 410 var nodes = [componentsList.removeAt(0)]; | 414 var nodes = [componentsList.removeAt(0)]; |
| 411 for (var component in componentsList) { | 415 for (var component in componentsList) { |
| 412 nodes.add(new LiteralNode('/')); | 416 nodes.add(new LiteralNode('/')); |
| 413 nodes.add(component); | 417 nodes.add(component); |
| 414 } | 418 } |
| 415 return new SequenceNode(nodes); | 419 return new SequenceNode(nodes); |
| 416 } | 420 } |
| OLD | NEW |