| 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;
|
| + }
|
| +}
|
|
|