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 library version_solver; | 5 library version_solver; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:json' as json; | 8 import 'dart:json' as json; |
9 | 9 |
10 import '../lock_file.dart'; | 10 import '../lock_file.dart'; |
11 import '../log.dart' as log; | 11 import '../log.dart' as log; |
12 import '../package.dart'; | 12 import '../package.dart'; |
13 import '../pubspec.dart'; | 13 import '../pubspec.dart'; |
14 import '../sdk.dart' as sdk; | |
14 import '../source.dart'; | 15 import '../source.dart'; |
15 import '../source_registry.dart'; | 16 import '../source_registry.dart'; |
16 import '../version.dart'; | 17 import '../version.dart'; |
17 import 'backtracking_solver.dart'; | 18 import 'backtracking_solver.dart'; |
18 import 'greedy_solver.dart'; | 19 import 'greedy_solver.dart'; |
19 | 20 |
20 /// Attempts to select the best concrete versions for all of the transitive | 21 /// Attempts to select the best concrete versions for all of the transitive |
21 /// dependencies of [root] taking into account all of the [VersionConstraint]s | 22 /// dependencies of [root] taking into account all of the [VersionConstraint]s |
22 /// that those dependencies place on each other and the requirements imposed by | 23 /// that those dependencies place on each other and the requirements imposed by |
23 /// [lockFile]. | 24 /// [lockFile]. |
(...skipping 15 matching lines...) Expand all Loading... | |
39 var solver; | 40 var solver; |
40 if (allowBacktracking) { | 41 if (allowBacktracking) { |
41 solver = new BacktrackingVersionSolver(sources, root, lockFile, useLatest); | 42 solver = new BacktrackingVersionSolver(sources, root, lockFile, useLatest); |
42 } else { | 43 } else { |
43 solver = new GreedyVersionSolver(sources, root, lockFile, useLatest); | 44 solver = new GreedyVersionSolver(sources, root, lockFile, useLatest); |
44 } | 45 } |
45 | 46 |
46 return solver.solve(); | 47 return solver.solve(); |
47 } | 48 } |
48 | 49 |
50 /// Ensures that if [pubspec] has an SDK constraint, then it is compatible | |
51 /// with the current SDK. Throws a [SolverFailure] if not. | |
52 void validateSdkConstraint(Pubspec pubspec) { | |
nweiz
2013/04/16 23:52:32
It seems really weird that this is a top-level, pu
Bob Nystrom
2013/04/17 17:28:44
It was being used by both VersionSolver and Backtr
| |
53 if (pubspec.environment.sdkVersion.allows(sdk.version)) return; | |
54 | |
55 throw new CouldNotSolveException( | |
56 'Package "{pubspec.name} requires SDK version ' | |
57 '${pubspec.environment.sdkVersion} but the current SDK is ' | |
58 '${sdk.version}.'); | |
59 } | |
60 | |
49 /// Base class for an implementation of the version constraint solver. | 61 /// Base class for an implementation of the version constraint solver. |
50 class VersionSolver { | 62 class VersionSolver { |
51 final SourceRegistry sources; | 63 final SourceRegistry sources; |
52 final Package root; | 64 final Package root; |
53 final LockFile lockFile; | 65 final LockFile lockFile; |
54 final PubspecCache cache; | 66 final PubspecCache cache; |
55 | 67 |
56 VersionSolver(SourceRegistry sources, this.root, this.lockFile, | 68 VersionSolver(SourceRegistry sources, this.root, this.lockFile, |
57 List<String> useLatest) | 69 List<String> useLatest) |
58 : sources = sources, | 70 : sources = sources, |
59 cache = new PubspecCache(sources) { | 71 cache = new PubspecCache(sources) { |
60 for (var package in useLatest) { | 72 for (var package in useLatest) { |
61 forceLatestVersion(package); | 73 forceLatestVersion(package); |
62 lockFile.packages.remove(package); | 74 lockFile.packages.remove(package); |
63 } | 75 } |
64 } | 76 } |
65 | 77 |
66 /// The number of solutions the solver has tried so far. | 78 /// The number of solutions the solver has tried so far. |
67 int get attemptedSolutions; | 79 int get attemptedSolutions; |
68 | 80 |
69 /// Force the solver to upgrade [package] to the latest available version. | 81 /// Force the solver to upgrade [package] to the latest available version. |
70 void forceLatestVersion(String package); | 82 void forceLatestVersion(String package); |
71 | 83 |
72 /// Run the solver. Completes with a list of specific package versions if | 84 /// Run the solver. Completes with a list of specific package versions if |
73 /// successful or an error if it failed to find a solution. | 85 /// successful or an error if it failed to find a solution. |
74 Future<SolveResult> solve() { | 86 Future<SolveResult> solve() { |
75 var stopwatch = new Stopwatch(); | 87 var stopwatch = new Stopwatch(); |
76 stopwatch.start(); | |
77 | 88 |
78 // Pre-cache the root package's known pubspec. | 89 return new Future(() { |
79 cache.cache(new PackageId.root(root), root.pubspec); | 90 stopwatch.start(); |
80 | 91 |
81 return runSolver().then((packages) { | 92 // Pre-cache the root package's known pubspec. |
93 cache.cache(new PackageId.root(root), root.pubspec); | |
94 | |
95 validateSdkConstraint(root.pubspec); | |
96 return runSolver(); | |
97 }).then((packages) { | |
82 return new SolveResult(packages, null, attemptedSolutions); | 98 return new SolveResult(packages, null, attemptedSolutions); |
83 }).catchError((error) { | 99 }).catchError((error) { |
84 if (error is! SolveFailure) throw error; | 100 if (error is! SolveFailure) throw error; |
85 | 101 |
86 // Wrap a failure in a result so we can attach some other data. | 102 // Wrap a failure in a result so we can attach some other data. |
87 return new SolveResult(null, error, attemptedSolutions); | 103 return new SolveResult(null, error, attemptedSolutions); |
88 }).whenComplete(() { | 104 }).whenComplete(() { |
89 // Gather some solving metrics. | 105 // Gather some solving metrics. |
90 var buffer = new StringBuffer(); | 106 var buffer = new StringBuffer(); |
91 buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.'); | 107 buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.'); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 | 313 |
298 /// Describes a dependencie's reference in the output message. Override this | 314 /// Describes a dependencie's reference in the output message. Override this |
299 /// to highlight which aspect of [ref] led to the failure. | 315 /// to highlight which aspect of [ref] led to the failure. |
300 String _describeDependency(PackageRef ref) => | 316 String _describeDependency(PackageRef ref) => |
301 "depends on version ${ref.constraint}"; | 317 "depends on version ${ref.constraint}"; |
302 } | 318 } |
303 | 319 |
304 /// Exception thrown when the [VersionSolver] fails to find a solution after a | 320 /// Exception thrown when the [VersionSolver] fails to find a solution after a |
305 /// certain number of iterations. | 321 /// certain number of iterations. |
306 class CouldNotSolveException extends SolveFailure { | 322 class CouldNotSolveException extends SolveFailure { |
307 CouldNotSolveException() | 323 CouldNotSolveException([String message]) |
308 : super(null, null); | 324 : super(null, null), |
325 _message = (message != null) ? message : | |
326 "Could not find a solution that met all constraints."; | |
309 | 327 |
310 /// A message describing the specific kind of solve failure. | 328 /// A message describing the specific kind of solve failure. |
311 String get _message => | 329 final String _message; |
312 "Could not find a solution that met all constraints."; | |
313 } | 330 } |
314 | 331 |
315 /// Exception thrown when the [VersionConstraint] used to match a package is | 332 /// Exception thrown when the [VersionConstraint] used to match a package is |
316 /// valid (i.e. non-empty), but there are no available versions of the package | 333 /// valid (i.e. non-empty), but there are no available versions of the package |
317 /// that fit that constraint. | 334 /// that fit that constraint. |
318 class NoVersionException extends SolveFailure { | 335 class NoVersionException extends SolveFailure { |
319 final VersionConstraint constraint; | 336 final VersionConstraint constraint; |
320 | 337 |
321 NoVersionException(String package, this.constraint, | 338 NoVersionException(String package, this.constraint, |
322 Iterable<Dependency> dependencies) | 339 Iterable<Dependency> dependencies) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 Iterable<Dependency> dependencies) | 387 Iterable<Dependency> dependencies) |
371 : super(package, dependencies); | 388 : super(package, dependencies); |
372 | 389 |
373 String get _message => "Incompatible dependencies on '$package'"; | 390 String get _message => "Incompatible dependencies on '$package'"; |
374 | 391 |
375 String _describeDependency(PackageRef ref) { | 392 String _describeDependency(PackageRef ref) { |
376 // TODO(nweiz): Dump descriptions to YAML when that's supported. | 393 // TODO(nweiz): Dump descriptions to YAML when that's supported. |
377 return "depends on it with description ${json.stringify(ref.description)}"; | 394 return "depends on it with description ${json.stringify(ref.description)}"; |
378 } | 395 } |
379 } | 396 } |
OLD | NEW |