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

Unified Diff: sdk/lib/_internal/pub/lib/src/command/deps.dart

Issue 217343004: Add a "pub dependencies" command. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Revise. Created 6 years, 9 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: sdk/lib/_internal/pub/lib/src/command/deps.dart
diff --git a/sdk/lib/_internal/pub/lib/src/command/deps.dart b/sdk/lib/_internal/pub/lib/src/command/deps.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a5e267bbd77a8f5b61202428e066ecae55262b4d
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/command/deps.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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 pub.command.list;
+
+import 'dart:async';
+import 'dart:collection';
+
+import '../ascii_tree.dart' as tree;
+import '../command.dart';
+import '../log.dart' as log;
+import '../package.dart';
+import '../package_graph.dart';
+import '../utils.dart';
+
+/// Handles the `deps` pub command.
+class DepsCommand extends PubCommand {
+ String get description => "Print package dependencies.";
+ List<String> get aliases => const ["dependencies", "tab"];
+ String get usage => "pub deps";
+
+ DepsCommand() {
+ commandParser.addOption("style", abbr: "s",
+ help: "How output should be displayed.",
+ allowed: ["compact", "tree", "list"],
+ defaultsTo: "tree");
+ }
+
+ Future onRun() {
+ return entrypoint.loadPackageGraph().then((graph) {
+ var buffer = new StringBuffer();
+
+ buffer.writeln(_labelPackage(entrypoint.root));
+
+ switch (commandOptions["style"]) {
+ case "compact": _outputCompact(graph, buffer); break;
+ case "list": _outputList(graph, buffer); break;
+ case "tree": _outputTree(graph, buffer); break;
+ }
+
+ log.message(buffer);
+ });
+ }
+
+ /// Outputs a list of all of the package's immediate, dev, override, and
+ /// transitive dependencies.
+ ///
+ /// For each dependency listed, *that* package's immediate dependencies are
+ /// shown. Unlike [_outputList], this prints all of these dependencies on one
+ /// line.
+ void _outputCompact(PackageGraph graph, StringBuffer buffer) {
+ outputPackages(String section, Iterable<String> names) {
+ if (names.isEmpty) return;
+
+ buffer.writeln();
+ buffer.writeln("$section:");
+ for (var name in ordered(names)) {
+ var package = graph.packages[name];
+
+ buffer.write("- ${_labelPackage(package)}");
+ if (package.dependencies.isEmpty) {
+ buffer.writeln();
+ } else {
+ var depNames = package.dependencies.map((dep) => dep.name);
+ var depsList = "[${depNames.join(' ')}]";
+ buffer.writeln(" ${log.gray(depsList)}");
+ }
+ }
+ }
+
+ var root = entrypoint.root;
+ outputPackages("dependencies", root.dependencies.map((dep) => dep.name));
+ outputPackages("dev dependencies",
+ root.devDependencies.map((dep) => dep.name));
+ outputPackages("dependency overrides",
+ root.dependencyOverrides.map((dep) => dep.name));
+
+ var transitive = _getTransitiveDependencies(graph);
+ outputPackages("transitive dependencies", transitive);
+ }
+
+ /// Outputs a list of all of the package's immediate, dev, override, and
+ /// transitive dependencies.
+ ///
+ /// For each dependency listed, *that* package's immediate dependencies are
+ /// shown.
+ void _outputList(PackageGraph graph, StringBuffer buffer) {
+ outputDeps(Iterable<PackageDep> deps) {
+ for (var dep in deps) {
+ buffer.writeln(" - ${log.bold(dep.name)} ${log.gray(dep.constraint)}");
+ }
+ }
+
+ outputPackages(Iterable<String> names) {
+ for (var name in names) {
+ var package = graph.packages[name];
+ buffer.writeln("- ${_labelPackage(package)}");
+
+ outputDeps(package.dependencies);
+ }
+ }
+
+ outputSection(String name, Iterable<String> deps) {
+ if (deps.isEmpty) return;
+
+ buffer.writeln();
+ buffer.writeln("$name:");
+ outputPackages(deps);
+ }
+
+ var root = entrypoint.root;
+ outputSection("dependencies",
+ root.dependencies.map((dep) => dep.name));
+ outputSection("dev dependencies",
+ root.devDependencies.map((dep) => dep.name));
+ outputSection("dependency overrides",
+ root.dependencyOverrides.map((dep) => dep.name));
+
+ var transitive = _getTransitiveDependencies(graph);
+ if (transitive.isEmpty) return;
+
+ outputSection("transitive dependencies", ordered(transitive));
+ }
+
+ /// Generates a dependency tree for the root package.
+ ///
+ /// If a package is encountered more than once (i.e. a shared or circular
+ /// dependency), later ones are not traversed. This is done in breadth-first
+ /// fashion so that a package will always be expanded at the shallowest
+ /// depth that it appears at.
+ void _outputTree(PackageGraph graph, StringBuffer buffer) {
+ // The work list for the breadth-first traversal. It contains the package
+ // being added to the tree, and the parent map that will receive that
+ // package.
+ var toWalk = new Queue<Pair<Package, Map>>();
+ var visited = new Set<String>();
+
+ // Start with the root dependencies.
+ var packageTree = {};
+ for (var dep in entrypoint.root.immediateDependencies) {
+ toWalk.add(new Pair(graph.packages[dep.name], packageTree));
+ }
+
+ // Do a breadth-first walk to the dependency graph.
+ while (toWalk.isNotEmpty) {
+ var pair = toWalk.removeFirst();
+ var package = pair.first;
+ var map = pair.last;
+
+ if (visited.contains(package.name)) {
+ map[log.gray('${package.name}...')] = {};
+ continue;
+ }
+
+ visited.add(package.name);
+
+ // Populate the map with this package's dependencies.
+ var childMap = {};
+ map[_labelPackage(package)] = childMap;
+
+ for (var dep in package.dependencies) {
+ toWalk.add(new Pair(graph.packages[dep.name], childMap));
+ }
+ }
+
+ buffer.write(tree.fromMap(packageTree, showAllChildren: true));
+ }
+
+ String _labelPackage(Package package) =>
+ "${log.bold(package.name)} ${package.version}";
+
+ /// Gets the names of the non-immediate dependencies of the root package.
+ Set<String> _getTransitiveDependencies(PackageGraph graph) {
+ var transitive = graph.packages.keys.toSet();
+ var root = entrypoint.root;
+ transitive.remove(root.name);
+ transitive.removeAll(root.dependencies.map((dep) => dep.name));
+ transitive.removeAll(root.devDependencies.map((dep) => dep.name));
+ transitive.removeAll(root.dependencyOverrides.map((dep) => dep.name));
+ return transitive;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698