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

Unified Diff: utils/pub/package.dart

Issue 10214006: Refactor command code and add support for --help and --version. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 8 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
Index: utils/pub/package.dart
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index 2942a92c67c1c4ec2af1a8a65d3b9b276d722f72..7a6a71b39797d709b757ac2a54da003fc6d1d360 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -5,7 +5,23 @@
/**
* A named, versioned, unit of code and resource reuse.
*/
-class Package {
+class Package implements Hashable {
+ /**
+ * Loads the package whose root directory is [packageDir].
+ */
+ static Future<Package> load(String packageDir) {
+ final pubspecPath = join(packageDir, 'pubspec');
+
+ return _parsePubspec(pubspecPath).transform((dependencies) {
+ return new Package._(packageDir, dependencies);
+ });
+ }
+
+ /**
+ * The path to the directory containing the package.
+ */
+ final String dir;
+
/**
* The name of the package.
*/
@@ -20,20 +36,93 @@ class Package {
final Collection<String> dependencies;
/**
- * The cache where this package is contained.
+ * Constructs a package. This should not be called directly. Instead, acquire
+ * packages from [load()].
*/
- final PackageCache _cache;
+ Package._(String dir, this.dependencies)
+ : dir = dir,
+ name = basename(dir);
/**
- * Constructs a package. This should not be called directly. Instead, acquire
- * packages from [PackageCache].
+ * Reads and returns all of the packages this package immediately depends on.
+ */
+ Future<Collection<Package>> loadDependencies(PackageCache cache) {
+ return Futures.wait(dependencies.map((name) => cache.find(name)));
+ }
+
+ /**
+ * Walks the entire dependency graph starting at this package and returns a
+ * [Set] of all of the packages dependend on by this one, directly or
+ * indirectly. This package is included in the result set.
+ */
+ Future<Set<Package>> traverseDependencies(PackageCache cache) {
+ final completer = new Completer<Set<Package>>();
+ final packages = new Set<Package>();
+
+ var pendingAsyncCalls = 0;
+
+ walkPackage(Package package) {
+ // Skip packages we've already traversed.
+ if (packages.contains(package)) return;
+
+ // Add the package.
+ packages.add(package);
+
+ // Recurse into its dependencies.
+ pendingAsyncCalls++;
+ package.loadDependencies(cache).then((dependencies) {
+ for (final dependency in dependencies) {
+ walkPackage(dependency);
+ }
+
+ pendingAsyncCalls--;
+ if (pendingAsyncCalls == 0) completer.complete(packages);
+ });
+ }
+
+ walkPackage(this);
+
+ return completer.future;
+ }
+
+ /**
+ * Generates a hashcode for the package.
+ */
+ int hashCode() => name.hashCode();
+
+ /**
+ * Returns a debug string for the package.
*/
- Package._(this._cache, this.name, this.dependencies);
+ String toString() => '$name ($dir)';
/**
- * Reads and returns all of the packages this package depends on.
+ * Parses the pubspec at the given path and returns the list of package
+ * dependencies it exposes.
*/
- Future<Collection<Package>> readDependencies() {
- return Futures.wait(dependencies.map((name) => _cache.find(name)));
+ static Future<List<String>> _parsePubspec(String path) {
+ final completer = new Completer<List<String>>();
+
+ // TODO(rnystrom): Handle the directory not existing.
+ // TODO(rnystrom): Error-handling.
+ final readFuture = readTextFile(path);
+ readFuture.handleException((error) {
+ // If there is no pubspec, we implicitly treat that as a package with no
+ // dependencies.
+ // TODO(rnystrom): Distinguish file not found from other real errors.
+ completer.complete(<String>[]);
+ return true;
+ });
+
+ readFuture.then((pubspec) {
+ // TODO(rnystrom): Use YAML parser when ready. For now, it's just a flat
+ // list of newline-separated strings.
+ final dependencyNames = pubspec.split('\n').
+ map((name) => name.trim()).
+ filter((name) => (name != null) && (name != ''));
+
+ completer.complete(dependencyNames);
+ });
+
+ return completer.future;
}
}

Powered by Google App Engine
This is Rietveld 408576698