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 |