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 /// A back-tracking depth-first solver. Attempts to find the best solution for | 5 /// A back-tracking depth-first solver. Attempts to find the best solution for |
6 /// a root package's transitive dependency graph, where a "solution" is a set | 6 /// a root package's transitive dependency graph, where a "solution" is a set |
7 /// of concrete package versions. A valid solution will select concrete | 7 /// of concrete package versions. A valid solution will select concrete |
8 /// versions for every package reached from the root package's dependency graph, | 8 /// versions for every package reached from the root package's dependency graph, |
9 /// and each of those packages will fit the version constraints placed on it. | 9 /// and each of those packages will fit the version constraints placed on it. |
10 /// | 10 /// |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
67 /// | 67 /// |
68 /// The solver tries versions in depth-first order, so only the last queue in | 68 /// The solver tries versions in depth-first order, so only the last queue in |
69 /// the list will have items removed from it. When a new constraint is placed | 69 /// the list will have items removed from it. When a new constraint is placed |
70 /// on an already-selected package, and that constraint doesn't match the | 70 /// on an already-selected package, and that constraint doesn't match the |
71 /// selected version, that will cause the current solution to fail and | 71 /// selected version, that will cause the current solution to fail and |
72 /// trigger backtracking. | 72 /// trigger backtracking. |
73 final _selected = <Queue<PackageId>>[]; | 73 final _selected = <Queue<PackageId>>[]; |
74 | 74 |
75 /// The number of possible solutions that have been attempted. | 75 /// The number of possible solutions that have been attempted. |
76 int get attemptedSolutions => _attemptedSolutions; | 76 int get attemptedSolutions => _attemptedSolutions; |
77 var _attemptedSolutions = 0; | 77 var _attemptedSolutions = 1; |
78 | 78 |
79 BacktrackingVersionSolver(SourceRegistry sources, Package root, | 79 BacktrackingVersionSolver(SourceRegistry sources, Package root, |
80 LockFile lockFile, List<String> useLatest) | 80 LockFile lockFile, List<String> useLatest) |
81 : super(sources, root, lockFile, useLatest); | 81 : super(sources, root, lockFile, useLatest); |
82 | 82 |
83 void forceLatestVersion(String package) { | 83 void forceLatestVersion(String package) { |
84 _forceLatest.add(package); | 84 _forceLatest.add(package); |
85 } | 85 } |
86 | 86 |
87 Future<List<PackageId>> runSolver() => _traverseSolution(); | 87 Future<List<PackageId>> runSolver() => _traverseSolution(); |
(...skipping 27 matching lines...) Expand all Loading... | |
115 /// `null` if it isn't in the lockfile (or has been unlocked). | 115 /// `null` if it isn't in the lockfile (or has been unlocked). |
116 PackageId getLocked(String package) => lockFile.packages[package]; | 116 PackageId getLocked(String package) => lockFile.packages[package]; |
117 | 117 |
118 /// Traverses the root package's dependency graph using the current potential | 118 /// Traverses the root package's dependency graph using the current potential |
119 /// solution. If successful, completes to the solution. If not, backtracks | 119 /// solution. If successful, completes to the solution. If not, backtracks |
120 /// to the most recently selected version of a package and tries the next | 120 /// to the most recently selected version of a package and tries the next |
121 /// version of it. If there are no more versions, continues to backtrack to | 121 /// version of it. If there are no more versions, continues to backtrack to |
122 /// previous selections, and so on. If there is nothing left to backtrack to, | 122 /// previous selections, and so on. If there is nothing left to backtrack to, |
123 /// completes to the last failure that occurred. | 123 /// completes to the last failure that occurred. |
124 Future<List<PackageId>> _traverseSolution() { | 124 Future<List<PackageId>> _traverseSolution() { |
125 _attemptedSolutions++; | |
126 | |
127 return new Traverser(this).traverse().catchError((error) { | 125 return new Traverser(this).traverse().catchError((error) { |
128 if (error is! SolveFailure) throw error; | 126 if (error is! SolveFailure) throw error; |
129 | 127 |
130 if (_backtrack(error)) return _traverseSolution(); | 128 if (_backtrack(error)) { |
129 _attemptedSolutions++; | |
nweiz
2013/04/16 23:52:32
Why is this moving in here? Won't this just decrem
Bob Nystrom
2013/04/17 17:28:44
This handles a weird little corner case. If the ro
| |
130 return _traverseSolution(); | |
131 } | |
131 | 132 |
132 // All out of solutions, so fail. | 133 // All out of solutions, so fail. |
133 throw error; | 134 throw error; |
134 }); | 135 }); |
135 } | 136 } |
136 | 137 |
137 /// Backtracks from the current failed solution and determines the next | 138 /// Backtracks from the current failed solution and determines the next |
138 /// solution to try. If possible, it will backjump based on the cause of the | 139 /// solution to try. If possible, it will backjump based on the cause of the |
139 /// [failure] to minize backtracking. Otherwise, it will simply backtrack to | 140 /// [failure] to minize backtracking. Otherwise, it will simply backtrack to |
140 /// the next possible solution. | 141 /// the next possible solution. |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 | 301 |
301 var id = _packages.removeFirst(); | 302 var id = _packages.removeFirst(); |
302 | 303 |
303 // Don't visit the same package twice. | 304 // Don't visit the same package twice. |
304 if (_visited.contains(id)) { | 305 if (_visited.contains(id)) { |
305 return _traversePackage(); | 306 return _traversePackage(); |
306 } | 307 } |
307 _visited.add(id); | 308 _visited.add(id); |
308 | 309 |
309 return _solver.cache.getPubspec(id).then((pubspec) { | 310 return _solver.cache.getPubspec(id).then((pubspec) { |
311 validateSdkConstraint(pubspec); | |
312 | |
310 var refs = pubspec.dependencies.toList(); | 313 var refs = pubspec.dependencies.toList(); |
311 | 314 |
312 // Include dev dependencies of the root package. | 315 // Include dev dependencies of the root package. |
313 if (id.isRoot) refs.addAll(pubspec.devDependencies); | 316 if (id.isRoot) refs.addAll(pubspec.devDependencies); |
314 | 317 |
315 // Given a package ref, returns a future that completes to a pair of the | 318 // Given a package ref, returns a future that completes to a pair of the |
316 // ref and the number of versions available for it. | 319 // ref and the number of versions available for it. |
317 getNumVersions(PackageRef ref) { | 320 getNumVersions(PackageRef ref) { |
318 // There is only ever one version of the root package. | 321 // There is only ever one version of the root package. |
319 if (ref.isRoot) { | 322 if (ref.isRoot) { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 | 536 |
534 var required = _getRequired(name); | 537 var required = _getRequired(name); |
535 if (required != null) { | 538 if (required != null) { |
536 if (package.source.name != required.ref.source.name) return null; | 539 if (package.source.name != required.ref.source.name) return null; |
537 if (!package.descriptionEquals(required.ref)) return null; | 540 if (!package.descriptionEquals(required.ref)) return null; |
538 } | 541 } |
539 | 542 |
540 return package; | 543 return package; |
541 } | 544 } |
542 } | 545 } |
OLD | NEW |