Make >=2.12 <3.0.0 compatible with dart 3 (#3572)
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 36f8047..2683cdf 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -20,7 +20,6 @@
import 'exceptions.dart';
import 'executable.dart';
import 'io.dart';
-import 'language_version.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
@@ -281,7 +280,8 @@
await lockFile.packageConfigFile(
cache,
entrypoint: entrypointName,
- entrypointSdkConstraint: root.pubspec.sdkConstraints[sdk.identifier],
+ entrypointSdkConstraint:
+ root.pubspec.sdkConstraints[sdk.identifier]?.effectiveConstraint,
relativeFrom: isGlobal ? null : root.dir,
),
);
@@ -816,9 +816,7 @@
try {
// Load `pubspec.yaml` and extract language version to compare with the
// language version from `package_config.json`.
- final languageVersion = LanguageVersion.fromSdkConstraint(
- cache.load(id).pubspec.sdkConstraints[sdk.identifier],
- );
+ final languageVersion = cache.load(id).pubspec.languageVersion;
if (pkg.languageVersion != languageVersion) {
final relativePubspecPath = p.join(
cache.getDirectory(id, relativeFrom: '.'),
@@ -874,7 +872,7 @@
///
/// We don't allow unknown sdks.
void _checkSdkConstraint(Pubspec pubspec) {
- final dartSdkConstraint = pubspec.sdkConstraints['dart'];
+ final dartSdkConstraint = pubspec.dartSdkConstraint.effectiveConstraint;
if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
// Suggest version range '>=2.10.0 <3.0.0', we avoid using:
// [CompatibleWithVersionRange] because some pub versions don't support
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index bb97023..d8cdef6 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -362,7 +362,9 @@
dataError('${log.bold(name)} ${entrypoint.root.version} requires '
'unknown SDK "$name".');
} else if (sdkName == 'dart') {
- if (constraint.allows((sdk as DartSdk).version)) return;
+ if (constraint.effectiveConstraint.allows((sdk as DartSdk).version)) {
+ return;
+ }
dataError("${log.bold(name)} ${entrypoint.root.version} doesn't "
'support Dart ${sdk.version}.');
} else {
diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart
index f133172..6c66224 100644
--- a/lib/src/lock_file.dart
+++ b/lib/src/lock_file.dart
@@ -306,12 +306,11 @@
rootUri = p.toUri(rootPath);
}
final pubspec = await cache.describe(id);
- final sdkConstraint = pubspec.sdkConstraints[sdk.identifier];
entries.add(PackageConfigEntry(
name: name,
rootUri: rootUri,
packageUri: p.toUri('lib/'),
- languageVersion: LanguageVersion.fromSdkConstraint(sdkConstraint),
+ languageVersion: pubspec.languageVersion,
));
}
diff --git a/lib/src/null_safety_analysis.dart b/lib/src/null_safety_analysis.dart
index fe89b55..284e845 100644
--- a/lib/src/null_safety_analysis.dart
+++ b/lib/src/null_safety_analysis.dart
@@ -91,7 +91,7 @@
}
},
sources: _systemCache.sources,
- sdkConstraints: {'dart': rootPubspec.sdkConstraints['dart']!}));
+ sdkConstraints: {'dart': rootPubspec.dartSdkConstraint}));
final rootLanguageVersion = rootPubspec.languageVersion;
if (!rootLanguageVersion.supportsNullSafety) {
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 6e1d566..69b5557 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -120,6 +120,9 @@
Map<String, PackageRange>? _devDependencies;
+ /// The Dart sdk version this is parsed against.
+ final Version _dartSdkVersion;
+
/// The dependency constraints that this package overrides when it is the
/// root package.
///
@@ -163,13 +166,13 @@
Map<String, PackageRange>? _dependencyOverrides;
- /// A map from SDK identifiers to constraints on those SDK versions.
- Map<String, VersionConstraint> get sdkConstraints {
- _ensureEnvironment();
- return _sdkConstraints!;
- }
+ SdkConstraint get dartSdkConstraint => sdkConstraints['dart']!;
- Map<String, VersionConstraint>? _sdkConstraints;
+ /// A map from SDK identifiers to constraints on those SDK versions.
+ late final Map<String, SdkConstraint> sdkConstraints =
+ _givenSdkConstraints ?? UnmodifiableMapView(_parseEnvironment(fields));
+
+ final Map<String, SdkConstraint>? _givenSdkConstraints;
/// Whether or not to apply the [_defaultUpperBoundsSdkConstraint] to this
/// pubspec.
@@ -177,41 +180,8 @@
/// Whether or not the SDK version was overridden from <2.0.0 to
/// <2.0.0-dev.infinity.
- bool get dartSdkWasOverridden => _dartSdkWasOverridden;
- bool _dartSdkWasOverridden = false;
-
- /// The original Dart SDK constraint as written in the pubspec.
- ///
- /// If [dartSdkWasOverridden] is `false`, this will be identical to
- /// `sdkConstraints["dart"]`.
- VersionConstraint get originalDartSdkConstraint {
- _ensureEnvironment();
- return _originalDartSdkConstraint ?? sdkConstraints['dart']!;
- }
-
- VersionConstraint? _originalDartSdkConstraint;
-
- /// Ensures that the top-level "environment" field has been parsed and
- /// [_sdkConstraints] is set accordingly.
- void _ensureEnvironment() {
- if (_sdkConstraints != null) return;
-
- var sdkConstraints = _parseEnvironment(fields);
- var parsedDartSdkConstraint = sdkConstraints['dart'];
-
- if (parsedDartSdkConstraint is VersionRange &&
- _shouldEnableCurrentSdk(parsedDartSdkConstraint)) {
- _originalDartSdkConstraint = parsedDartSdkConstraint;
- _dartSdkWasOverridden = true;
- sdkConstraints['dart'] = VersionRange(
- min: parsedDartSdkConstraint.min,
- includeMin: parsedDartSdkConstraint.includeMin,
- max: sdk.version,
- includeMax: true);
- }
-
- _sdkConstraints = UnmodifiableMapView(sdkConstraints);
- }
+ bool get dartSdkWasOverridden => _dartSdkWasOverriddenToAllowPrerelease;
+ bool _dartSdkWasOverriddenToAllowPrerelease = false;
/// Whether or not we should override [sdkConstraint] to be <= the user's
/// current SDK version.
@@ -227,12 +197,12 @@
/// patch versions as the user's current SDK.
bool _shouldEnableCurrentSdk(VersionRange sdkConstraint) {
if (!_allowPreReleaseSdk) return false;
- if (!sdk.version.isPreRelease) return false;
+ if (!_dartSdkVersion.isPreRelease) return false;
if (sdkConstraint.includeMax) return false;
var minSdkConstraint = sdkConstraint.min;
if (minSdkConstraint != null &&
minSdkConstraint.isPreRelease &&
- equalsIgnoringPreRelease(sdkConstraint.min!, sdk.version)) {
+ equalsIgnoringPreRelease(sdkConstraint.min!, _dartSdkVersion)) {
return false;
}
var maxSdkConstraint = sdkConstraint.max;
@@ -241,54 +211,121 @@
!maxSdkConstraint.isFirstPreRelease) {
return false;
}
- return equalsIgnoringPreRelease(maxSdkConstraint, sdk.version);
+ return equalsIgnoringPreRelease(maxSdkConstraint, _dartSdkVersion);
+ }
+
+ SdkConstraint _interpretDartSdkConstraint(
+ VersionConstraint originalConstraint, {
+ required VersionConstraint? defaultUpperBoundConstraint,
+ }) {
+ VersionConstraint constraint = originalConstraint;
+ if (constraint is VersionRange && _shouldEnableCurrentSdk(constraint)) {
+ _dartSdkWasOverriddenToAllowPrerelease = true;
+ constraint = VersionRange(
+ min: constraint.min,
+ includeMin: constraint.includeMin,
+ max: _dartSdkVersion,
+ includeMax: true);
+ }
+ if (defaultUpperBoundConstraint != null &&
+ constraint is VersionRange &&
+ constraint.max == null &&
+ defaultUpperBoundConstraint.allowsAny(constraint)) {
+ constraint = VersionConstraint.intersection(
+ [constraint, defaultUpperBoundConstraint]);
+ }
+ // If a package is null safe it should also be compatible with dart 3.
+ // Therefore we rewrite a null-safety enabled constraint with the upper
+ // bound <3.0.0 to be have upper bound <4.0.0
+ if (constraint is VersionRange &&
+ LanguageVersion.fromSdkConstraint(constraint) >=
+ LanguageVersion.firstVersionWithNullSafety &&
+ // <3.0.0 is parsed into a max of 3.0.0-0, so that is what we look for
+ // here.
+ constraint.max == Version(3, 0, 0).firstPreRelease &&
+ constraint.includeMax == false) {
+ constraint = VersionRange(
+ min: constraint.min,
+ includeMin: constraint.includeMin,
+ // We don't have to use .firstPreRelease as the constructor will do that
+ // if needed.
+ max: Version(4, 0, 0),
+ );
+ }
+ return SdkConstraint(constraint, originalConstraint: originalConstraint);
+ }
+
+ // Flutter constraints get special treatment, as Flutter won't be using
+ // semantic versioning to mark breaking releases. We simply ignore upper
+ // bounds.
+ SdkConstraint _interpretFlutterSdkConstraint(VersionConstraint constraint) {
+ if (constraint is VersionRange) {
+ return SdkConstraint(
+ VersionRange(min: constraint.min, includeMin: constraint.includeMin),
+ originalConstraint: constraint,
+ );
+ }
+ return SdkConstraint(constraint);
}
/// Parses the "environment" field in [parent] and returns a map from SDK
/// identifiers to constraints on those SDKs.
- Map<String, VersionConstraint> _parseEnvironment(YamlMap parent) {
+ Map<String, SdkConstraint> _parseEnvironment(YamlMap parent) {
var yaml = parent['environment'];
+ final VersionConstraint originalDartSdkConstraint;
if (yaml == null) {
- return {
- 'dart': _includeDefaultSdkConstraint
- ? _defaultUpperBoundSdkConstraint
- : VersionConstraint.any
- };
- }
-
- if (yaml is! YamlMap) {
+ originalDartSdkConstraint = _includeDefaultSdkConstraint
+ ? _defaultUpperBoundSdkConstraint
+ : VersionConstraint.any;
+ } else if (yaml is! YamlMap) {
_error('"environment" field must be a map.',
parent.nodes['environment']!.span);
+ } else {
+ originalDartSdkConstraint = _parseVersionConstraint(
+ yaml.nodes['sdk'],
+ _packageName,
+ _FileType.pubspec,
+ );
}
var constraints = {
- 'dart': _parseVersionConstraint(
- yaml.nodes['sdk'], _packageName, _FileType.pubspec,
- defaultUpperBoundConstraint: _includeDefaultSdkConstraint
- ? _defaultUpperBoundSdkConstraint
- : null)
+ 'dart': _interpretDartSdkConstraint(
+ originalDartSdkConstraint,
+ defaultUpperBoundConstraint: _includeDefaultSdkConstraint
+ ? _defaultUpperBoundSdkConstraint
+ : null,
+ )
};
- yaml.nodes.forEach((name, constraint) {
- if (name.value is! String) {
- _error('SDK names must be strings.', name.span);
- } else if (name.value == 'dart') {
- _error('Use "sdk" to for Dart SDK constraints.', name.span);
- }
- if (name.value == 'sdk') return;
- constraints[name.value as String] =
- _parseVersionConstraint(constraint, _packageName, _FileType.pubspec,
- // Flutter constraints get special treatment, as Flutter won't be
- // using semantic versioning to mark breaking releases.
- ignoreUpperBound: name.value == 'flutter');
- });
+ if (yaml is YamlMap) {
+ yaml.nodes.forEach((nameNode, constraintNode) {
+ final name = nameNode.value;
+ if (name is! String) {
+ _error('SDK names must be strings.', nameNode.span);
+ } else if (name == 'dart') {
+ _error('Use "sdk" to for Dart SDK constraints.', nameNode.span);
+ }
+ if (name == 'sdk') return;
+ final constraint = _parseVersionConstraint(
+ constraintNode,
+ _packageName,
+ _FileType.pubspec,
+ );
+ constraints[name] = name == 'flutter'
+ ? _interpretFlutterSdkConstraint(constraint)
+ : SdkConstraint(constraint);
+ });
+ }
return constraints;
}
/// The language version implied by the sdk constraint.
- LanguageVersion get languageVersion =>
- LanguageVersion.fromSdkConstraint(originalDartSdkConstraint);
+ LanguageVersion get languageVersion {
+ return LanguageVersion.fromSdkConstraint(
+ dartSdkConstraint.originalConstraint,
+ );
+ }
/// Loads the pubspec for a package located in [packageDir].
///
@@ -332,7 +369,8 @@
Iterable<PackageRange>? dependencyOverrides,
Map? fields,
SourceRegistry? sources,
- Map<String, VersionConstraint>? sdkConstraints,
+ Map<String, SdkConstraint>? sdkConstraints,
+ Version? dartSdkVersion,
}) : _dependencies = dependencies == null
? null
: Map.fromIterable(dependencies, key: (range) => range.name),
@@ -342,12 +380,13 @@
_dependencyOverrides = dependencyOverrides == null
? null
: Map.fromIterable(dependencyOverrides, key: (range) => range.name),
- _sdkConstraints = sdkConstraints ??
- UnmodifiableMapView({'dart': VersionConstraint.any}),
+ _givenSdkConstraints = sdkConstraints ??
+ UnmodifiableMapView({'dart': SdkConstraint(VersionConstraint.any)}),
_includeDefaultSdkConstraint = false,
_sources = sources ??
((String? name) => throw StateError('No source registry given')),
_overridesFileFields = null,
+ _dartSdkVersion = dartSdkVersion ?? sdk.version,
super(
fields == null ? YamlMap() : YamlMap.wrap(fields),
name: name,
@@ -361,10 +400,17 @@
/// field, this will throw a [PubspecError].
///
/// [location] is the location from which this pubspec was loaded.
- Pubspec.fromMap(Map fields, this._sources,
- {YamlMap? overridesFields, String? expectedName, Uri? location})
- : _overridesFileFields = overridesFields,
+ Pubspec.fromMap(
+ Map fields,
+ this._sources, {
+ YamlMap? overridesFields,
+ String? expectedName,
+ Uri? location,
+ Version? dartSdkVersion,
+ }) : _overridesFileFields = overridesFields,
_includeDefaultSdkConstraint = true,
+ _givenSdkConstraints = null,
+ _dartSdkVersion = dartSdkVersion ?? sdk.version,
super(fields is YamlMap
? fields
: YamlMap.wrap(fields, sourceUrl: location)) {
@@ -390,6 +436,7 @@
Uri? location,
String? overridesFileContents,
Uri? overridesLocation,
+ Version? dartSdkVersion,
}) {
late final YamlMap pubspecMap;
YamlMap? overridesFileMap;
@@ -403,10 +450,14 @@
throw SourceSpanApplicationException(error.message, error.span);
}
- return Pubspec.fromMap(pubspecMap, sources,
- overridesFields: overridesFileMap,
- expectedName: expectedName,
- location: location);
+ return Pubspec.fromMap(
+ pubspecMap,
+ sources,
+ overridesFields: overridesFileMap,
+ expectedName: expectedName,
+ location: location,
+ dartSdkVersion: dartSdkVersion,
+ );
}
/// Ensures that [node] is a mapping.
@@ -445,7 +496,7 @@
collectError(() => publishTo);
collectError(() => executables);
collectError(() => falseSecrets);
- collectError(_ensureEnvironment);
+ collectError(() => sdkConstraints);
return errors;
}
}
@@ -558,17 +609,13 @@
/// Parses [node] to a [VersionConstraint].
///
-/// If or [defaultUpperBoundConstraint] is specified then it will be set as
-/// the max constraint if the original constraint doesn't have an upper
-/// bound and it is compatible with [defaultUpperBoundConstraint].
-///
-/// If [ignoreUpperBound] the max constraint is ignored.
+/// If or [defaultUpperBoundConstraint] is specified then it will be set as the
+/// max constraint if the original constraint doesn't have an upper bound and it
+/// is compatible with [defaultUpperBoundConstraint].
VersionConstraint _parseVersionConstraint(
- YamlNode? node, String? packageName, _FileType fileType,
- {VersionConstraint? defaultUpperBoundConstraint,
- bool ignoreUpperBound = false}) {
+ YamlNode? node, String? packageName, _FileType fileType) {
if (node?.value == null) {
- return defaultUpperBoundConstraint ?? VersionConstraint.any;
+ return VersionConstraint.any;
}
if (node!.value is! String) {
_error('A version constraint must be a string.', node.span);
@@ -576,17 +623,6 @@
return _wrapFormatException('version constraint', node.span, () {
var constraint = VersionConstraint.parse(node.value);
- if (defaultUpperBoundConstraint != null &&
- constraint is VersionRange &&
- constraint.max == null &&
- defaultUpperBoundConstraint.allowsAny(constraint)) {
- constraint = VersionConstraint.intersection(
- [constraint, defaultUpperBoundConstraint]);
- }
- if (ignoreUpperBound && constraint is VersionRange) {
- return VersionRange(
- min: constraint.min, includeMin: constraint.includeMin);
- }
return constraint;
}, packageName, fileType);
}
@@ -643,3 +679,40 @@
return 'pubspec override';
}
}
+
+/// There are special rules or interpreting SDK constraints, we take care to
+/// save the original constraint as found in pubspec.yaml.
+class SdkConstraint {
+ /// The constraint as written in the pubspec.yaml.
+ final VersionConstraint originalConstraint;
+
+ /// The constraint as interpreted by pub.
+ final VersionConstraint effectiveConstraint;
+
+ SdkConstraint(this.effectiveConstraint,
+ {VersionConstraint? originalConstraint})
+ : originalConstraint = originalConstraint ?? effectiveConstraint;
+
+ /// The language version of a constraint is determined from how it is written.
+ LanguageVersion get languageVersion =>
+ LanguageVersion.fromSdkConstraint(originalConstraint);
+
+ // We currently don't call this anywhere - so this is only for debugging
+ // purposes.
+ @override
+ String toString() {
+ if (effectiveConstraint != originalConstraint) {
+ return '$originalConstraint (interpreted as $effectiveConstraint)';
+ }
+ return effectiveConstraint.toString();
+ }
+
+ @override
+ operator ==(other) =>
+ other is SdkConstraint &&
+ other.effectiveConstraint == effectiveConstraint &&
+ other.originalConstraint == originalConstraint;
+
+ @override
+ int get hashCode => Object.hash(effectiveConstraint, originalConstraint);
+}
diff --git a/lib/src/solver/package_lister.dart b/lib/src/solver/package_lister.dart
index 1597e73..f3b63b6 100644
--- a/lib/src/solver/package_lister.dart
+++ b/lib/src/solver/package_lister.dart
@@ -218,8 +218,11 @@
for (var sdk in sdks.values) {
if (!_matchesSdkConstraint(pubspec, sdk)) {
return [
- Incompatibility([Term(depender, true)],
- SdkCause(pubspec.sdkConstraints[sdk.identifier], sdk))
+ Incompatibility(
+ [Term(depender, true)],
+ SdkCause(
+ pubspec.sdkConstraints[sdk.identifier]?.effectiveConstraint,
+ sdk))
];
}
}
@@ -321,12 +324,13 @@
alwaysIncludeMaxPreRelease: true);
_knownInvalidVersions = incompatibleVersions.union(_knownInvalidVersions);
- var sdkConstraint = await foldAsync(
+ var sdkConstraint = await foldAsync<VersionConstraint, PackageId>(
slice(versions, bounds.first, bounds.last + 1), VersionConstraint.empty,
- (dynamic previous, dynamic version) async {
+ (previous, version) async {
var pubspec = await _describeSafe(version);
return previous.union(
- pubspec.sdkConstraints[sdk.identifier] ?? VersionConstraint.any);
+ pubspec.sdkConstraints[sdk.identifier]?.effectiveConstraint ??
+ VersionConstraint.any);
});
return Incompatibility(
@@ -428,6 +432,7 @@
var constraint = pubspec.sdkConstraints[sdk.identifier];
if (constraint == null) return true;
- return sdk.isAvailable && constraint.allows(sdk.version!);
+ return sdk.isAvailable &&
+ constraint.effectiveConstraint.allows(sdk.version!);
}
}
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index 7d57c36..df3aa4a 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -63,7 +63,7 @@
var sdkConstraints = <String, VersionConstraint>{};
for (var pubspec in nonOverrides) {
pubspec.sdkConstraints.forEach((identifier, constraint) {
- sdkConstraints[identifier] = constraint
+ sdkConstraints[identifier] = constraint.effectiveConstraint
.intersect(sdkConstraints[identifier] ?? VersionConstraint.any);
});
}
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index 82de012..cbf930f 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -75,7 +75,7 @@
void validateSdkConstraint(Version firstSdkVersion, String message) {
// If the SDK constraint disallowed all versions before [firstSdkVersion],
// no error is necessary.
- if (entrypoint.root.pubspec.originalDartSdkConstraint
+ if (entrypoint.root.pubspec.dartSdkConstraint.originalConstraint
.intersect(VersionRange(max: firstSdkVersion))
.isEmpty) {
return;
@@ -96,7 +96,8 @@
? firstSdkVersion.nextPatch
: firstSdkVersion.nextBreaking);
- var newSdkConstraint = entrypoint.root.pubspec.originalDartSdkConstraint
+ var newSdkConstraint = entrypoint
+ .root.pubspec.dartSdkConstraint.originalConstraint
.intersect(allowedSdks);
if (newSdkConstraint.isEmpty) newSdkConstraint = allowedSdks;
diff --git a/lib/src/validator/flutter_plugin_format.dart b/lib/src/validator/flutter_plugin_format.dart
index a56f7df..00160ca 100644
--- a/lib/src/validator/flutter_plugin_format.dart
+++ b/lib/src/validator/flutter_plugin_format.dart
@@ -46,7 +46,7 @@
final flutterConstraint = pubspec.sdkConstraints['flutter'];
if (usesNewPluginFormat &&
(flutterConstraint == null ||
- flutterConstraint.allowsAny(VersionRange(
+ flutterConstraint.effectiveConstraint.allowsAny(VersionRange(
min: Version.parse('0.0.0'),
max: Version.parse('1.10.0'),
includeMin: true,
diff --git a/test/dart3_sdk_constraint_hack_test.dart b/test/dart3_sdk_constraint_hack_test.dart
new file mode 100644
index 0000000..7df3ee8
--- /dev/null
+++ b/test/dart3_sdk_constraint_hack_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
+
+void main() {
+ test('The bound of ">=2.11.0 <3.0.0" is not modified', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.11.0 <3.0.0'}
+ }),
+ ]).create();
+
+ await pubGet(
+ error: contains(
+ 'Because myapp requires SDK version >=2.11.0 <3.0.0, version solving failed'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ );
+ });
+ test('The bound of ">=2.12.0 <3.1.0" is not modified', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.12.0 <3.1.0'}
+ }),
+ ]).create();
+
+ await pubGet(
+ error: contains(
+ 'Because myapp requires SDK version >=2.12.0 <3.1.0, version solving failed'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ );
+ });
+
+ test('The bound of ">=2.11.0 <2.999.0" is not modified', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.11.0 <2.999.0'}
+ }),
+ ]).create();
+
+ await pubGet(
+ error: contains(
+ 'Because myapp requires SDK version >=2.11.0 <2.999.0, version solving failed'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ );
+ });
+
+ test('The bound of ">=2.11.0 <3.0.0-0.0" is not modified', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.11.0 <3.0.0-0.0'}
+ }),
+ ]).create();
+
+ await pubGet(
+ error: contains(
+ 'Because myapp requires SDK version >=2.11.0 <3.0.0-0.0, version solving failed'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+ );
+ });
+
+ test('The bound of ">=2.12.0 <3.0.0" is modified', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.12.0 <3.0.0'}
+ }),
+ ]).create();
+
+ await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'});
+ });
+
+ test('The bound of ">=2.12.0 <3.0.0-0" is modified', () async {
+ // For the upper bound <3.0.0 is treated as <3.0.0-0, so they both have
+ // the rewrite applied.
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.12.0 <3.0.0-0'}
+ }),
+ ]).create();
+
+ await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'});
+ });
+
+ test(
+ 'The bound of ">=2.12.0 <3.0.0" is not compatible with prereleases of dart 4',
+ () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=2.12.0 <3.0.0'}
+ }),
+ ]).create();
+
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '4.0.0-alpha'},
+ error: contains(
+ 'Because myapp requires SDK version >=2.12.0 <4.0.0, version solving failed.',
+ ),
+ );
+ });
+}
diff --git a/test/pubspec_test.dart b/test/pubspec_test.dart
index 1a9ac48..23079c5 100644
--- a/test/pubspec_test.dart
+++ b/test/pubspec_test.dart
@@ -6,7 +6,6 @@
import 'package:pub/src/exceptions.dart';
import 'package:pub/src/pubspec.dart';
-import 'package:pub/src/sdk.dart';
import 'package:pub/src/source/hosted.dart';
import 'package:pub/src/system_cache.dart';
import 'package:pub_semver/pub_semver.dart';
@@ -495,36 +494,23 @@
});
group('environment', () {
- /// Checking for the default SDK constraint based on the current SDK.
- void expectDefaultSdkConstraint(Pubspec pubspec) {
- var sdkVersionString = sdk.version.toString();
- if (sdkVersionString.startsWith('2.0.0') && sdk.version.isPreRelease) {
- expect(
- pubspec.sdkConstraints,
- containsPair(
- 'dart',
- VersionConstraint.parse(
- '${pubspec.sdkConstraints["dart"]} <=$sdkVersionString')));
- } else {
- expect(
- pubspec.sdkConstraints,
- containsPair(
- 'dart',
- VersionConstraint.parse(
- "${pubspec.sdkConstraints["dart"]} <2.0.0")));
- }
- }
-
test('allows an omitted environment', () {
var pubspec = Pubspec.parse('name: testing', sources);
- expectDefaultSdkConstraint(pubspec);
+ expect(
+ pubspec.dartSdkConstraint.effectiveConstraint,
+ VersionConstraint.parse('<2.0.0'),
+ );
+
expect(pubspec.sdkConstraints, isNot(contains('flutter')));
expect(pubspec.sdkConstraints, isNot(contains('fuchsia')));
});
test('default SDK constraint can be omitted with empty environment', () {
var pubspec = Pubspec.parse('', sources);
- expectDefaultSdkConstraint(pubspec);
+ expect(
+ pubspec.dartSdkConstraint.effectiveConstraint,
+ VersionConstraint.parse('<2.0.0'),
+ );
expect(pubspec.sdkConstraints, isNot(contains('flutter')));
expect(pubspec.sdkConstraints, isNot(contains('fuchsia')));
});
@@ -535,7 +521,10 @@
environment:
sdk: ">1.0.0"
''', sources);
- expectDefaultSdkConstraint(pubspec);
+ expect(
+ pubspec.dartSdkConstraint.effectiveConstraint,
+ VersionConstraint.parse('>1.0.0 <2.0.0'),
+ );
expect(pubspec.sdkConstraints, isNot(contains('flutter')));
expect(pubspec.sdkConstraints, isNot(contains('fuchsia')));
});
@@ -547,8 +536,12 @@
environment:
sdk: ">3.0.0"
''', sources);
- expect(pubspec.sdkConstraints,
- containsPair('dart', VersionConstraint.parse('>3.0.0')));
+ expect(
+ pubspec.sdkConstraints,
+ containsPair(
+ 'dart',
+ SdkConstraint(VersionConstraint.parse('>3.0.0')),
+ ));
expect(pubspec.sdkConstraints, isNot(contains('flutter')));
expect(pubspec.sdkConstraints, isNot(contains('fuchsia')));
});
@@ -565,12 +558,23 @@
flutter: ^0.1.2
fuchsia: ^5.6.7
''', sources);
- expect(pubspec.sdkConstraints,
- containsPair('dart', VersionConstraint.parse('>=1.2.3 <2.3.4')));
- expect(pubspec.sdkConstraints,
- containsPair('flutter', VersionConstraint.parse('>=0.1.2')));
- expect(pubspec.sdkConstraints,
- containsPair('fuchsia', VersionConstraint.parse('^5.6.7')));
+ expect(
+ pubspec.sdkConstraints,
+ containsPair('dart',
+ SdkConstraint(VersionConstraint.parse('>=1.2.3 <2.3.4'))));
+ expect(
+ pubspec.sdkConstraints,
+ containsPair(
+ 'flutter',
+ SdkConstraint(
+ VersionConstraint.parse('>=0.1.2'),
+ originalConstraint: VersionConstraint.parse('^0.1.2'),
+ )));
+ expect(
+ pubspec.sdkConstraints,
+ containsPair(
+ 'fuchsia', SdkConstraint(VersionConstraint.parse('^5.6.7'))),
+ );
});
test("throws if the sdk isn't a string", () {
diff --git a/test/upgrade/upgrade_null_safety_test.dart b/test/upgrade/upgrade_null_safety_test.dart
index 557c589..ad210d8 100644
--- a/test/upgrade/upgrade_null_safety_test.dart
+++ b/test/upgrade/upgrade_null_safety_test.dart
@@ -441,7 +441,7 @@
},
error: allOf(
contains('Because myapp depends on has_conflict >=2.0.0 which'),
- contains('requires SDK version >=2.13.0 <3.0.0,'),
+ contains('requires SDK version >=2.13.0 <4.0.0,'),
contains('version solving failed.'),
),
);
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index 69489a3..8ade3f6 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -1172,7 +1172,7 @@
await expectResolves(
environment: {'_PUB_TEST_SDK_VERSION': '2.0.0-dev.99'},
- // Log output should mention the PUB_ALLOW_RELEASE_SDK environment
+ // Log output should mention the PUB_ALLOW_PRERELEASE_SDK environment
// variable and mention the foo and bar packages specifically.
output: allOf(contains('PUB_ALLOW_PRERELEASE_SDK'),
anyOf(contains('bar, foo'))),