| Index: sdk/lib/_internal/pub/lib/src/io.dart
|
| diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
|
| index 52752b15209bb4c9875f646d6de35b0f33554695..6daff54113357705330c0cdbbe2cd8d8e4e3683d 100644
|
| --- a/sdk/lib/_internal/pub/lib/src/io.dart
|
| +++ b/sdk/lib/_internal/pub/lib/src/io.dart
|
| @@ -239,9 +239,15 @@ String createSystemTempDir() {
|
| return tempDir.path;
|
| }
|
|
|
| -/// Lists the contents of [dir]. If [recursive] is `true`, lists subdirectory
|
| -/// contents (defaults to `false`). If [includeHidden] is `true`, includes files
|
| -/// and directories beginning with `.` (defaults to `false`).
|
| +/// Lists the contents of [dir].
|
| +///
|
| +/// If [recursive] is `true`, lists subdirectory contents (defaults to `false`).
|
| +/// If [includeHidden] is `true`, includes files and directories beginning with
|
| +/// `.` (defaults to `false`). If [includeDirs] is `true`, includes directories
|
| +/// as well as files (defaults to `true`).
|
| +///
|
| +/// [whiteList] is a list of hidden filenames to include even when
|
| +/// [includeHidden] is `false`.
|
| ///
|
| /// Note that dart:io handles recursive symlinks in an unfortunate way. You
|
| /// end up with two copies of every entity that is within the recursive loop.
|
| @@ -249,21 +255,41 @@ String createSystemTempDir() {
|
| /// had a noticeable performance impact. In the interest of speed, we'll just
|
| /// live with that annoying behavior.
|
| ///
|
| -/// The returned paths are guaranteed to begin with [dir].
|
| +/// The returned paths are guaranteed to begin with [dir]. Broken symlinks won't
|
| +/// be returned.
|
| List<String> listDir(String dir, {bool recursive: false,
|
| - bool includeHidden: false}) {
|
| - var entities = new Directory(dir).listSync(recursive: recursive);
|
| -
|
| - isHidden(part) => part.startsWith(".") && part != "." && part != "..";
|
| -
|
| - if (!includeHidden) {
|
| - entities = entities.where((entity) {
|
| - assert(entity.path.startsWith(dir));
|
| - return !path.split(entity.path.substring(dir.length + 1)).any(isHidden);
|
| - });
|
| - }
|
| + bool includeHidden: false, bool includeDirs: true,
|
| + Iterable<String> whitelist}) {
|
| + if (whitelist == null) whitelist = [];
|
| + var whitelistFilter = createFileFilter(whitelist);
|
| +
|
| + // This is used in some performance-sensitive paths and can list many, many
|
| + // files. As such, it leans more havily towards optimization as opposed to
|
| + // readability than most code in pub. In particular, it avoids using the path
|
| + // package, since re-parsing a path is very expensive relative to string
|
| + // operations.
|
| + return new Directory(dir).listSync(
|
| + recursive: recursive, followLinks: true).where((entity) {
|
| + if (!includeDirs && entity is Directory) return false;
|
| + if (entity is Link) return false;
|
| + if (includeHidden) return true;
|
| +
|
| + assert(entity.path.startsWith(dir));
|
| + var pathInDir = entity.path.substring(dir.length);
|
| +
|
| + // If the basename is whitelisted, don't count its "/." as making the file
|
| + // hidden.
|
| + var whitelistedBasename = whitelistFilter.firstWhere(pathInDir.contains,
|
| + orElse: () => null);
|
| + if (whitelistedBasename != null) {
|
| + pathInDir = pathInDir.substring(
|
| + 0, pathInDir.length - whitelistedBasename.length);
|
| + }
|
|
|
| - return entities.map((entity) => entity.path).toList();
|
| + if (pathInDir.contains("/.")) return false;
|
| + if (Platform.operatingSystem != "windows") return true;
|
| + return pathInDir.contains("\\.");
|
| + }).map((entity) => entity.path).toList();
|
| }
|
|
|
| /// Returns whether [dir] exists on the file system. This will return `true` for
|
|
|