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

Unified Diff: packages/watcher/lib/src/path_set.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 5 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/watcher/lib/src/file_watcher/polling.dart ('k') | packages/watcher/lib/src/resubscribable.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/watcher/lib/src/path_set.dart
diff --git a/packages/watcher/lib/src/path_set.dart b/packages/watcher/lib/src/path_set.dart
index e9f7d32d25c294ea697cb702752e63ac21112584..3726e1fd86b440142123029e8892db46c87e725c 100644
--- a/packages/watcher/lib/src/path_set.dart
+++ b/packages/watcher/lib/src/path_set.dart
@@ -2,8 +2,6 @@
// 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.
-library watcher.path_dart;
-
import 'dart:collection';
import 'package:path/path.dart' as p;
@@ -21,32 +19,24 @@ class PathSet {
/// The path set's directory hierarchy.
///
- /// Each level of this hierarchy has the same structure: a map from strings to
- /// other maps, which are further levels of the hierarchy. A map with no
- /// elements indicates a path that was added to the set that has no paths
- /// beneath it. Such a path should not be treated as a directory by
- /// [containsDir].
- final _entries = new Map<String, Map>();
-
- /// The set of paths that were explicitly added to this set.
- ///
- /// This is needed to disambiguate a directory that was explicitly added to
- /// the set from a directory that was implicitly added by adding a path
- /// beneath it.
- final _paths = new Set<String>();
+ /// Each entry represents a directory or file. It may be a file or directory
+ /// that was explicitly added, or a parent directory that was implicitly
+ /// added in order to add a child.
+ final _Entry _entries = new _Entry();
PathSet(this.root);
/// Adds [path] to the set.
void add(String path) {
path = _normalize(path);
- _paths.add(path);
- var parts = _split(path);
- var dir = _entries;
+ var parts = p.split(path);
+ var entry = _entries;
for (var part in parts) {
- dir = dir.putIfAbsent(part, () => {});
+ entry = entry.contents.putIfAbsent(part, () => new _Entry());
}
+
+ entry.isExplicit = true;
}
/// Removes [path] and any paths beneath it from the set and returns the
@@ -59,110 +49,140 @@ class PathSet {
/// empty set.
Set<String> remove(String path) {
path = _normalize(path);
- var parts = new Queue.from(_split(path));
+ var parts = new Queue.from(p.split(path));
// Remove the children of [dir], as well as [dir] itself if necessary.
//
// [partialPath] is the path to [dir], and a prefix of [path]; the remaining
// components of [path] are in [parts].
- recurse(dir, partialPath) {
+ Set<String> recurse(dir, partialPath) {
if (parts.length > 1) {
// If there's more than one component left in [path], recurse down to
// the next level.
var part = parts.removeFirst();
- var entry = dir[part];
- if (entry == null || entry.isEmpty) return new Set();
+ var entry = dir.contents[part];
+ if (entry == null || entry.contents.isEmpty) return new Set();
partialPath = p.join(partialPath, part);
var paths = recurse(entry, partialPath);
// After removing this entry's children, if it has no more children and
// it's not in the set in its own right, remove it as well.
- if (entry.isEmpty && !_paths.contains(partialPath)) dir.remove(part);
+ if (entry.contents.isEmpty && !entry.isExplicit) {
+ dir.contents.remove(part);
+ }
return paths;
}
// If there's only one component left in [path], we should remove it.
- var entry = dir.remove(parts.first);
+ var entry = dir.contents.remove(parts.first);
if (entry == null) return new Set();
- if (entry.isEmpty) {
- _paths.remove(path);
- return new Set.from([path]);
+ if (entry.contents.isEmpty) {
+ return new Set.from([p.join(root, path)]);
}
- var set = _removePathsIn(entry, path);
- if (_paths.contains(path)) {
- _paths.remove(path);
- set.add(path);
+ var set = _explicitPathsWithin(entry, path);
+ if (entry.isExplicit) {
+ set.add(p.join(root, path));
}
+
return set;
}
return recurse(_entries, root);
}
- /// Recursively removes and returns all paths in [dir].
+ /// Recursively lists all of the explicit paths within [dir].
///
- /// [root] should be the path to [dir].
- Set<String> _removePathsIn(Map dir, String root) {
- var removedPaths = new Set();
+ /// [dirPath] should be the path to [dir].
+ Set<String> _explicitPathsWithin(_Entry dir, String dirPath) {
+ var paths = new Set<String>();
recurse(dir, path) {
- dir.forEach((name, entry) {
+ dir.contents.forEach((name, entry) {
var entryPath = p.join(path, name);
- if (_paths.remove(entryPath)) removedPaths.add(entryPath);
+ if (entry.isExplicit) paths.add(p.join(root, entryPath));
+
recurse(entry, entryPath);
});
}
- recurse(dir, root);
- return removedPaths;
+ recurse(dir, dirPath);
+ return paths;
}
/// Returns whether [this] contains [path].
///
/// This only returns true for paths explicitly added to [this].
/// Implicitly-added directories can be inspected using [containsDir].
- bool contains(String path) => _paths.contains(_normalize(path));
+ bool contains(String path) {
+ path = _normalize(path);
+ var entry = _entries;
+
+ for (var part in p.split(path)) {
+ entry = entry.contents[part];
+ if (entry == null) return false;
+ }
+
+ return entry.isExplicit;
+ }
/// Returns whether [this] contains paths beneath [path].
bool containsDir(String path) {
path = _normalize(path);
- var dir = _entries;
+ var entry = _entries;
- for (var part in _split(path)) {
- dir = dir[part];
- if (dir == null) return false;
+ for (var part in p.split(path)) {
+ entry = entry.contents[part];
+ if (entry == null) return false;
}
- return !dir.isEmpty;
+ return !entry.contents.isEmpty;
}
- /// Returns a [Set] of all paths in [this].
- Set<String> toSet() => _paths.toSet();
+ /// All of the paths explicitly added to this set.
+ List<String> get paths {
+ var result = <String>[];
+
+ recurse(dir, path) {
+ for (var name in dir.contents.keys) {
+ var entry = dir.contents[name];
+ var entryPath = p.join(path, name);
+ if (entry.isExplicit) result.add(entryPath);
+ recurse(entry, entryPath);
+ }
+ }
+
+ recurse(_entries, root);
+ return result;
+ }
/// Removes all paths from [this].
void clear() {
- _paths.clear();
- _entries.clear();
+ _entries.contents.clear();
}
- String toString() => _paths.toString();
-
/// Returns a normalized version of [path].
///
/// This removes any extra ".." or "."s and ensure that the returned path
/// begins with [root]. It's an error if [path] isn't within [root].
String _normalize(String path) {
- var relative = p.relative(p.normalize(path), from: root);
- var parts = p.split(relative);
- // TODO(nweiz): replace this with [p.isWithin] when that exists (issue
- // 14980).
- if (!p.isRelative(relative) || parts.first == '..' || parts.first == '.') {
- throw new ArgumentError('Path "$path" is not inside "$root".');
- }
- return p.join(root, relative);
+ assert(p.isWithin(root, path));
+
+ return p.relative(p.normalize(path), from: root);
}
+}
- /// Returns the segments of [path] beneath [root].
- List<String> _split(String path) => p.split(p.relative(path, from: root));
+/// A virtual file system entity tracked by the [PathSet].
+///
+/// It may have child entries in [contents], which implies it's a directory.
+class _Entry {
+ /// The child entries contained in this directory.
+ final Map<String, _Entry> contents = {};
+
+ /// If this entry was explicitly added as a leaf file system entity, this
+ /// will be true.
+ ///
+ /// Otherwise, it represents a parent directory that was implicitly added
+ /// when added some child of it.
+ bool isExplicit = false;
}
« no previous file with comments | « packages/watcher/lib/src/file_watcher/polling.dart ('k') | packages/watcher/lib/src/resubscribable.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698