Chromium Code Reviews| 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'; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 _outputCompactPackages("transitive dependencies", transitive); | 67 _outputCompactPackages("transitive dependencies", transitive); |
| 68 } | 68 } |
| 69 | 69 |
| 70 /// Outputs one section of packages in the compact output. | 70 /// Outputs one section of packages in the compact output. |
| 71 _outputCompactPackages(String section, Iterable<String> names) { | 71 _outputCompactPackages(String section, Iterable<String> names) { |
| 72 if (names.isEmpty) return; | 72 if (names.isEmpty) return; |
| 73 | 73 |
| 74 _buffer.writeln(); | 74 _buffer.writeln(); |
| 75 _buffer.writeln("$section:"); | 75 _buffer.writeln("$section:"); |
| 76 for (var name in ordered(names)) { | 76 for (var name in ordered(names)) { |
| 77 var package = entrypoint.packageGraph.packages[name]; | 77 var package = _getPackage(name); |
| 78 | 78 |
| 79 _buffer.write("- ${_labelPackage(package)}"); | 79 _buffer.write("- ${_labelPackage(package)}"); |
| 80 if (package.dependencies.isEmpty) { | 80 if (package.dependencies.isEmpty) { |
| 81 _buffer.writeln(); | 81 _buffer.writeln(); |
| 82 } else { | 82 } else { |
| 83 var depNames = package.dependencies.map((dep) => dep.name); | 83 var depNames = package.dependencies.map((dep) => dep.name); |
| 84 var depsList = "[${depNames.join(' ')}]"; | 84 var depsList = "[${depNames.join(' ')}]"; |
| 85 _buffer.writeln(" ${log.gray(depsList)}"); | 85 _buffer.writeln(" ${log.gray(depsList)}"); |
| 86 } | 86 } |
| 87 } | 87 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 108 } | 108 } |
| 109 | 109 |
| 110 /// Outputs one section of packages in the list output. | 110 /// Outputs one section of packages in the list output. |
| 111 _outputListSection(String name, Iterable<String> deps) { | 111 _outputListSection(String name, Iterable<String> deps) { |
| 112 if (deps.isEmpty) return; | 112 if (deps.isEmpty) return; |
| 113 | 113 |
| 114 _buffer.writeln(); | 114 _buffer.writeln(); |
| 115 _buffer.writeln("$name:"); | 115 _buffer.writeln("$name:"); |
| 116 | 116 |
| 117 for (var name in deps) { | 117 for (var name in deps) { |
| 118 var package = entrypoint.packageGraph.packages[name]; | 118 var package = _getPackage(name); |
| 119 _buffer.writeln("- ${_labelPackage(package)}"); | 119 _buffer.writeln("- ${_labelPackage(package)}"); |
| 120 | 120 |
| 121 for (var dep in package.dependencies) { | 121 for (var dep in package.dependencies) { |
| 122 _buffer.writeln( | 122 _buffer.writeln( |
| 123 " - ${log.bold(dep.name)} ${log.gray(dep.constraint)}"); | 123 " - ${log.bold(dep.name)} ${log.gray(dep.constraint)}"); |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 /// Generates a dependency tree for the root package. | 128 /// Generates a dependency tree for the root package. |
| 129 /// | 129 /// |
| 130 /// If a package is encountered more than once (i.e. a shared or circular | 130 /// If a package is encountered more than once (i.e. a shared or circular |
| 131 /// dependency), later ones are not traversed. This is done in breadth-first | 131 /// dependency), later ones are not traversed. This is done in breadth-first |
| 132 /// fashion so that a package will always be expanded at the shallowest | 132 /// fashion so that a package will always be expanded at the shallowest |
| 133 /// depth that it appears at. | 133 /// depth that it appears at. |
| 134 void _outputTree() { | 134 void _outputTree() { |
| 135 // The work list for the breadth-first traversal. It contains the package | 135 // 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 | 136 // being added to the tree, and the parent map that will receive that |
| 137 // package. | 137 // package. |
| 138 var toWalk = new Queue<Pair<Package, Map>>(); | 138 var toWalk = new Queue<Pair<Package, Map>>(); |
| 139 var visited = new Set<String>.from([entrypoint.root.name]); | 139 var visited = new Set<String>.from([entrypoint.root.name]); |
| 140 | 140 |
| 141 // Start with the root dependencies. | 141 // Start with the root dependencies. |
| 142 var packageTree = {}; | 142 var packageTree = {}; |
| 143 for (var dep in entrypoint.root.immediateDependencies) { | 143 for (var dep in entrypoint.root.immediateDependencies) { |
| 144 toWalk.add( | 144 toWalk.add(new Pair(_getPackage(dep.name), packageTree)); |
| 145 new Pair(entrypoint.packageGraph.packages[dep.name], packageTree)); | |
| 146 } | 145 } |
| 147 | 146 |
| 148 // Do a breadth-first walk to the dependency graph. | 147 // Do a breadth-first walk to the dependency graph. |
| 149 while (toWalk.isNotEmpty) { | 148 while (toWalk.isNotEmpty) { |
| 150 var pair = toWalk.removeFirst(); | 149 var pair = toWalk.removeFirst(); |
| 151 var package = pair.first; | 150 var package = pair.first; |
| 152 var map = pair.last; | 151 var map = pair.last; |
| 153 | 152 |
| 154 if (visited.contains(package.name)) { | 153 if (visited.contains(package.name)) { |
| 155 map[log.gray('${package.name}...')] = {}; | 154 map[log.gray('${package.name}...')] = {}; |
| 156 continue; | 155 continue; |
| 157 } | 156 } |
| 158 | 157 |
| 159 visited.add(package.name); | 158 visited.add(package.name); |
| 160 | 159 |
| 161 // Populate the map with this package's dependencies. | 160 // Populate the map with this package's dependencies. |
| 162 var childMap = {}; | 161 var childMap = {}; |
| 163 map[_labelPackage(package)] = childMap; | 162 map[_labelPackage(package)] = childMap; |
| 164 | 163 |
| 165 for (var dep in package.dependencies) { | 164 for (var dep in package.dependencies) { |
| 166 toWalk.add( | 165 toWalk.add(new Pair(_getPackage(dep.name), childMap)); |
| 167 new Pair(entrypoint.packageGraph.packages[dep.name], childMap)); | |
| 168 } | 166 } |
| 169 } | 167 } |
| 170 | 168 |
| 171 _buffer.write(tree.fromMap(packageTree, showAllChildren: true)); | 169 _buffer.write(tree.fromMap(packageTree, showAllChildren: true)); |
| 172 } | 170 } |
| 173 | 171 |
| 174 String _labelPackage(Package package) => | 172 String _labelPackage(Package package) => |
| 175 "${log.bold(package.name)} ${package.version}"; | 173 "${log.bold(package.name)} ${package.version}"; |
| 176 | 174 |
| 177 /// Gets the names of the non-immediate dependencies of the root package. | 175 /// Gets the names of the non-immediate dependencies of the root package. |
| 178 Set<String> _getTransitiveDependencies() { | 176 Set<String> _getTransitiveDependencies() { |
| 179 var transitive = entrypoint.packageGraph.packages.keys.toSet(); | 177 var transitive = entrypoint.packageGraph.packages.keys.toSet(); |
| 180 var root = entrypoint.root; | 178 var root = entrypoint.root; |
| 181 transitive.remove(root.name); | 179 transitive.remove(root.name); |
| 182 transitive.removeAll(root.dependencies.map((dep) => dep.name)); | 180 transitive.removeAll(root.dependencies.map((dep) => dep.name)); |
| 183 transitive.removeAll(root.devDependencies.map((dep) => dep.name)); | 181 transitive.removeAll(root.devDependencies.map((dep) => dep.name)); |
| 184 transitive.removeAll(root.dependencyOverrides.map((dep) => dep.name)); | 182 transitive.removeAll(root.dependencyOverrides.map((dep) => dep.name)); |
| 185 return transitive; | 183 return transitive; |
| 186 } | 184 } |
| 185 | |
| 186 /// Get the package named [name], or throw a [DataError] if it's not | |
| 187 /// avaialble. | |
|
Bob Nystrom
2015/08/31 19:32:21
"available"
nweiz
2015/08/31 20:41:29
Done.
| |
| 188 /// | |
| 189 /// 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 | |
| 191 /// check can return a false negative. This fails gracefully if that happens. | |
| 192 Package _getPackage(String name) { | |
| 193 var package = entrypoint.packageGraph.packages[name]; | |
| 194 if (package != null) return package; | |
| 195 dataError('The pubspec.yaml file has changed since the pubspec.lock file ' | |
| 196 'was generated, please run "pub get" again.'); | |
| 197 } | |
| 187 } | 198 } |
| OLD | NEW |