Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: sdk/lib/_internal/pub/lib/src/validator/dependency.dart

Issue 686323002: Add support for ^ constraints in pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 pub.validator.dependency; 5 library pub.validator.dependency;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:pub_semver/pub_semver.dart'; 9 import 'package:pub_semver/pub_semver.dart';
10 10
11 import '../entrypoint.dart'; 11 import '../entrypoint.dart';
12 import '../log.dart' as log; 12 import '../log.dart' as log;
13 import '../package.dart'; 13 import '../package.dart';
14 import '../utils.dart';
14 import '../validator.dart'; 15 import '../validator.dart';
15 16
17 /// The range of all pub versions that don't support `^` version constraints.
18 final _preCaretPubVersions = new VersionConstraint.parse("<1.8.0-dev.3.0");
19
20 // TODO(nweiz): replace this with "^1.8.0" for the 1.8 release.
21 /// The range of all pub versions that do support `^` version constraints.
22 ///
23 /// This is intersected with the user's SDK constraint to provide a suggested
24 /// constraint.
25 final _postCaretPubVersions = new VersionConstraint.parse("^1.8.0-dev.3.0");
26
16 /// A validator that validates a package's dependencies. 27 /// A validator that validates a package's dependencies.
17 class DependencyValidator extends Validator { 28 class DependencyValidator extends Validator {
29 /// Whether the SDK constraint guarantees that `^` version constraints are
30 /// safe.
31 bool get _caretAllowed => entrypoint.root.pubspec.environment.sdkVersion
32 .intersect(_preCaretPubVersions).isEmpty;
33
18 DependencyValidator(Entrypoint entrypoint) 34 DependencyValidator(Entrypoint entrypoint)
19 : super(entrypoint); 35 : super(entrypoint);
20 36
21 Future validate() { 37 Future validate() async {
22 return Future.forEach(entrypoint.root.pubspec.dependencies, (dependency) { 38 var caretDeps = [];
39
40 // TODO(nweiz): Replace this with a real for/in loop when we update
41 // async_await.
42 await Future.forEach(entrypoint.root.pubspec.dependencies,
43 (dependency) async {
23 if (dependency.source != "hosted") { 44 if (dependency.source != "hosted") {
24 return _warnAboutSource(dependency); 45 await _warnAboutSource(dependency);
25 } 46 } else if (dependency.constraint.isAny) {
26
27 if (dependency.constraint.isAny) {
28 _warnAboutNoConstraint(dependency); 47 _warnAboutNoConstraint(dependency);
29 } else if (dependency.constraint is Version) { 48 } else if (dependency.constraint is Version) {
30 _warnAboutSingleVersionConstraint(dependency); 49 _warnAboutSingleVersionConstraint(dependency);
31 } else if (dependency.constraint is VersionRange) { 50 } else if (dependency.constraint is VersionRange) {
32 if (dependency.constraint.min == null) { 51 if (dependency.constraint.min == null) {
33 _warnAboutNoConstraintLowerBound(dependency); 52 _warnAboutNoConstraintLowerBound(dependency);
34 } else if (dependency.constraint.max == null) { 53 } else if (dependency.constraint.max == null) {
35 _warnAboutNoConstraintUpperBound(dependency); 54 _warnAboutNoConstraintUpperBound(dependency);
36 } 55 }
56
57 if (dependency.constraint.toString().startsWith("^")) {
58 caretDeps.add(dependency);
59 }
37 } 60 }
61 });
38 62
39 return new Future.value(); 63 if (caretDeps.isNotEmpty && !_caretAllowed) {
40 }); 64 _errorAboutCaretConstraints(caretDeps);
65 }
41 } 66 }
42 67
43 /// Warn that dependencies should use the hosted source. 68 /// Warn that dependencies should use the hosted source.
44 Future _warnAboutSource(PackageDep dep) { 69 Future _warnAboutSource(PackageDep dep) {
45 return entrypoint.cache.sources['hosted'] 70 return entrypoint.cache.sources['hosted']
46 .getVersions(dep.name, dep.name) 71 .getVersions(dep.name, dep.name)
47 .catchError((e) => <Version>[]) 72 .catchError((e) => <Version>[])
48 .then((versions) { 73 .then((versions) {
49 var constraint; 74 var constraint;
50 var primary = Version.primary(versions); 75 var primary = Version.primary(versions);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 'dependencies:\n' 146 'dependencies:\n'
122 ' ${dep.name}: $constraint\n'; 147 ' ${dep.name}: $constraint\n';
123 } 148 }
124 warnings.add("$message\n" 149 warnings.add("$message\n"
125 'Without a constraint, you\'re promising to support ${log.bold("all")} ' 150 'Without a constraint, you\'re promising to support ${log.bold("all")} '
126 'previous versions of "${dep.name}".'); 151 'previous versions of "${dep.name}".');
127 } 152 }
128 153
129 /// Warn that dependencies should have upper bounds on their constraints. 154 /// Warn that dependencies should have upper bounds on their constraints.
130 void _warnAboutNoConstraintUpperBound(PackageDep dep) { 155 void _warnAboutNoConstraintUpperBound(PackageDep dep) {
156 var constraint;
157 if ((dep.constraint as VersionRange).includeMin) {
158 constraint = _constraintForVersion(dep.constraint.min);
159 } else {
160 constraint = '"${dep.constraint} '
161 '<${(dep.constraint as VersionRange).min.nextBreaking}"';
162 }
163
131 warnings.add( 164 warnings.add(
132 'Your dependency on "${dep.name}" should have an upper bound. For ' 165 'Your dependency on "${dep.name}" should have an upper bound. For '
133 'example:\n' 166 'example:\n'
134 '\n' 167 '\n'
135 'dependencies:\n' 168 'dependencies:\n'
136 ' ${dep.name}: "${dep.constraint} ' 169 ' ${dep.name}: $constraint\n'
137 '${_upperBoundForVersion((dep.constraint as VersionRange).min)}"\n'
138 '\n' 170 '\n'
139 'Without an upper bound, you\'re promising to support ' 171 'Without an upper bound, you\'re promising to support '
140 '${log.bold("all")} future versions of ${dep.name}.'); 172 '${log.bold("all")} future versions of ${dep.name}.');
141 } 173 }
142 174
175 /// Emits an error for any version constraints that use `^` without an
176 /// appropriate SDK constraint.
177 void _errorAboutCaretConstraints(List<PackageDeps> caretDeps) {
178 var newSdkConstraint = entrypoint.root.pubspec.environment.sdkVersion
179 .intersect(_postCaretPubVersions);
180
181 if (newSdkConstraint.isEmpty) newSdkConstraint = _postCaretPubVersions;
182
183 var buffer = new StringBuffer(
184 "Older versions of pub don't support ^ version constraints.\n"
185 "Make sure your SDK constraint excludes those old versions:\n"
186 "\n"
187 "environment:\n"
188 " sdk: \"$newSdkConstraint\"\n"
189 "\n");
190
191 if (caretDeps.length == 1) {
192 buffer.writeln("Or use a fully-expanded constraint:");
193 } else {
194 buffer.writeln("Or use fully-expanded constraints:");
195 }
196
197 buffer.writeln();
198 buffer.writeln("dependencies:");
199
200 caretDeps.forEach((dep) {
201 VersionRange constraint = dep.constraint;
202 buffer.writeln(
203 " ${dep.name}: \">=${constraint.min} <${constraint.max}\"");
204 });
205
206 errors.add(buffer.toString().trim());
207 }
208
143 /// Returns the suggested version constraint for a dependency that was tested 209 /// Returns the suggested version constraint for a dependency that was tested
144 /// against [version]. 210 /// against [version].
145 String _constraintForVersion(Version version) => 211 String _constraintForVersion(Version version) {
146 '">=$version ${_upperBoundForVersion(version)}"'; 212 if (_caretAllowed) return "^$version";
147 213 return '">=$version <${version.nextBreaking}"';
148 /// Returns the suggested upper bound for a dependency that was tested against
149 /// [version].
150 String _upperBoundForVersion(Version version) {
151 if (version.major != 0) return '<${version.major + 1}.0.0';
152 return '<${version.major}.${version.minor + 1}.0';
153 } 214 }
154 } 215 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/pub/lib/src/validator.dart ('k') | sdk/lib/_internal/pub/lib/src/validator/sdk_constraint.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698