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

Unified Diff: packages/glob/lib/src/list_tree.dart

Issue 3015713002: Roll to pickup pool changes
Patch Set: Created 3 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/glob/lib/src/ast.dart ('k') | packages/glob/lib/src/parser.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/glob/lib/src/list_tree.dart
diff --git a/packages/glob/lib/src/list_tree.dart b/packages/glob/lib/src/list_tree.dart
index 3cce642253c25b18d4593fcff67807ffd67f6be2..f51e4bb58018f7dd06f2f8df8dacaa6ee255b842 100644
--- a/packages/glob/lib/src/list_tree.dart
+++ b/packages/glob/lib/src/list_tree.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:io';
import 'dart:async';
+import 'dart:io';
import 'package:async/async.dart';
import 'package:path/path.dart' as p;
@@ -143,8 +143,8 @@ class ListTree {
parent = parent.children[component];
}
} else if (recursive) {
- _trees[root] = new _ListTreeNode.recursive(
- _join(components.sublist(i)));
+ _trees[root] =
+ new _ListTreeNode.recursive(_join(components.sublist(i)));
return;
} else if (complete) {
_trees[root] = new _ListTreeNode()..addOption(component);
@@ -193,8 +193,7 @@ class ListTree {
List<FileSystemEntity> listSync({String root, bool followLinks: true}) {
if (root == null) root = '.';
- // TODO(nweiz): Remove the explicit annotation when sdk#26139 is fixed.
- var result = _trees.keys.expand/*<FileSystemEntity>*/((rootDir) {
+ var result = _trees.keys.expand((rootDir) {
var dir = rootDir == '.' ? root : rootDir;
return _trees[rootDir].listSync(dir, followLinks: followLinks);
});
@@ -247,7 +246,6 @@ class _ListTreeNode {
/// its children.
bool get _isIntermediate {
if (_validator != null) return false;
- if (!_caseSensitive) return false;
return children.keys.every((sequence) =>
sequence.nodes.length == 1 && sequence.nodes.first is LiteralNode);
}
@@ -301,8 +299,8 @@ class _ListTreeNode {
/// Adds [validator] to this node's existing validator.
void addOption(SequenceNode validator) {
if (_validator == null) {
- _validator = new OptionsNode([validator],
- caseSensitive: validator.caseSensitive);
+ _validator =
+ new OptionsNode([validator], caseSensitive: validator.caseSensitive);
} else {
_validator.options.add(validator);
}
@@ -314,15 +312,15 @@ class _ListTreeNode {
/// [ListTree.list].
Stream<FileSystemEntity> list(String dir, {bool followLinks: true}) {
if (isRecursive) {
- return new Directory(dir).list(recursive: true, followLinks: followLinks)
+ return new Directory(dir)
+ .list(recursive: true, followLinks: followLinks)
.where((entity) => _matches(p.relative(entity.path, from: dir)));
}
- var resultGroup = new StreamGroup<FileSystemEntity>();
-
// Don't spawn extra [Directory.list] calls when we already know exactly
// which subdirectories we're interested in.
- if (_isIntermediate) {
+ if (_isIntermediate && _caseSensitive) {
+ var resultGroup = new StreamGroup<FileSystemEntity>();
children.forEach((sequence, child) {
resultGroup.add(child.list(
p.join(dir, (sequence.nodes.single as LiteralNode).text),
@@ -332,35 +330,65 @@ class _ListTreeNode {
return resultGroup.stream;
}
- var resultController = new StreamController<FileSystemEntity>(sync: true);
- resultGroup.add(resultController.stream);
- new Directory(dir).list(followLinks: followLinks).listen((entity) {
- var basename = p.relative(entity.path, from: dir);
- if (_matches(basename)) resultController.add(entity);
-
- children.forEach((sequence, child) {
- if (entity is! Directory) return;
- if (!sequence.matches(basename)) return;
- var stream = child.list(p.join(dir, basename), followLinks: followLinks)
- .handleError((_) {}, test: (error) {
- // Ignore errors from directories not existing. We do this here so
- // that we only ignore warnings below wild cards. For example, the
- // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but
- // succeed if "foo/bar/qux/baz" doesn't exist.
- return error is FileSystemException &&
- (error.osError.errorCode == _ENOENT ||
- error.osError.errorCode == _ENOENT_WIN);
- });
- resultGroup.add(stream);
- });
- },
- onError: resultController.addError,
- onDone: () {
- resultController.close();
- resultGroup.close();
+ return StreamCompleter.fromFuture(() async {
+ var entities =
+ await new Directory(dir).list(followLinks: followLinks).toList();
+ await _validateIntermediateChildrenAsync(dir, entities);
+
+ var resultGroup = new StreamGroup<FileSystemEntity>();
+ var resultController = new StreamController<FileSystemEntity>(sync: true);
+ resultGroup.add(resultController.stream);
+ for (var entity in entities) {
+ var basename = p.relative(entity.path, from: dir);
+ if (_matches(basename)) resultController.add(entity);
+
+ children.forEach((sequence, child) {
+ if (entity is! Directory) return;
+ if (!sequence.matches(basename)) return;
+ var stream = child
+ .list(p.join(dir, basename), followLinks: followLinks)
+ .handleError((_) {}, test: (error) {
+ // Ignore errors from directories not existing. We do this here so
+ // that we only ignore warnings below wild cards. For example, the
+ // glob "foo/bar/*/baz" should fail if "foo/bar" doesn't exist but
+ // succeed if "foo/bar/qux/baz" doesn't exist.
+ return error is FileSystemException &&
+ (error.osError.errorCode == _ENOENT ||
+ error.osError.errorCode == _ENOENT_WIN);
+ });
+ resultGroup.add(stream);
});
+ }
+ resultController.close();
+ resultGroup.close();
+ return resultGroup.stream;
+ }());
+ }
+
+ /// If this is a case-insensitive list, validates that all intermediate
+ /// children (according to [_isIntermediate]) match at least one entity in
+ /// [entities].
+ ///
+ /// This ensures that listing "foo/bar/*" fails on case-sensitive systems if
+ /// "foo/bar" doesn't exist.
+ Future _validateIntermediateChildrenAsync(
+ String dir, List<FileSystemEntity> entities) async {
+ if (_caseSensitive) return;
+
+ for (var sequence in children.keys) {
+ var child = children[sequence];
+ if (!child._isIntermediate) continue;
+ if (entities.any(
+ (entity) => sequence.matches(p.relative(entity.path, from: dir)))) {
+ continue;
+ }
- return resultGroup.stream;
+ // We know this will fail, we're just doing it to force dart:io to emit
+ // the exception it would if we were listing case-sensitively.
+ await child
+ .list(p.join(dir, (sequence.nodes.single as LiteralNode).text))
+ .toList();
+ }
}
/// Synchronously lists all entities within [dir] matching this node or its
@@ -377,7 +405,7 @@ class _ListTreeNode {
// Don't spawn extra [Directory.listSync] calls when we already know exactly
// which subdirectories we're interested in.
- if (_isIntermediate) {
+ if (_isIntermediate && _caseSensitive) {
return children.keys.expand((sequence) {
return children[sequence].listSync(
p.join(dir, (sequence.nodes.single as LiteralNode).text),
@@ -385,8 +413,10 @@ class _ListTreeNode {
});
}
- return new Directory(dir).listSync(followLinks: followLinks)
- .expand((entity) {
+ var entities = new Directory(dir).listSync(followLinks: followLinks);
+ _validateIntermediateChildrenSync(dir, entities);
+
+ return entities.expand((entity) {
var entities = <FileSystemEntity>[];
var basename = p.relative(entity.path, from: dir);
if (_matches(basename)) entities.add(entity);
@@ -396,8 +426,9 @@ class _ListTreeNode {
.where((sequence) => sequence.matches(basename))
.expand((sequence) {
try {
- return children[sequence].listSync(
- p.join(dir, basename), followLinks: followLinks).toList();
+ return children[sequence]
+ .listSync(p.join(dir, basename), followLinks: followLinks)
+ .toList();
} on FileSystemException catch (error) {
// Ignore errors from directories not existing. We do this here so
// that we only ignore warnings below wild cards. For example, the
@@ -416,6 +447,31 @@ class _ListTreeNode {
});
}
+ /// If this is a case-insensitive list, validates that all intermediate
+ /// children (according to [_isIntermediate]) match at least one entity in
+ /// [entities].
+ ///
+ /// This ensures that listing "foo/bar/*" fails on case-sensitive systems if
+ /// "foo/bar" doesn't exist.
+ void _validateIntermediateChildrenSync(
+ String dir, List<FileSystemEntity> entities) {
+ if (_caseSensitive) return;
+
+ children.forEach((sequence, child) {
+ if (!child._isIntermediate) return;
+ if (entities.any(
+ (entity) => sequence.matches(p.relative(entity.path, from: dir)))) {
+ return;
+ }
+
+ // If there are no [entities] that match [sequence], manually list the
+ // directory to force `dart:io` to throw an error. This allows us to
+ // ensure that listing "foo/bar/*" fails on case-sensitive systems if
+ // "foo/bar" doesn't exist.
+ child.listSync(p.join(dir, (sequence.nodes.single as LiteralNode).text));
+ });
+ }
+
/// Returns whether the native [path] matches [_validator].
bool _matches(String path) {
if (_validator == null) return false;
« no previous file with comments | « packages/glob/lib/src/ast.dart ('k') | packages/glob/lib/src/parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698