Handle build-versions when reformatting ranges (#3170)
diff --git a/lib/src/solver/reformat_ranges.dart b/lib/src/solver/reformat_ranges.dart
index bdb64b8..d40bd6f 100644
--- a/lib/src/solver/reformat_ranges.dart
+++ b/lib/src/solver/reformat_ranges.dart
@@ -4,6 +4,7 @@
// @dart=2.10
+import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import '../package_name.dart';
@@ -48,7 +49,7 @@
var range = term.package.constraint as VersionRange;
var min = _reformatMin(versions, range);
- var tuple = _reformatMax(versions, range);
+ var tuple = reformatMax(versions, range);
var max = tuple?.first;
var includeMax = tuple?.last;
@@ -84,10 +85,16 @@
/// Returns the new maximum version to use for [range] and whether that maximum
/// is inclusive, or `null` if it doesn't need to be reformatted.
-Pair<Version, bool> _reformatMax(List<PackageId> versions, VersionRange range) {
+@visibleForTesting
+Pair<Version, bool> reformatMax(List<PackageId> versions, VersionRange range) {
+ // This corresponds to the logic in the constructor of [VersionRange] with
+ // `alwaysIncludeMaxPreRelease = false` for discovering when a max-bound
+ // should not include prereleases.
+
if (range.max == null) return null;
if (range.includeMax) return null;
if (range.max.isPreRelease) return null;
+ if (range.max.build.isNotEmpty) return null;
if (range.min != null &&
range.min.isPreRelease &&
equalsIgnoringPreRelease(range.min, range.max)) {
diff --git a/test/reformat_ranges_test.dart b/test/reformat_ranges_test.dart
new file mode 100644
index 0000000..4af9cf7
--- /dev/null
+++ b/test/reformat_ranges_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2021, 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.
+
+// @dart=2.10
+
+import 'package:pub/src/package_name.dart';
+import 'package:pub/src/solver/reformat_ranges.dart';
+import 'package:pub/src/utils.dart';
+import 'package:pub_semver/pub_semver.dart';
+import 'package:test/test.dart';
+
+void main() {
+ test('reformatMax when max has a build identifier', () {
+ expect(
+ reformatMax(
+ [PackageId('abc', null, Version.parse('1.2.3'), null)],
+ VersionRange(
+ min: Version.parse('0.2.4'),
+ max: Version.parse('1.2.4'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(
+ Pair(
+ Version.parse('1.2.4-0'),
+ false,
+ ),
+ ),
+ );
+ expect(
+ reformatMax(
+ [PackageId('abc', null, Version.parse('1.2.4-3'), null)],
+ VersionRange(
+ min: Version.parse('0.2.4'),
+ max: Version.parse('1.2.4'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(
+ Pair(
+ Version.parse('1.2.4-3'),
+ true,
+ ),
+ ),
+ );
+ expect(
+ reformatMax(
+ [],
+ VersionRange(
+ max: Version.parse('1.2.4+1'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(null));
+ });
+}
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index e2136c5..caca301 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -31,6 +31,8 @@
group('override', override);
group('downgrade', downgrade);
group('features', features, skip: true);
+
+ group('regressions', regressions);
}
void basicGraph() {
@@ -3014,3 +3016,22 @@
expect(ids, isEmpty, reason: 'Expected no additional packages.');
}
+
+void regressions() {
+ test('reformatRanges with a build', () async {
+ await servePackages((b) {
+ b.serve('integration_test', '1.0.1',
+ deps: {'vm_service': '>= 4.2.0 <6.0.0'});
+ b.serve('integration_test', '1.0.2+2',
+ deps: {'vm_service': '>= 4.2.0 <7.0.0'});
+
+ b.serve('vm_service', '7.3.0');
+ });
+ await d.appDir({'integration_test': '^1.0.2'}).create();
+ await expectResolves(
+ error: contains(
+ 'Because no versions of integration_test match >=1.0.2 <1.0.2+2',
+ ),
+ );
+ });
+}