| 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 | 
|---|