| 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 /** | 5 /** |
| 6 * Attempts to resolve a set of version constraints for a package dependency | 6 * Attempts to resolve a set of version constraints for a package dependency |
| 7 * graph and select an appropriate set of best specific versions for all | 7 * graph and select an appropriate set of best specific versions for all |
| 8 * dependent packages. It works iteratively and tries to reach a stable | 8 * dependent packages. It works iteratively and tries to reach a stable |
| 9 * solution where the constraints of all dependencies are met. If it fails to | 9 * solution where the constraints of all dependencies are met. If it fails to |
| 10 * reach a solution after a certain number of iterations, it assumes the | 10 * reach a solution after a certain number of iterations, it assumes the |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 * picked version for that package may fall outside of the new constraint. If | 33 * picked version for that package may fall outside of the new constraint. If |
| 34 * that happens, we find the new best version that meets the updated constraint | 34 * that happens, we find the new best version that meets the updated constraint |
| 35 * and then the change the package to use that version. That cycles back up to | 35 * and then the change the package to use that version. That cycles back up to |
| 36 * the beginning again. | 36 * the beginning again. |
| 37 */ | 37 */ |
| 38 library version_solver; | 38 library version_solver; |
| 39 | 39 |
| 40 import 'dart:json'; | 40 import 'dart:json'; |
| 41 import 'dart:math'; | 41 import 'dart:math'; |
| 42 import 'lock_file.dart'; | 42 import 'lock_file.dart'; |
| 43 import 'log.dart' as log; | |
| 44 import 'package.dart'; | 43 import 'package.dart'; |
| 45 import 'pubspec.dart'; | 44 import 'pubspec.dart'; |
| 46 import 'root_source.dart'; | 45 import 'root_source.dart'; |
| 47 import 'source.dart'; | 46 import 'source.dart'; |
| 48 import 'source_registry.dart'; | 47 import 'source_registry.dart'; |
| 49 import 'utils.dart'; | 48 import 'utils.dart'; |
| 50 import 'version.dart'; | 49 import 'version.dart'; |
| 51 | 50 |
| 52 /** | 51 /** |
| 53 * Attempts to select the best concrete versions for all of the transitive | 52 * Attempts to select the best concrete versions for all of the transitive |
| 54 * dependencies of [root] taking into account all of the [VersionConstraint]s | 53 * dependencies of [root] taking into account all of the [VersionConstraint]s |
| 55 * that those dependencies place on each other and the requirements imposed by | 54 * that those dependencies place on each other and the requirements imposed by |
| 56 * [lockFile]. If successful, completes to a [Map] that maps package names to | 55 * [lockFile]. If successful, completes to a [Map] that maps package names to |
| 57 * the selected version for that package. If it fails, the future will complete | 56 * the selected version for that package. If it fails, the future will complete |
| 58 * with a [NoVersionException], [DisjointConstraintException], or | 57 * with a [NoVersionException], [DisjointConstraintException], or |
| 59 * [CouldNotSolveException]. | 58 * [CouldNotSolveException]. |
| 60 */ | 59 */ |
| 61 Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root, | 60 Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root, |
| 62 LockFile lockFile) { | 61 LockFile lockFile) { |
| 63 log.message('Resolving dependencies...'); | 62 print('Resolving dependencies...'); |
| 64 return new VersionSolver(sources, root, lockFile).solve(); | 63 return new VersionSolver(sources, root, lockFile).solve(); |
| 65 } | 64 } |
| 66 | 65 |
| 67 class VersionSolver { | 66 class VersionSolver { |
| 68 final SourceRegistry _sources; | 67 final SourceRegistry _sources; |
| 69 final Package _root; | 68 final Package _root; |
| 70 final LockFile lockFile; | 69 final LockFile lockFile; |
| 71 final PubspecCache _pubspecs; | 70 final PubspecCache _pubspecs; |
| 72 final Map<String, Dependency> _packages; | 71 final Map<String, Dependency> _packages; |
| 73 final Queue<WorkItem> _work; | 72 final Queue<WorkItem> _work; |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 /** | 260 /** |
| 262 * The new selected version. | 261 * The new selected version. |
| 263 */ | 262 */ |
| 264 final Version version; | 263 final Version version; |
| 265 | 264 |
| 266 ChangeVersion(this.package, this.source, this.description, this.version) { | 265 ChangeVersion(this.package, this.source, this.description, this.version) { |
| 267 if (source == null) throw "null source"; | 266 if (source == null) throw "null source"; |
| 268 } | 267 } |
| 269 | 268 |
| 270 Future process(VersionSolver solver) { | 269 Future process(VersionSolver solver) { |
| 271 log.fine("Changing $package to version $version."); | |
| 272 | |
| 273 var dependency = solver.getDependency(package); | 270 var dependency = solver.getDependency(package); |
| 274 var oldVersion = dependency.version; | 271 var oldVersion = dependency.version; |
| 275 solver.setVersion(package, version); | 272 solver.setVersion(package, version); |
| 276 | 273 |
| 277 // The dependencies between the old and new version may be different. Walk | 274 // The dependencies between the old and new version may be different. Walk |
| 278 // them both and update any constraints that differ between the two. | 275 // them both and update any constraints that differ between the two. |
| 279 return Futures.wait([ | 276 return Futures.wait([ |
| 280 getDependencyRefs(solver, oldVersion), | 277 getDependencyRefs(solver, oldVersion), |
| 281 getDependencyRefs(solver, version)]).transform((list) { | 278 getDependencyRefs(solver, version)]).transform((list) { |
| 282 var oldDependencyRefs = list[0]; | 279 var oldDependencyRefs = list[0]; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 /** | 411 /** |
| 415 * The package being depended on and the constraints being placed on it. The | 412 * The package being depended on and the constraints being placed on it. The |
| 416 * source, version, and description in this ref are all considered constraints | 413 * source, version, and description in this ref are all considered constraints |
| 417 * on the dependent package. | 414 * on the dependent package. |
| 418 */ | 415 */ |
| 419 final PackageRef ref; | 416 final PackageRef ref; |
| 420 | 417 |
| 421 AddConstraint(this.depender, this.ref); | 418 AddConstraint(this.depender, this.ref); |
| 422 | 419 |
| 423 Future process(VersionSolver solver) { | 420 Future process(VersionSolver solver) { |
| 424 log.fine("Adding $depender's constraint $ref."); | |
| 425 | |
| 426 var dependency = solver.getDependency(ref.name); | 421 var dependency = solver.getDependency(ref.name); |
| 427 var oldDependency = dependency.clone(); | 422 var oldDependency = dependency.clone(); |
| 428 dependency.placeConstraint(depender, ref); | 423 dependency.placeConstraint(depender, ref); |
| 429 return _processChange(solver, oldDependency, dependency); | 424 return _processChange(solver, oldDependency, dependency); |
| 430 } | 425 } |
| 431 | 426 |
| 432 void undo(VersionSolver solver) { | 427 void undo(VersionSolver solver) { |
| 433 solver.getDependency(ref.name).removeConstraint(depender); | 428 solver.getDependency(ref.name).removeConstraint(depender); |
| 434 } | 429 } |
| 435 } | 430 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 447 * The package that was being depended on. | 442 * The package that was being depended on. |
| 448 */ | 443 */ |
| 449 String dependent; | 444 String dependent; |
| 450 | 445 |
| 451 /** The constraint that was removed. */ | 446 /** The constraint that was removed. */ |
| 452 PackageRef _removed; | 447 PackageRef _removed; |
| 453 | 448 |
| 454 RemoveConstraint(this.depender, this.dependent); | 449 RemoveConstraint(this.depender, this.dependent); |
| 455 | 450 |
| 456 Future process(VersionSolver solver) { | 451 Future process(VersionSolver solver) { |
| 457 log.fine("Removing $depender's constraint ($_removed) on $dependent."); | |
| 458 | |
| 459 var dependency = solver.getDependency(dependent); | 452 var dependency = solver.getDependency(dependent); |
| 460 var oldDependency = dependency.clone(); | 453 var oldDependency = dependency.clone(); |
| 461 _removed = dependency.removeConstraint(depender); | 454 _removed = dependency.removeConstraint(depender); |
| 462 return _processChange(solver, oldDependency, dependency); | 455 return _processChange(solver, oldDependency, dependency); |
| 463 } | 456 } |
| 464 | 457 |
| 465 void undo(VersionSolver solver) { | 458 void undo(VersionSolver solver) { |
| 466 solver.getDependency(dependent).placeConstraint(depender, _removed); | 459 solver.getDependency(dependent).placeConstraint(depender, _removed); |
| 467 } | 460 } |
| 468 } | 461 } |
| 469 | 462 |
| 470 /** [package]'s version is no longer constrained by the lockfile. */ | 463 /** [package]'s version is no longer constrained by the lockfile. */ |
| 471 class UnlockPackage implements WorkItem { | 464 class UnlockPackage implements WorkItem { |
| 472 /** The package being unlocked. */ | 465 /** The package being unlocked. */ |
| 473 Dependency package; | 466 Dependency package; |
| 474 | 467 |
| 475 UnlockPackage(this.package); | 468 UnlockPackage(this.package); |
| 476 | 469 |
| 477 Future process(VersionSolver solver) { | 470 Future process(VersionSolver solver) { |
| 478 log.fine("Unlocking ${package.name}."); | |
| 479 | |
| 480 solver.lockFile.packages.remove(package.name); | 471 solver.lockFile.packages.remove(package.name); |
| 481 return solver.getBestVersion(package).transform((best) { | 472 return solver.getBestVersion(package).transform((best) { |
| 482 if (best == null) return null; | 473 if (best == null) return null; |
| 483 solver.enqueue(new ChangeVersion( | 474 solver.enqueue(new ChangeVersion( |
| 484 package.name, package.source, package.description, best)); | 475 package.name, package.source, package.description, best)); |
| 485 }); | 476 }); |
| 486 } | 477 } |
| 487 } | 478 } |
| 488 | 479 |
| 489 // TODO(rnystrom): Instead of always pulling from the source (which will mean | 480 // TODO(rnystrom): Instead of always pulling from the source (which will mean |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 | 765 |
| 775 String toString() { | 766 String toString() { |
| 776 // TODO(nweiz): Dump descriptions to YAML when that's supported. | 767 // TODO(nweiz): Dump descriptions to YAML when that's supported. |
| 777 return "Incompatible dependencies on '$package':\n" | 768 return "Incompatible dependencies on '$package':\n" |
| 778 "- '$depender1' depends on it with description " | 769 "- '$depender1' depends on it with description " |
| 779 "${JSON.stringify(description1)}\n" | 770 "${JSON.stringify(description1)}\n" |
| 780 "- '$depender2' depends on it with description " | 771 "- '$depender2' depends on it with description " |
| 781 "${JSON.stringify(description2)}"; | 772 "${JSON.stringify(description2)}"; |
| 782 } | 773 } |
| 783 } | 774 } |
| OLD | NEW |