OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 library pub.solver.solve_report; | |
6 | |
7 import '../lock_file.dart'; | |
8 import '../log.dart' as log; | |
9 import '../package.dart'; | |
10 import '../source_registry.dart'; | |
11 import '../utils.dart'; | |
12 import 'version_solver.dart'; | |
13 | |
14 /// Generates and displays nicely formatted reports for the results of running | |
15 /// a version resolution. | |
16 class SolveReport { | |
nweiz
2013/12/11 06:48:32
At first glance the fact that this is different th
Bob Nystrom
2013/12/11 22:36:59
Added some more docs clarifying.
nweiz
2013/12/11 23:31:27
I do. Exporting a class instead of a function impl
Bob Nystrom
2013/12/12 00:14:58
Done.
| |
17 final SourceRegistry _sources; | |
18 final Package _root; | |
19 final LockFile _previousLockFile; | |
20 final SolveResult _result; | |
21 | |
22 /// The dependencies in [_result], keyed by package name. | |
23 final _dependencies = new Map<String, PackageId>(); | |
24 | |
25 final _output = new StringBuffer(); | |
26 | |
27 /// To avoid emitting trailing newlines, we track if any are needed and only | |
28 /// emit then when text on the next line is about to be written. | |
29 int _pendingLines = 0; | |
nweiz
2013/12/11 06:48:32
This is pretty general behavior. It would be nice
Bob Nystrom
2013/12/11 22:36:59
Added a TODO. I like the idea, but I can't come up
nweiz
2013/12/11 23:31:27
I'm not a big fan of the philosophy of "postpone t
| |
30 | |
31 SolveReport(this._sources, this._root, this._previousLockFile, this._result) { | |
32 // Fill the map so we can use it later. | |
33 for (var id in _result.packages) { | |
34 _dependencies[id.name] = id; | |
35 } | |
36 } | |
37 | |
38 /// Displays a report of the results of the version resolution relative to | |
39 /// the previous lock file. | |
40 /// | |
41 /// If [showAll] is true, then all of the previous and current dependencies | |
42 /// are shown and their changes relative to the previous lock file are | |
43 /// highlighted. Otherwise, only overrides are shown. | |
44 /// | |
45 /// Returns the number of changed dependencies. | |
46 int show({bool showAll}) { | |
47 if (showAll) _reportChanges(); | |
48 _reportOverrides(); | |
49 | |
50 // Count how many dependencies actually changed. | |
51 var dependencies = _dependencies.keys.toSet(); | |
52 dependencies.addAll(_previousLockFile.packages.keys); | |
53 dependencies.remove(_root.name); | |
54 | |
55 return dependencies.where((name) { | |
56 var oldId = _previousLockFile.packages[name]; | |
57 var newId = _dependencies[name]; | |
58 | |
59 // Added or removed dependencies count. | |
60 if (oldId == null) return true; | |
61 if (newId == null) return true; | |
62 | |
63 // The dependency existed before, so see if it was modified. | |
64 return !_descriptionsEqual(oldId, newId) || | |
65 oldId.version != newId.version; | |
66 }).length; | |
67 } | |
68 | |
69 /// Displays a report of all of the previous and current dependencies and | |
70 /// how they have changed. | |
71 void _reportChanges() { | |
72 _output.clear(); | |
nweiz
2013/12/11 06:48:32
Clearing and writing to a StringBuffer instance va
Bob Nystrom
2013/12/11 22:36:59
It's a bit gross to me too, but this class's reaso
| |
73 | |
74 // Show the current dependencies ordered by name. | |
nweiz
2013/12/11 06:48:32
"current" -> "new"
Bob Nystrom
2013/12/11 22:36:59
I used "current" here because "new" could mean "de
nweiz
2013/12/11 23:31:27
"current" is confusing because it's not clear whic
Bob Nystrom
2013/12/12 00:14:58
Done.
| |
75 var names = _result.packages.map((id) => id.name).toList(); | |
76 names.remove(_root.name); | |
77 names.sort(); | |
78 names.forEach(_reportPackage); | |
79 | |
80 // Show any removed ones. | |
81 var removed = _previousLockFile.packages.keys.toSet(); | |
82 removed.removeAll(names); | |
83 if (removed.isNotEmpty) { | |
84 _writeln("These packages are no longer being depended on:"); | |
85 removed = removed.toList(); | |
86 removed.sort(); | |
87 removed.forEach(_reportPackage); | |
88 } | |
89 | |
90 log.message(_output.toString()); | |
91 } | |
92 | |
93 /// Displays a warning about the overrides currently in effect. | |
94 void _reportOverrides() { | |
95 _output.clear(); | |
96 | |
97 if (_result.overrides.isNotEmpty) { | |
98 _writeln("Warning: You are using these overridden dependencies:"); | |
99 var overrides = _result.overrides.map((dep) => dep.name).toList(); | |
100 overrides.sort((a, b) => a.compareTo(b)); | |
101 | |
102 overrides.forEach( | |
103 (name) => _reportPackage(name, highlightOverride: false)); | |
104 | |
105 log.warning(_output.toString()); | |
106 } | |
107 } | |
108 | |
109 /// Reports the results of the upgrade on the package named [name]. | |
110 /// | |
111 /// If [highlightOverride] is true (or absent), writes "(override)" next to | |
112 /// overridden packages. | |
113 void _reportPackage(String name, {bool highlightOverride}) { | |
114 if (highlightOverride == null) highlightOverride = true; | |
nweiz
2013/12/11 06:48:32
Blah blah explicit default.
Bob Nystrom
2013/12/11 22:36:59
Previous comment.
| |
115 | |
116 var newId = _dependencies[name]; | |
117 var oldId = _previousLockFile.packages[name]; | |
118 var id = newId != null ? newId : oldId; | |
119 | |
120 var isOverridden = _result.overrides.map( | |
121 (dep) => dep.name).contains(id.name); | |
122 | |
123 var changed = false; | |
124 | |
125 // Show a one-character "icon" describing the change. They are: | |
126 // | |
127 // ! The package is being overridden. | |
128 // - The package was removed. | |
129 // + The package was added. | |
130 // > The package was upgraded from a lower version. | |
131 // < The package was downgraded from a higher version. | |
132 // * Any other change between the old and new package. | |
133 if (isOverridden) { | |
134 _write(log.magenta("! ")); | |
135 } else if (newId == null) { | |
136 _write(log.red("- ")); | |
137 } else if (oldId == null) { | |
138 _write(log.green("+ ")); | |
139 } else if (!_descriptionsEqual(oldId, newId)) { | |
140 _write(log.cyan("* ")); | |
nweiz
2013/12/11 06:48:32
For colorblind folks like myself, it might be nice
Bob Nystrom
2013/12/11 22:36:59
Added a bunch of docs to the color functions in lo
| |
141 changed = true; | |
142 } else if (oldId.version < newId.version) { | |
143 _write(log.green("> ")); | |
144 changed = true; | |
145 } else if (oldId.version > newId.version) { | |
146 _write(log.cyan("< ")); | |
147 changed = true; | |
148 } else { | |
149 // Unchanged. | |
150 _write(" "); | |
151 } | |
152 | |
153 // If the package was upgraded, show what it was upgraded from. | |
nweiz
2013/12/11 06:48:32
This comment should be on the next block.
Bob Nystrom
2013/12/11 22:36:59
Done.
| |
154 _write(log.bold(id.name)); | |
155 _write(" "); | |
156 _writeId(id); | |
157 | |
158 if (changed) { | |
159 _write(" (was "); | |
160 _writeId(oldId); | |
161 _write(")"); | |
162 } | |
163 | |
164 // Highlight overridden packages. | |
165 if (isOverridden && highlightOverride) { | |
166 _write(" ${log.magenta('(overridden)')}"); | |
167 } | |
168 | |
169 // See if there are any newer versions of the package that we were | |
170 // unable to upgrade to. | |
171 if (newId != null) { | |
172 var versions = _result.availableVersions[newId.name]; | |
173 var newerStable = 0; | |
174 var newerUnstable = 0; | |
175 | |
176 for (var version in versions) { | |
177 if (version > newId.version) { | |
178 if (version.isPreRelease) { | |
179 newerUnstable++; | |
180 } else { | |
181 newerStable++; | |
182 } | |
183 } | |
184 } | |
185 | |
186 // If there are newer stable versions, only show those. | |
187 var message; | |
188 if (newerStable > 0) { | |
189 message = "($newerStable newer " | |
190 "${pluralize('version', newerStable)} available)"; | |
191 } else if (newerUnstable > 0) { | |
192 message = "($newerUnstable newer unstable " | |
193 "${pluralize('version', newerUnstable)} available)"; | |
194 } | |
195 | |
196 if (message != null) _write(" ${log.cyan(message)}"); | |
197 } | |
198 | |
199 _writeln(); | |
200 } | |
201 | |
202 /// Returns `true` if [a] and [b] are from the same source and have the same | |
203 /// description. | |
204 bool _descriptionsEqual(PackageId a, PackageId b) { | |
205 if (a.source != b.source) return false; | |
206 | |
207 if (_sources.contains(a.source)) { | |
208 var source = _sources[a.source]; | |
209 return source.descriptionsEqual(a.description, b.description); | |
210 } else { | |
211 // Unknown source, so just do a literal comparison. | |
nweiz
2013/12/11 06:48:32
If it's an unknown source there's no way the versi
Bob Nystrom
2013/12/11 22:36:59
I added a TODO elsewhere for this. What I want to
| |
212 return a.description == b.description; | |
213 } | |
214 } | |
215 | |
216 /// Writes a terse description of [id] (not including its name) to the output. | |
217 void _writeId(PackageId id) { | |
218 _write(id.version); | |
219 | |
220 var source = null; | |
221 if (_sources.contains(id.source)) { | |
222 source = _sources[id.source]; | |
223 } | |
224 | |
225 if (source != null && source != _sources.defaultSource) { | |
226 var description = source.formatDescription(_root.dir, id.description); | |
227 _write(" from ${id.source} $description"); | |
228 } | |
229 } | |
230 | |
231 /// Writes [obj] to the output. | |
232 void _write(Object obj) { | |
233 while (_pendingLines > 0) { | |
234 _output.writeln(); | |
235 _pendingLines--; | |
236 } | |
237 _output.write(obj); | |
238 } | |
239 | |
240 /// Writes [obj] (if not null) followed by a newline to the output. | |
241 /// | |
242 /// Doesn't actually immediately write. Instead, it waits until output is | |
nweiz
2013/12/11 06:48:32
"immediately write a newline".
Bob Nystrom
2013/12/11 22:36:59
Done.
| |
243 /// written on the nextline. That way, trailing newlines aren't displayed. | |
nweiz
2013/12/11 06:48:32
"next line"
Bob Nystrom
2013/12/11 22:36:59
Done.
| |
244 void _writeln([Object obj]) { | |
245 if (obj != null) _write(obj); | |
246 _pendingLines++; | |
247 } | |
248 } | |
OLD | NEW |