Chromium Code Reviews| Index: sdk/lib/_internal/pub/lib/src/solver/version_solver.dart |
| diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart |
| index 6ac4aad5513ee2aed95501249761406ba679c942..26aeb13666d38b84c5594168e86a978899586563 100644 |
| --- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart |
| +++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart |
| @@ -116,19 +116,19 @@ class PubspecCache { |
| /// The number of times a version list was requested and it wasn't cached and |
| /// had to be requested from the source. |
| - int versionCacheMisses = 0; |
| + int _versionCacheMisses = 0; |
| /// The number of times a version list was requested and the cached version |
| /// was returned. |
| - int versionCacheHits = 0; |
| + int _versionCacheHits = 0; |
| /// The number of times a pubspec was requested and it wasn't cached and had |
| /// to be requested from the source. |
| - int pubspecCacheMisses = 0; |
| + int _pubspecCacheMisses = 0; |
| /// The number of times a pubspec was requested and the cached version was |
| /// returned. |
| - int pubspecCacheHits = 0; |
| + int _pubspecCacheHits = 0; |
| PubspecCache(this._sources); |
| @@ -141,11 +141,11 @@ class PubspecCache { |
| Future<Pubspec> getPubspec(PackageId id) { |
| // Complete immediately if it's already cached. |
| if (_pubspecs.containsKey(id)) { |
| - pubspecCacheHits++; |
| + _pubspecCacheHits++; |
| return new Future<Pubspec>.value(_pubspecs[id]); |
| } |
| - pubspecCacheMisses++; |
| + _pubspecCacheMisses++; |
| var source = _sources[id.source]; |
| return source.describe(id).then((pubspec) { |
| @@ -172,11 +172,10 @@ class PubspecCache { |
| // See if we have it cached. |
| var versions = _versions[package]; |
| if (versions != null) { |
| - versionCacheHits++; |
| + _versionCacheHits++; |
| return new Future.value(versions); |
| } |
| - |
| - versionCacheMisses++; |
| + _versionCacheMisses++; |
| var source = _sources[package.source]; |
| return source.getVersions(package.name, package.description) |
| @@ -194,6 +193,50 @@ class PubspecCache { |
| /// Returns the previously cached list of versions for the package identified |
| /// by [package] or returns `null` if not in the cache. |
| List<PackageId> getCachedVersions(PackageRef package) => _versions[package]; |
| + |
| + /// Writes some metrics about the solve to [buffer]. |
| + void writeResults(StringBuffer buffer) { |
| + buffer.writeln( |
| + '- Requested $_versionCacheMisses version lists'); |
| + buffer.writeln( |
| + '- Looked up $_versionCacheHits cached version lists'); |
| + buffer.writeln( |
| + '- Requested $_pubspecCacheMisses pubspecs'); |
| + buffer.writeln( |
| + '- Looked up $_pubspecCacheHits cached pubspecs'); |
| + |
| + // Uncomment this to dump the visited package graph to JSON. |
| + // _debugWritePackageGraph(buffer); |
|
nweiz
2014/04/21 21:38:49
Rather than commenting this out, maybe hide it beh
Bob Nystrom
2014/04/21 22:58:32
It's not quite ready for prime-time. I slapped it
|
| + } |
| + |
| + /// This dumps the set of packages that were looked at by the solver to a |
| + /// JSON map whose format matches the map passed to [testResolve] in the |
| + /// version solver unit tests. |
| + /// |
| + /// If a real-world version solve is failing, this can be used to mirror that |
| + /// data to build a regression test using mock packages. |
| + void _debugWritePackageGraph(StringBuffer buffer) { |
| + var packages = {}; |
| + _pubspecs.forEach((id, pubspec) { |
| + var deps = {}; |
| + packages["${id.name} ${id.version}"] = deps; |
| + |
| + for (var dep in pubspec.dependencies) { |
| + deps[dep.name] = dep.constraint.toString(); |
| + } |
| + }); |
| + |
| + // Add in the packages that we know of but didn't need their pubspecs. |
| + _versions.forEach((ref, versions) { |
| + for (var id in versions) { |
| + packages.putIfAbsent("${id.name} ${id.version}", () => {}); |
| + } |
| + }); |
| + |
| + // TODO(rnystrom): Include dev dependencies and dependency overrides. |
| + |
| + buffer.writeln(JSON.encode(packages)); |
| + } |
| } |
| /// A reference from a depending package to a package that it depends on. |
| @@ -201,12 +244,17 @@ class Dependency { |
| /// The name of the package that has this dependency. |
| final String depender; |
| + /// The version of the depender that has this dependency. |
| + /// |
| + /// This will be `null` when [depender] is the magic "pub itself" dependency. |
| + final Version dependerVersion; |
| + |
| /// The package being depended on. |
| final PackageDep dep; |
| - Dependency(this.depender, this.dep); |
| + Dependency(this.depender, this.dependerVersion, this.dep); |
| - String toString() => '$depender -> $dep'; |
| + String toString() => '$depender $dependerVersion -> $dep'; |
| } |
| /// Base class for all failures that can occur while trying to resolve versions. |
| @@ -238,16 +286,16 @@ abstract class SolveFailure implements ApplicationException { |
| var buffer = new StringBuffer(); |
| buffer.write("$_message:"); |
| - var map = {}; |
| - for (var dep in dependencies) { |
| - map[dep.depender] = dep.dep; |
| - } |
| + var sorted = dependencies.toList(); |
| + sorted.sort((a, b) => a.depender.compareTo(b.depender)); |
| - var names = ordered(map.keys); |
| - |
| - for (var name in names) { |
| + for (var dep in sorted) { |
| buffer.writeln(); |
| - buffer.write("- $name ${_describeDependency(map[name])}"); |
| + buffer.write("- ${log.bold(dep.depender)}"); |
| + if (dep.dependerVersion != null) { |
| + buffer.write(" ${dep.dependerVersion}"); |
| + } |
| + buffer.write(" ${_describeDependency(dep.dep)}"); |
| } |
| return buffer.toString(); |
| @@ -275,12 +323,27 @@ class BadSdkVersionException extends SolveFailure { |
| class NoVersionException extends SolveFailure { |
| final VersionConstraint constraint; |
| - NoVersionException(String package, this.constraint, |
| + /// The last selected version of the package that failed to meet the new |
| + /// constraint. |
| + /// |
| + /// This will be `null` when the failure occurred because there are no |
| + /// versions of the package *at all* that match the constraint. It will be |
| + /// non-`null` when a version was selected, but then the solver tightened a |
| + /// constraint such that that version was no longer allowed. |
| + final Version version; |
| + |
| + NoVersionException(String package, this.version, this.constraint, |
| Iterable<Dependency> dependencies) |
| : super(package, dependencies); |
| - String get _message => "Package $package has no versions that match " |
| - "$constraint derived from"; |
| + String get _message { |
| + if (version == null) { |
| + return "Package $package has no versions that match $constraint derived " |
| + "from"; |
| + } |
| + |
| + return "Package $package $version does not match $constraint derived from"; |
| + } |
| } |
| // TODO(rnystrom): Report the list of depending packages and their constraints. |