diff --git a/packages/flutter_tools/lib/src/commands/update_packages.dart b/packages/flutter_tools/lib/src/commands/update_packages.dart index 4ac5b356bf0a..3aa204362dc9 100644 --- a/packages/flutter_tools/lib/src/commands/update_packages.dart +++ b/packages/flutter_tools/lib/src/commands/update_packages.dart @@ -382,9 +382,9 @@ class UpdatePackagesCommand extends FlutterCommand { final File fakePackage = _pubspecFor(tempDir); fakePackage.createSync(); fakePackage.writeAsStringSync( - _generateFakePubspec( + generateFakePubspec( dependencies, - useAnyVersion: doUpgrade, + doUpgrade: doUpgrade, ), ); // Create a synthetic flutter SDK so that transitive flutter SDK @@ -1321,8 +1321,22 @@ class PubspecDependency extends PubspecLine { /// This generates the entry for this dependency for the pubspec.yaml for the /// fake package that we'll use to get the version numbers figured out. - void describeForFakePubspec(StringBuffer dependencies, StringBuffer overrides, { bool useAnyVersion = true}) { - final String versionToUse = useAnyVersion || version.isEmpty ? 'any' : version; + /// + /// When called with [doUpgrade] as [true], the version constrains will be set + /// to >= whatever the previous version was. If [doUpgrade] is [false], then + /// the previous version is used again as an exact pin. + void describeForFakePubspec(StringBuffer dependencies, StringBuffer overrides, { bool doUpgrade = true }) { + final String versionToUse; + // This should only happen when manually adding new dependencies; otherwise + // versions should always be pinned exactly + if (version.isEmpty || version == 'any') { + versionToUse = 'any'; + } else if (doUpgrade) { + // Must wrap in quotes for Yaml parsing + versionToUse = "'>= $version'"; + } else { + versionToUse = version; + } switch (kind) { case DependencyKind.unknown: case DependencyKind.overridden: @@ -1362,6 +1376,7 @@ class PubspecDependency extends PubspecLine { dependencies.writeln(' $name:'); dependencies.writeln(lockLine); } + break; } } @@ -1379,13 +1394,14 @@ File _pubspecFor(Directory directory) { /// Generates the source of a fake pubspec.yaml file given a list of /// dependencies. -String _generateFakePubspec( +@visibleForTesting +String generateFakePubspec( Iterable dependencies, { - bool useAnyVersion = false + bool doUpgrade = false }) { final StringBuffer result = StringBuffer(); final StringBuffer overrides = StringBuffer(); - final bool verbose = useAnyVersion; + final bool verbose = doUpgrade; result.writeln('name: flutter_update_packages'); result.writeln('environment:'); result.writeln(" sdk: '>=2.10.0 <3.0.0'"); @@ -1415,7 +1431,7 @@ String _generateFakePubspec( } for (final PubspecDependency dependency in dependencies) { if (!dependency.pointsToSdk) { - dependency.describeForFakePubspec(result, overrides, useAnyVersion: useAnyVersion); + dependency.describeForFakePubspec(result, overrides, doUpgrade: doUpgrade); } } result.write(overrides.toString()); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/update_packages_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/update_packages_test.dart index f6753df6bac4..89e2316bcdfb 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/update_packages_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/update_packages_test.dart @@ -12,6 +12,7 @@ import 'package:flutter_tools/src/commands/update_packages.dart'; import 'package:flutter_tools/src/dart/pub.dart'; import 'package:meta/meta.dart'; import 'package:test/fake.dart'; +import 'package:yaml/yaml.dart'; import '../../src/common.dart'; import '../../src/context.dart'; @@ -173,6 +174,47 @@ void main() { ), }); }); + + group('generateFakePubspec', () { + const String prevVersion = '1.2.0'; + testUsingContext('constrains package versions to >= previous version if doUpgrade: true', () { + final String pubspecSource = generateFakePubspec( + [ + PubspecDependency( + ' foo: $prevVersion', + 'foo', + '', + version: prevVersion, + sourcePath: '/path/to/pubspec.yaml', + kind: DependencyKind.normal, + isTransitive: false, + ), + ], + doUpgrade: true, + ); + final YamlMap pubspec = loadYaml(pubspecSource) as YamlMap; + expect((pubspec['dependencies'] as YamlMap)['foo'], '>= $prevVersion'); + }); + + testUsingContext('uses previous package versions doUpgrade: false', () { + final String pubspecSource = generateFakePubspec( + [ + PubspecDependency( + ' foo: $prevVersion', + 'foo', + '', + version: prevVersion, + sourcePath: '/path/to/pubspec.yaml', + kind: DependencyKind.normal, + isTransitive: false, + ), + ], + doUpgrade: false, + ); + final YamlMap pubspec = loadYaml(pubspecSource) as YamlMap; + expect((pubspec['dependencies'] as YamlMap)['foo'], prevVersion); + }); + }); } class FakePub extends Fake implements Pub {