Chromium Code Reviews| 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 |