Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 version_solver; | 5 library version_solver; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:json' as json; | 8 import 'dart:json' as json; |
| 9 | 9 |
| 10 import '../lock_file.dart'; | 10 import '../lock_file.dart'; |
| 11 import '../log.dart' as log; | 11 import '../log.dart' as log; |
| 12 import '../package.dart'; | 12 import '../package.dart'; |
| 13 import '../pubspec.dart'; | 13 import '../pubspec.dart'; |
| 14 import '../sdk.dart' as sdk; | |
| 14 import '../source.dart'; | 15 import '../source.dart'; |
| 15 import '../source_registry.dart'; | 16 import '../source_registry.dart'; |
| 16 import '../version.dart'; | 17 import '../version.dart'; |
| 17 import 'backtracking_solver.dart'; | 18 import 'backtracking_solver.dart'; |
| 18 import 'greedy_solver.dart'; | 19 import 'greedy_solver.dart'; |
| 19 | 20 |
| 20 /// Attempts to select the best concrete versions for all of the transitive | 21 /// Attempts to select the best concrete versions for all of the transitive |
| 21 /// dependencies of [root] taking into account all of the [VersionConstraint]s | 22 /// dependencies of [root] taking into account all of the [VersionConstraint]s |
| 22 /// that those dependencies place on each other and the requirements imposed by | 23 /// that those dependencies place on each other and the requirements imposed by |
| 23 /// [lockFile]. | 24 /// [lockFile]. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 39 var solver; | 40 var solver; |
| 40 if (allowBacktracking) { | 41 if (allowBacktracking) { |
| 41 solver = new BacktrackingVersionSolver(sources, root, lockFile, useLatest); | 42 solver = new BacktrackingVersionSolver(sources, root, lockFile, useLatest); |
| 42 } else { | 43 } else { |
| 43 solver = new GreedyVersionSolver(sources, root, lockFile, useLatest); | 44 solver = new GreedyVersionSolver(sources, root, lockFile, useLatest); |
| 44 } | 45 } |
| 45 | 46 |
| 46 return solver.solve(); | 47 return solver.solve(); |
| 47 } | 48 } |
| 48 | 49 |
| 50 /// Ensures that if [pubspec] has an SDK constraint, then it is compatible | |
| 51 /// with the current SDK. Throws a [SolverFailure] if not. | |
| 52 void validateSdkConstraint(Pubspec pubspec) { | |
|
nweiz
2013/04/16 23:52:32
It seems really weird that this is a top-level, pu
Bob Nystrom
2013/04/17 17:28:44
It was being used by both VersionSolver and Backtr
| |
| 53 if (pubspec.environment.sdkVersion.allows(sdk.version)) return; | |
| 54 | |
| 55 throw new CouldNotSolveException( | |
| 56 'Package "{pubspec.name} requires SDK version ' | |
| 57 '${pubspec.environment.sdkVersion} but the current SDK is ' | |
| 58 '${sdk.version}.'); | |
| 59 } | |
| 60 | |
| 49 /// Base class for an implementation of the version constraint solver. | 61 /// Base class for an implementation of the version constraint solver. |
| 50 class VersionSolver { | 62 class VersionSolver { |
| 51 final SourceRegistry sources; | 63 final SourceRegistry sources; |
| 52 final Package root; | 64 final Package root; |
| 53 final LockFile lockFile; | 65 final LockFile lockFile; |
| 54 final PubspecCache cache; | 66 final PubspecCache cache; |
| 55 | 67 |
| 56 VersionSolver(SourceRegistry sources, this.root, this.lockFile, | 68 VersionSolver(SourceRegistry sources, this.root, this.lockFile, |
| 57 List<String> useLatest) | 69 List<String> useLatest) |
| 58 : sources = sources, | 70 : sources = sources, |
| 59 cache = new PubspecCache(sources) { | 71 cache = new PubspecCache(sources) { |
| 60 for (var package in useLatest) { | 72 for (var package in useLatest) { |
| 61 forceLatestVersion(package); | 73 forceLatestVersion(package); |
| 62 lockFile.packages.remove(package); | 74 lockFile.packages.remove(package); |
| 63 } | 75 } |
| 64 } | 76 } |
| 65 | 77 |
| 66 /// The number of solutions the solver has tried so far. | 78 /// The number of solutions the solver has tried so far. |
| 67 int get attemptedSolutions; | 79 int get attemptedSolutions; |
| 68 | 80 |
| 69 /// Force the solver to upgrade [package] to the latest available version. | 81 /// Force the solver to upgrade [package] to the latest available version. |
| 70 void forceLatestVersion(String package); | 82 void forceLatestVersion(String package); |
| 71 | 83 |
| 72 /// Run the solver. Completes with a list of specific package versions if | 84 /// Run the solver. Completes with a list of specific package versions if |
| 73 /// successful or an error if it failed to find a solution. | 85 /// successful or an error if it failed to find a solution. |
| 74 Future<SolveResult> solve() { | 86 Future<SolveResult> solve() { |
| 75 var stopwatch = new Stopwatch(); | 87 var stopwatch = new Stopwatch(); |
| 76 stopwatch.start(); | |
| 77 | 88 |
| 78 // Pre-cache the root package's known pubspec. | 89 return new Future(() { |
| 79 cache.cache(new PackageId.root(root), root.pubspec); | 90 stopwatch.start(); |
| 80 | 91 |
| 81 return runSolver().then((packages) { | 92 // Pre-cache the root package's known pubspec. |
| 93 cache.cache(new PackageId.root(root), root.pubspec); | |
| 94 | |
| 95 validateSdkConstraint(root.pubspec); | |
| 96 return runSolver(); | |
| 97 }).then((packages) { | |
| 82 return new SolveResult(packages, null, attemptedSolutions); | 98 return new SolveResult(packages, null, attemptedSolutions); |
| 83 }).catchError((error) { | 99 }).catchError((error) { |
| 84 if (error is! SolveFailure) throw error; | 100 if (error is! SolveFailure) throw error; |
| 85 | 101 |
| 86 // Wrap a failure in a result so we can attach some other data. | 102 // Wrap a failure in a result so we can attach some other data. |
| 87 return new SolveResult(null, error, attemptedSolutions); | 103 return new SolveResult(null, error, attemptedSolutions); |
| 88 }).whenComplete(() { | 104 }).whenComplete(() { |
| 89 // Gather some solving metrics. | 105 // Gather some solving metrics. |
| 90 var buffer = new StringBuffer(); | 106 var buffer = new StringBuffer(); |
| 91 buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.'); | 107 buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.'); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 | 313 |
| 298 /// Describes a dependencie's reference in the output message. Override this | 314 /// Describes a dependencie's reference in the output message. Override this |
| 299 /// to highlight which aspect of [ref] led to the failure. | 315 /// to highlight which aspect of [ref] led to the failure. |
| 300 String _describeDependency(PackageRef ref) => | 316 String _describeDependency(PackageRef ref) => |
| 301 "depends on version ${ref.constraint}"; | 317 "depends on version ${ref.constraint}"; |
| 302 } | 318 } |
| 303 | 319 |
| 304 /// Exception thrown when the [VersionSolver] fails to find a solution after a | 320 /// Exception thrown when the [VersionSolver] fails to find a solution after a |
| 305 /// certain number of iterations. | 321 /// certain number of iterations. |
| 306 class CouldNotSolveException extends SolveFailure { | 322 class CouldNotSolveException extends SolveFailure { |
| 307 CouldNotSolveException() | 323 CouldNotSolveException([String message]) |
| 308 : super(null, null); | 324 : super(null, null), |
| 325 _message = (message != null) ? message : | |
| 326 "Could not find a solution that met all constraints."; | |
| 309 | 327 |
| 310 /// A message describing the specific kind of solve failure. | 328 /// A message describing the specific kind of solve failure. |
| 311 String get _message => | 329 final String _message; |
| 312 "Could not find a solution that met all constraints."; | |
| 313 } | 330 } |
| 314 | 331 |
| 315 /// Exception thrown when the [VersionConstraint] used to match a package is | 332 /// Exception thrown when the [VersionConstraint] used to match a package is |
| 316 /// valid (i.e. non-empty), but there are no available versions of the package | 333 /// valid (i.e. non-empty), but there are no available versions of the package |
| 317 /// that fit that constraint. | 334 /// that fit that constraint. |
| 318 class NoVersionException extends SolveFailure { | 335 class NoVersionException extends SolveFailure { |
| 319 final VersionConstraint constraint; | 336 final VersionConstraint constraint; |
| 320 | 337 |
| 321 NoVersionException(String package, this.constraint, | 338 NoVersionException(String package, this.constraint, |
| 322 Iterable<Dependency> dependencies) | 339 Iterable<Dependency> dependencies) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 Iterable<Dependency> dependencies) | 387 Iterable<Dependency> dependencies) |
| 371 : super(package, dependencies); | 388 : super(package, dependencies); |
| 372 | 389 |
| 373 String get _message => "Incompatible dependencies on '$package'"; | 390 String get _message => "Incompatible dependencies on '$package'"; |
| 374 | 391 |
| 375 String _describeDependency(PackageRef ref) { | 392 String _describeDependency(PackageRef ref) { |
| 376 // TODO(nweiz): Dump descriptions to YAML when that's supported. | 393 // TODO(nweiz): Dump descriptions to YAML when that's supported. |
| 377 return "depends on it with description ${json.stringify(ref.description)}"; | 394 return "depends on it with description ${json.stringify(ref.description)}"; |
| 378 } | 395 } |
| 379 } | 396 } |
| OLD | NEW |