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', + ), + ); + }); +}