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; | |
43 import 'package.dart'; | 44 import 'package.dart'; |
44 import 'pubspec.dart'; | 45 import 'pubspec.dart'; |
45 import 'root_source.dart'; | 46 import 'root_source.dart'; |
46 import 'source.dart'; | 47 import 'source.dart'; |
47 import 'source_registry.dart'; | 48 import 'source_registry.dart'; |
48 import 'utils.dart'; | 49 import 'utils.dart'; |
49 import 'version.dart'; | 50 import 'version.dart'; |
50 | 51 |
51 /** | 52 /** |
52 * Attempts to select the best concrete versions for all of the transitive | 53 * Attempts to select the best concrete versions for all of the transitive |
53 * dependencies of [root] taking into account all of the [VersionConstraint]s | 54 * dependencies of [root] taking into account all of the [VersionConstraint]s |
54 * that those dependencies place on each other and the requirements imposed by | 55 * that those dependencies place on each other and the requirements imposed by |
55 * [lockFile]. If successful, completes to a [Map] that maps package names to | 56 * [lockFile]. If successful, completes to a [Map] that maps package names to |
56 * the selected version for that package. If it fails, the future will complete | 57 * the selected version for that package. If it fails, the future will complete |
57 * with a [NoVersionException], [DisjointConstraintException], or | 58 * with a [NoVersionException], [DisjointConstraintException], or |
58 * [CouldNotSolveException]. | 59 * [CouldNotSolveException]. |
59 */ | 60 */ |
60 Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root, | 61 Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root, |
61 LockFile lockFile) { | 62 LockFile lockFile) { |
62 print('Resolving dependencies...'); | 63 log.message('Resolving dependencies...'); |
63 return new VersionSolver(sources, root, lockFile).solve(); | 64 return new VersionSolver(sources, root, lockFile).solve(); |
64 } | 65 } |
65 | 66 |
66 class VersionSolver { | 67 class VersionSolver { |
67 final SourceRegistry _sources; | 68 final SourceRegistry _sources; |
68 final Package _root; | 69 final Package _root; |
69 final LockFile lockFile; | 70 final LockFile lockFile; |
70 final PubspecCache _pubspecs; | 71 final PubspecCache _pubspecs; |
71 final Map<String, Dependency> _packages; | 72 final Map<String, Dependency> _packages; |
72 final Queue<WorkItem> _work; | 73 final Queue<WorkItem> _work; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 /** | 260 /** |
260 * The new selected version. | 261 * The new selected version. |
261 */ | 262 */ |
262 final Version version; | 263 final Version version; |
263 | 264 |
264 ChangeVersion(this.package, this.source, this.description, this.version) { | 265 ChangeVersion(this.package, this.source, this.description, this.version) { |
265 if (source == null) throw "null source"; | 266 if (source == null) throw "null source"; |
266 } | 267 } |
267 | 268 |
268 Future process(VersionSolver solver) { | 269 Future process(VersionSolver solver) { |
270 log.fine("Changing $package to version $version."); | |
271 | |
269 var dependency = solver.getDependency(package); | 272 var dependency = solver.getDependency(package); |
270 var oldVersion = dependency.version; | 273 var oldVersion = dependency.version; |
271 solver.setVersion(package, version); | 274 solver.setVersion(package, version); |
272 | 275 |
273 // The dependencies between the old and new version may be different. Walk | 276 // The dependencies between the old and new version may be different. Walk |
274 // them both and update any constraints that differ between the two. | 277 // them both and update any constraints that differ between the two. |
275 return Futures.wait([ | 278 return Futures.wait([ |
276 getDependencyRefs(solver, oldVersion), | 279 getDependencyRefs(solver, oldVersion), |
277 getDependencyRefs(solver, version)]).transform((list) { | 280 getDependencyRefs(solver, version)]).transform((list) { |
278 var oldDependencyRefs = list[0]; | 281 var oldDependencyRefs = list[0]; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 /** | 413 /** |
411 * The package being depended on and the constraints being placed on it. The | 414 * The package being depended on and the constraints being placed on it. The |
412 * source, version, and description in this ref are all considered constraints | 415 * source, version, and description in this ref are all considered constraints |
413 * on the dependent package. | 416 * on the dependent package. |
414 */ | 417 */ |
415 final PackageRef ref; | 418 final PackageRef ref; |
416 | 419 |
417 AddConstraint(this.depender, this.ref); | 420 AddConstraint(this.depender, this.ref); |
418 | 421 |
419 Future process(VersionSolver solver) { | 422 Future process(VersionSolver solver) { |
423 log.fine("Adding $depender's constraint $ref."); | |
424 | |
420 var dependency = solver.getDependency(ref.name); | 425 var dependency = solver.getDependency(ref.name); |
421 var oldDependency = dependency.clone(); | 426 var oldDependency = dependency.clone(); |
422 dependency.placeConstraint(depender, ref); | 427 dependency.placeConstraint(depender, ref); |
423 return _processChange(solver, oldDependency, dependency); | 428 return _processChange(solver, oldDependency, dependency); |
424 } | 429 } |
425 | 430 |
426 void undo(VersionSolver solver) { | 431 void undo(VersionSolver solver) { |
427 solver.getDependency(ref.name).removeConstraint(depender); | 432 solver.getDependency(ref.name).removeConstraint(depender); |
428 } | 433 } |
429 } | 434 } |
(...skipping 11 matching lines...) Expand all Loading... | |
441 * The package that was being depended on. | 446 * The package that was being depended on. |
442 */ | 447 */ |
443 String dependent; | 448 String dependent; |
444 | 449 |
445 /** The constraint that was removed. */ | 450 /** The constraint that was removed. */ |
446 PackageRef _removed; | 451 PackageRef _removed; |
447 | 452 |
448 RemoveConstraint(this.depender, this.dependent); | 453 RemoveConstraint(this.depender, this.dependent); |
449 | 454 |
450 Future process(VersionSolver solver) { | 455 Future process(VersionSolver solver) { |
456 log.fine("Removing $depender's constraint on $dependent."); | |
nweiz
2012/12/05 23:56:54
Log what the removed constraint was.
Bob Nystrom
2012/12/06 01:33:26
Done.
| |
457 | |
451 var dependency = solver.getDependency(dependent); | 458 var dependency = solver.getDependency(dependent); |
452 var oldDependency = dependency.clone(); | 459 var oldDependency = dependency.clone(); |
453 _removed = dependency.removeConstraint(depender); | 460 _removed = dependency.removeConstraint(depender); |
454 return _processChange(solver, oldDependency, dependency); | 461 return _processChange(solver, oldDependency, dependency); |
455 } | 462 } |
456 | 463 |
457 void undo(VersionSolver solver) { | 464 void undo(VersionSolver solver) { |
458 solver.getDependency(dependent).placeConstraint(depender, _removed); | 465 solver.getDependency(dependent).placeConstraint(depender, _removed); |
459 } | 466 } |
460 } | 467 } |
461 | 468 |
462 /** [package]'s version is no longer constrained by the lockfile. */ | 469 /** [package]'s version is no longer constrained by the lockfile. */ |
463 class UnlockPackage implements WorkItem { | 470 class UnlockPackage implements WorkItem { |
464 /** The package being unlocked. */ | 471 /** The package being unlocked. */ |
465 Dependency package; | 472 Dependency package; |
466 | 473 |
467 UnlockPackage(this.package); | 474 UnlockPackage(this.package); |
468 | 475 |
469 Future process(VersionSolver solver) { | 476 Future process(VersionSolver solver) { |
477 log.fine("Unlocking ${package.name}."); | |
478 | |
470 solver.lockFile.packages.remove(package.name); | 479 solver.lockFile.packages.remove(package.name); |
471 return solver.getBestVersion(package).transform((best) { | 480 return solver.getBestVersion(package).transform((best) { |
472 if (best == null) return null; | 481 if (best == null) return null; |
473 solver.enqueue(new ChangeVersion( | 482 solver.enqueue(new ChangeVersion( |
474 package.name, package.source, package.description, best)); | 483 package.name, package.source, package.description, best)); |
475 }); | 484 }); |
476 } | 485 } |
477 } | 486 } |
478 | 487 |
479 // TODO(rnystrom): Instead of always pulling from the source (which will mean | 488 // TODO(rnystrom): Instead of always pulling from the source (which will mean |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 final description1; | 733 final description1; |
725 final description2; | 734 final description2; |
726 | 735 |
727 DescriptionMismatchException(this.package, this.description1, | 736 DescriptionMismatchException(this.package, this.description1, |
728 this.description2); | 737 this.description2); |
729 | 738 |
730 // TODO(nweiz): Dump to YAML when that's supported | 739 // TODO(nweiz): Dump to YAML when that's supported |
731 String toString() => "Package '$package' has conflicting descriptions " | 740 String toString() => "Package '$package' has conflicting descriptions " |
732 "'${JSON.stringify(description1)}' and '${JSON.stringify(description2)}'"; | 741 "'${JSON.stringify(description1)}' and '${JSON.stringify(description2)}'"; |
733 } | 742 } |
OLD | NEW |