| 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 /// Attempts to resolve a set of version constraints for a package dependency | 5 /// Attempts to resolve a set of version constraints for a package dependency |
| 6 /// graph and select an appropriate set of best specific versions for all | 6 /// graph and select an appropriate set of best specific versions for all |
| 7 /// dependent packages. It works iteratively and tries to reach a stable | 7 /// dependent packages. It works iteratively and tries to reach a stable |
| 8 /// solution where the constraints of all dependencies are met. If it fails to | 8 /// solution where the constraints of all dependencies are met. If it fails to |
| 9 /// reach a solution after a certain number of iterations, it assumes the | 9 /// reach a solution after a certain number of iterations, it assumes the |
| 10 /// dependency graph is unstable and reports and error. | 10 /// dependency graph is unstable and reports and error. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 library version_solver; | 36 library version_solver; |
| 37 | 37 |
| 38 import 'dart:async'; | 38 import 'dart:async'; |
| 39 import 'dart:collection' show Queue; | 39 import 'dart:collection' show Queue; |
| 40 import 'dart:json' as json; | 40 import 'dart:json' as 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 'log.dart' as log; |
| 44 import 'package.dart'; | 44 import 'package.dart'; |
| 45 import 'pubspec.dart'; | 45 import 'pubspec.dart'; |
| 46 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 /// Attempts to select the best concrete versions for all of the transitive | 51 /// Attempts to select the best concrete versions for all of the transitive |
| 53 /// dependencies of [root] taking into account all of the [VersionConstraint]s | 52 /// dependencies of [root] taking into account all of the [VersionConstraint]s |
| 54 /// that those dependencies place on each other and the requirements imposed by | 53 /// 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 | 54 /// [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 | 55 /// the selected version for that package. If it fails, the future will complete |
| (...skipping 27 matching lines...) Expand all Loading... |
| 84 void useLatestVersion(String package) { | 83 void useLatestVersion(String package) { |
| 85 // TODO(nweiz): How do we want to detect and handle unknown dependencies | 84 // TODO(nweiz): How do we want to detect and handle unknown dependencies |
| 86 // here? | 85 // here? |
| 87 getDependency(package).useLatestVersion = true; | 86 getDependency(package).useLatestVersion = true; |
| 88 lockFile.packages.remove(package); | 87 lockFile.packages.remove(package); |
| 89 } | 88 } |
| 90 | 89 |
| 91 Future<List<PackageId>> solve() { | 90 Future<List<PackageId>> solve() { |
| 92 // Kick off the work by adding the root package at its concrete version to | 91 // Kick off the work by adding the root package at its concrete version to |
| 93 // the dependency graph. | 92 // the dependency graph. |
| 94 var ref = new PackageRef( | 93 var ref = new PackageRef.root(_root); |
| 95 _root.name, new RootSource(_root), _root.version, _root.name); | |
| 96 enqueue(new AddConstraint('(entrypoint)', ref)); | 94 enqueue(new AddConstraint('(entrypoint)', ref)); |
| 97 _pubspecs.cache(ref.atVersion(_root.version), _root.pubspec); | 95 _pubspecs.cache(ref.atVersion(_root.version), _root.pubspec); |
| 98 | 96 |
| 99 Future processNextWorkItem(_) { | 97 Future processNextWorkItem(_) { |
| 100 while (true) { | 98 while (true) { |
| 101 // Stop if we are done. | 99 // Stop if we are done. |
| 102 if (_work.isEmpty) return new Future.immediate(buildResults()); | 100 if (_work.isEmpty) return new Future.immediate(buildResults()); |
| 103 | 101 |
| 104 // If we appear to be stuck in a loop, then we probably have an unstable | 102 // If we appear to be stuck in a loop, then we probably have an unstable |
| 105 // graph, bail. We guess this based on a rough heuristic that it should | 103 // graph, bail. We guess this based on a rough heuristic that it should |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 | 233 |
| 236 /// The source of the package whose version is changing. | 234 /// The source of the package whose version is changing. |
| 237 final Source source; | 235 final Source source; |
| 238 | 236 |
| 239 /// The description identifying the package whose version is changing. | 237 /// The description identifying the package whose version is changing. |
| 240 final description; | 238 final description; |
| 241 | 239 |
| 242 /// The new selected version. | 240 /// The new selected version. |
| 243 final Version version; | 241 final Version version; |
| 244 | 242 |
| 245 ChangeVersion(this.package, this.source, this.description, this.version) { | 243 ChangeVersion(this.package, this.source, this.description, this.version); |
| 246 if (source == null) throw "null source"; | |
| 247 } | |
| 248 | 244 |
| 249 Future process(VersionSolver solver) { | 245 Future process(VersionSolver solver) { |
| 250 log.fine("Changing $package to version $version."); | 246 log.fine("Changing $package to version $version."); |
| 251 | 247 |
| 252 var dependency = solver.getDependency(package); | 248 var dependency = solver.getDependency(package); |
| 253 var oldVersion = dependency.version; | 249 var oldVersion = dependency.version; |
| 254 solver.setVersion(package, version); | 250 solver.setVersion(package, version); |
| 255 | 251 |
| 256 // The dependencies between the old and new version may be different. Walk | 252 // The dependencies between the old and new version may be different. Walk |
| 257 // them both and update any constraints that differ between the two. | 253 // them both and update any constraints that differ between the two. |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 } | 518 } |
| 523 | 519 |
| 524 /// The description of this dependency's package. | 520 /// The description of this dependency's package. |
| 525 get description { | 521 get description { |
| 526 var canonical = _canonicalRef(); | 522 var canonical = _canonicalRef(); |
| 527 if (canonical == null) return null; | 523 if (canonical == null) return null; |
| 528 return canonical.description; | 524 return canonical.description; |
| 529 } | 525 } |
| 530 | 526 |
| 531 /// Return the PackageRef that has the canonical source and description for | 527 /// Return the PackageRef that has the canonical source and description for |
| 532 /// this package. If any dependency requires that this package come from a | 528 /// this package. If any dependency is on the root package, that will be used; |
| 533 /// [RootSource], that will be used; otherwise, it will be the source and | 529 /// otherwise, it will be the source and description that all dependencies |
| 534 /// description that all dependencies agree upon. | 530 /// agree upon. |
| 535 PackageRef _canonicalRef() { | 531 PackageRef _canonicalRef() { |
| 536 if (_refs.isEmpty) return null; | 532 if (_refs.isEmpty) return null; |
| 537 var refs = _refs.values; | 533 var refs = _refs.values; |
| 538 for (var ref in refs) { | 534 for (var ref in refs) { |
| 539 if (ref is RootSource) return ref; | 535 if (ref.isRoot) return ref; |
| 540 } | 536 } |
| 541 return refs.first; | 537 return refs.first; |
| 542 } | 538 } |
| 543 | 539 |
| 544 Dependency(this.name) | 540 Dependency(this.name) |
| 545 : _refs = <String, PackageRef>{}; | 541 : _refs = <String, PackageRef>{}; |
| 546 | 542 |
| 547 Dependency._clone(Dependency other) | 543 Dependency._clone(Dependency other) |
| 548 : name = other.name, | 544 : name = other.name, |
| 549 version = other.version, | 545 version = other.version, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 575 | 571 |
| 576 /// Returns the name of a package whose constraint source and description | 572 /// Returns the name of a package whose constraint source and description |
| 577 /// all other constraints must match. Returns null if there are no | 573 /// all other constraints must match. Returns null if there are no |
| 578 /// requirements on new constraints. | 574 /// requirements on new constraints. |
| 579 String _requiredDepender() { | 575 String _requiredDepender() { |
| 580 if (_refs.isEmpty) return null; | 576 if (_refs.isEmpty) return null; |
| 581 | 577 |
| 582 var dependers = _refs.keys.toList(); | 578 var dependers = _refs.keys.toList(); |
| 583 if (dependers.length == 1) { | 579 if (dependers.length == 1) { |
| 584 var depender = dependers[0]; | 580 var depender = dependers[0]; |
| 585 if (_refs[depender].source is RootSource) return null; | 581 if (_refs[depender].isRoot) return null; |
| 586 return depender; | 582 return depender; |
| 587 } | 583 } |
| 588 | 584 |
| 589 return dependers[1]; | 585 return dependers[1]; |
| 590 } | 586 } |
| 591 | 587 |
| 592 /// Removes the constraint from [package] onto this. | 588 /// Removes the constraint from [package] onto this. |
| 593 PackageRef removeConstraint(String package) => _refs.remove(package); | 589 PackageRef removeConstraint(String package) => _refs.remove(package); |
| 594 } | 590 } |
| 595 | 591 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 | 697 |
| 702 String toString() { | 698 String toString() { |
| 703 // TODO(nweiz): Dump descriptions to YAML when that's supported. | 699 // TODO(nweiz): Dump descriptions to YAML when that's supported. |
| 704 return "Incompatible dependencies on '$package':\n" | 700 return "Incompatible dependencies on '$package':\n" |
| 705 "- '$depender1' depends on it with description " | 701 "- '$depender1' depends on it with description " |
| 706 "${json.stringify(description1)}\n" | 702 "${json.stringify(description1)}\n" |
| 707 "- '$depender2' depends on it with description " | 703 "- '$depender2' depends on it with description " |
| 708 "${json.stringify(description2)}"; | 704 "${json.stringify(description2)}"; |
| 709 } | 705 } |
| 710 } | 706 } |
| OLD | NEW |