| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library pub.command.list; | 5 library pub.command.list; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import '../ascii_tree.dart' as tree; | 9 import '../ascii_tree.dart' as tree; |
| 10 import '../command.dart'; | 10 import '../command.dart'; |
| 11 import '../log.dart' as log; | 11 import '../log.dart' as log; |
| 12 import '../package.dart'; | 12 import '../package.dart'; |
| 13 import '../utils.dart'; | 13 import '../utils.dart'; |
| 14 | 14 |
| 15 /// Handles the `deps` pub command. | 15 /// Handles the `deps` pub command. |
| 16 class DepsCommand extends PubCommand { | 16 class DepsCommand extends PubCommand { |
| 17 String get name => "deps"; | 17 String get name => "deps"; |
| 18 String get description => "Print package dependencies."; | 18 String get description => "Print package dependencies."; |
| 19 List<String> get aliases => const ["dependencies", "tab"]; | 19 List<String> get aliases => const ["dependencies", "tab"]; |
| 20 String get invocation => "pub deps"; | 20 String get invocation => "pub deps"; |
| 21 String get docUrl => "http://dartlang.org/tools/pub/cmd/pub-deps.html"; | 21 String get docUrl => "http://dartlang.org/tools/pub/cmd/pub-deps.html"; |
| 22 bool get takesArguments => false; | 22 bool get takesArguments => false; |
| 23 | 23 |
| 24 /// The [StringBuffer] used to accumulate the output. | 24 /// The [StringBuffer] used to accumulate the output. |
| 25 StringBuffer _buffer; | 25 StringBuffer _buffer; |
| 26 | 26 |
| 27 /// Whether to include dev dependencies. |
| 28 bool get _includeDev => argResults['dev']; |
| 29 |
| 27 DepsCommand() { | 30 DepsCommand() { |
| 28 argParser.addOption("style", abbr: "s", | 31 argParser.addOption("style", abbr: "s", |
| 29 help: "How output should be displayed.", | 32 help: "How output should be displayed.", |
| 30 allowed: ["compact", "tree", "list"], | 33 allowed: ["compact", "tree", "list"], |
| 31 defaultsTo: "tree"); | 34 defaultsTo: "tree"); |
| 35 |
| 36 argParser.addFlag("dev", negatable: true, |
| 37 help: "Whether to include dev dependencies.", |
| 38 defaultsTo: true); |
| 32 } | 39 } |
| 33 | 40 |
| 34 void run() { | 41 void run() { |
| 35 // Explicitly run this in case we don't access `entrypoint.packageGraph`. | 42 // Explicitly run this in case we don't access `entrypoint.packageGraph`. |
| 36 entrypoint.assertUpToDate(); | 43 entrypoint.assertUpToDate(); |
| 37 | 44 |
| 38 _buffer = new StringBuffer(); | 45 _buffer = new StringBuffer(); |
| 39 | 46 |
| 40 _buffer.writeln(_labelPackage(entrypoint.root)); | 47 _buffer.writeln(_labelPackage(entrypoint.root)); |
| 41 | 48 |
| 42 switch (argResults["style"]) { | 49 switch (argResults["style"]) { |
| 43 case "compact": _outputCompact(); break; | 50 case "compact": _outputCompact(); break; |
| 44 case "list": _outputList(); break; | 51 case "list": _outputList(); break; |
| 45 case "tree": _outputTree(); break; | 52 case "tree": _outputTree(); break; |
| 46 } | 53 } |
| 47 | 54 |
| 48 log.message(_buffer); | 55 log.message(_buffer); |
| 49 } | 56 } |
| 50 | 57 |
| 51 /// Outputs a list of all of the package's immediate, dev, override, and | 58 /// Outputs a list of all of the package's immediate, dev, override, and |
| 52 /// transitive dependencies. | 59 /// transitive dependencies. |
| 53 /// | 60 /// |
| 54 /// For each dependency listed, *that* package's immediate dependencies are | 61 /// For each dependency listed, *that* package's immediate dependencies are |
| 55 /// shown. Unlike [_outputList], this prints all of these dependencies on one | 62 /// shown. Unlike [_outputList], this prints all of these dependencies on one |
| 56 /// line. | 63 /// line. |
| 57 void _outputCompact() { | 64 void _outputCompact() { |
| 58 var root = entrypoint.root; | 65 var root = entrypoint.root; |
| 59 _outputCompactPackages("dependencies", | 66 _outputCompactPackages("dependencies", |
| 60 root.dependencies.map((dep) => dep.name)); | 67 root.dependencies.map((dep) => dep.name)); |
| 61 _outputCompactPackages("dev dependencies", | 68 if (_includeDev) { |
| 62 root.devDependencies.map((dep) => dep.name)); | 69 _outputCompactPackages("dev dependencies", |
| 70 root.devDependencies.map((dep) => dep.name)); |
| 71 } |
| 63 _outputCompactPackages("dependency overrides", | 72 _outputCompactPackages("dependency overrides", |
| 64 root.dependencyOverrides.map((dep) => dep.name)); | 73 root.dependencyOverrides.map((dep) => dep.name)); |
| 65 | 74 |
| 66 var transitive = _getTransitiveDependencies(); | 75 var transitive = _getTransitiveDependencies(); |
| 67 _outputCompactPackages("transitive dependencies", transitive); | 76 _outputCompactPackages("transitive dependencies", transitive); |
| 68 } | 77 } |
| 69 | 78 |
| 70 /// Outputs one section of packages in the compact output. | 79 /// Outputs one section of packages in the compact output. |
| 71 _outputCompactPackages(String section, Iterable<String> names) { | 80 _outputCompactPackages(String section, Iterable<String> names) { |
| 72 if (names.isEmpty) return; | 81 if (names.isEmpty) return; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 89 | 98 |
| 90 /// Outputs a list of all of the package's immediate, dev, override, and | 99 /// Outputs a list of all of the package's immediate, dev, override, and |
| 91 /// transitive dependencies. | 100 /// transitive dependencies. |
| 92 /// | 101 /// |
| 93 /// For each dependency listed, *that* package's immediate dependencies are | 102 /// For each dependency listed, *that* package's immediate dependencies are |
| 94 /// shown. | 103 /// shown. |
| 95 void _outputList() { | 104 void _outputList() { |
| 96 var root = entrypoint.root; | 105 var root = entrypoint.root; |
| 97 _outputListSection("dependencies", | 106 _outputListSection("dependencies", |
| 98 root.dependencies.map((dep) => dep.name)); | 107 root.dependencies.map((dep) => dep.name)); |
| 99 _outputListSection("dev dependencies", | 108 if (_includeDev) { |
| 100 root.devDependencies.map((dep) => dep.name)); | 109 _outputListSection("dev dependencies", |
| 110 root.devDependencies.map((dep) => dep.name)); |
| 111 } |
| 101 _outputListSection("dependency overrides", | 112 _outputListSection("dependency overrides", |
| 102 root.dependencyOverrides.map((dep) => dep.name)); | 113 root.dependencyOverrides.map((dep) => dep.name)); |
| 103 | 114 |
| 104 var transitive = _getTransitiveDependencies(); | 115 var transitive = _getTransitiveDependencies(); |
| 105 if (transitive.isEmpty) return; | 116 if (transitive.isEmpty) return; |
| 106 | 117 |
| 107 _outputListSection("transitive dependencies", ordered(transitive)); | 118 _outputListSection("transitive dependencies", ordered(transitive)); |
| 108 } | 119 } |
| 109 | 120 |
| 110 /// Outputs one section of packages in the list output. | 121 /// Outputs one section of packages in the list output. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 133 /// depth that it appears at. | 144 /// depth that it appears at. |
| 134 void _outputTree() { | 145 void _outputTree() { |
| 135 // The work list for the breadth-first traversal. It contains the package | 146 // The work list for the breadth-first traversal. It contains the package |
| 136 // being added to the tree, and the parent map that will receive that | 147 // being added to the tree, and the parent map that will receive that |
| 137 // package. | 148 // package. |
| 138 var toWalk = new Queue<Pair<Package, Map>>(); | 149 var toWalk = new Queue<Pair<Package, Map>>(); |
| 139 var visited = new Set<String>.from([entrypoint.root.name]); | 150 var visited = new Set<String>.from([entrypoint.root.name]); |
| 140 | 151 |
| 141 // Start with the root dependencies. | 152 // Start with the root dependencies. |
| 142 var packageTree = {}; | 153 var packageTree = {}; |
| 143 for (var dep in entrypoint.root.immediateDependencies) { | 154 var immediateDependencies = entrypoint.root.immediateDependencies.toSet(); |
| 155 if (!_includeDev) { |
| 156 immediateDependencies.removeAll(entrypoint.root.devDependencies); |
| 157 } |
| 158 for (var dep in immediateDependenciesr) { |
| 144 toWalk.add(new Pair(_getPackage(dep.name), packageTree)); | 159 toWalk.add(new Pair(_getPackage(dep.name), packageTree)); |
| 145 } | 160 } |
| 146 | 161 |
| 147 // Do a breadth-first walk to the dependency graph. | 162 // Do a breadth-first walk to the dependency graph. |
| 148 while (toWalk.isNotEmpty) { | 163 while (toWalk.isNotEmpty) { |
| 149 var pair = toWalk.removeFirst(); | 164 var pair = toWalk.removeFirst(); |
| 150 var package = pair.first; | 165 var package = pair.first; |
| 151 var map = pair.last; | 166 var map = pair.last; |
| 152 | 167 |
| 153 if (visited.contains(package.name)) { | 168 if (visited.contains(package.name)) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 167 } | 182 } |
| 168 | 183 |
| 169 _buffer.write(tree.fromMap(packageTree, showAllChildren: true)); | 184 _buffer.write(tree.fromMap(packageTree, showAllChildren: true)); |
| 170 } | 185 } |
| 171 | 186 |
| 172 String _labelPackage(Package package) => | 187 String _labelPackage(Package package) => |
| 173 "${log.bold(package.name)} ${package.version}"; | 188 "${log.bold(package.name)} ${package.version}"; |
| 174 | 189 |
| 175 /// Gets the names of the non-immediate dependencies of the root package. | 190 /// Gets the names of the non-immediate dependencies of the root package. |
| 176 Set<String> _getTransitiveDependencies() { | 191 Set<String> _getTransitiveDependencies() { |
| 177 var transitive = entrypoint.packageGraph.packages.keys.toSet(); | 192 var transitive = _getAllDependencies(); |
| 178 var root = entrypoint.root; | 193 var root = entrypoint.root; |
| 179 transitive.remove(root.name); | 194 transitive.remove(root.name); |
| 180 transitive.removeAll(root.dependencies.map((dep) => dep.name)); | 195 transitive.removeAll(root.dependencies.map((dep) => dep.name)); |
| 181 transitive.removeAll(root.devDependencies.map((dep) => dep.name)); | 196 if (_includeDev) { |
| 197 transitive.removeAll(root.devDependencies.map((dep) => dep.name)); |
| 198 } |
| 182 transitive.removeAll(root.dependencyOverrides.map((dep) => dep.name)); | 199 transitive.removeAll(root.dependencyOverrides.map((dep) => dep.name)); |
| 183 return transitive; | 200 return transitive; |
| 184 } | 201 } |
| 185 | 202 |
| 203 Set<String> _getAllDependencies() { |
| 204 if (_includeDev) return entrypoint.packageGraph.packages.keys.toSet(); |
| 205 |
| 206 var nonDevDependencies = entrypoint.root.dependencies.toList() |
| 207 ..addAll(entrypoint.root.dependencyOverrides); |
| 208 return nonDevDependencies |
| 209 .expand((dep) => |
| 210 entrypoint.packageGraph.transitiveDependencies(dep.name)) |
| 211 .map((package) => package.name) |
| 212 .toSet(); |
| 213 } |
| 214 |
| 186 /// Get the package named [name], or throw a [DataError] if it's not | 215 /// Get the package named [name], or throw a [DataError] if it's not |
| 187 /// available. | 216 /// available. |
| 188 /// | 217 /// |
| 189 /// It's very unlikely that the lockfile won't be up-to-date with the pubspec, | 218 /// It's very unlikely that the lockfile won't be up-to-date with the pubspec, |
| 190 /// but it's possible, since [Entrypoint.assertUpToDate]'s modification time | 219 /// but it's possible, since [Entrypoint.assertUpToDate]'s modification time |
| 191 /// check can return a false negative. This fails gracefully if that happens. | 220 /// check can return a false negative. This fails gracefully if that happens. |
| 192 Package _getPackage(String name) { | 221 Package _getPackage(String name) { |
| 193 var package = entrypoint.packageGraph.packages[name]; | 222 var package = entrypoint.packageGraph.packages[name]; |
| 194 if (package != null) return package; | 223 if (package != null) return package; |
| 195 dataError('The pubspec.yaml file has changed since the pubspec.lock file ' | 224 dataError('The pubspec.yaml file has changed since the pubspec.lock file ' |
| 196 'was generated, please run "pub get" again.'); | 225 'was generated, please run "pub get" again.'); |
| 197 } | 226 } |
| 198 } | 227 } |
| OLD | NEW |