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 |