Have executableForCommand rerun pub get if sdk changed minor version (#3652)
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 76bcdcd..4626559 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -625,8 +625,10 @@
// * Force `pub get` if a path dependency has changed language version.
_checkPackageConfigUpToDate();
touch(packageConfigPath);
- } else if (touchedLockFile) {
- touch(packageConfigPath);
+ } else {
+ if (touchedLockFile) {
+ touch(packageConfigPath);
+ }
}
for (var match in _sdkConstraint.allMatches(lockFileText)) {
@@ -645,6 +647,12 @@
"dependencies' SDK constraints. Please run \"$topLevelProgram pub get\" again.");
}
}
+ // We want to do ensure a pub get gets run when updating a minor version of
+ // the Dart SDK.
+ //
+ // Putting this check last because it leads to less specific messages than
+ // the 'incompatible sdk' check above.
+ _checkPackageConfigSameDartSdk();
}
/// Determines whether or not the lockfile is out of date with respect to the
@@ -840,6 +848,26 @@
}
}
+ /// Checks whether or not the `.dart_tool/package_config.json` file is was
+ /// generated by a different sdk down changes in minor versions.
+ ///
+ /// For pre-releases we always consider the package_config.json out of date
+ /// when the version changes.
+ ///
+ /// Throws [DataException], if `.dart_tool/package_config.json` the version
+ /// changed sufficiently.
+ void _checkPackageConfigSameDartSdk() {
+ final generatorVersion = packageConfig.generatorVersion;
+ if (generatorVersion == null ||
+ generatorVersion.major != sdk.version.major ||
+ generatorVersion.minor != sdk.version.minor ||
+ generatorVersion.isPreRelease ||
+ sdk.version.isPreRelease) {
+ dataError('The sdk was updated since last package resolution. Please run '
+ '"$topLevelProgram pub get" again.');
+ }
+ }
+
/// If the entrypoint uses the old-style `.pub` cache directory, migrates it
/// to the new-style `.dart_tool/pub` directory.
void migrateCache() {
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index b3d8be6..e895a3c 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -307,7 +307,8 @@
try {
// TODO(sigurdm): it would be nicer with a 'isUpToDate' function.
entrypoint.assertUpToDate();
- } on DataException {
+ } on DataException catch (e) {
+ log.fine('Resolution not up to date: ${e.message}. Redoing.');
try {
await warningsOnlyUnlessTerminal(
() => entrypoint.acquireDependencies(
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart
index 9f74405..4419c15 100644
--- a/test/embedding/embedding_test.dart
+++ b/test/embedding/embedding_test.dart
@@ -258,6 +258,67 @@
environment: getPubTestEnvironment(),
);
});
+
+ test('`embedding run` does `pub get` if sdk updated', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '^2.18.0'},
+ 'dependencies': {'foo': '^1.0.0'}
+ }),
+ d.dir('bin', [
+ d.file('myapp.dart', 'main() {print(42);}'),
+ ])
+ ]).create();
+
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {'sdk': '^2.18.0'}
+ });
+
+ await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.18.3'});
+ // Deleting the version-listing cache will cause it to be refetched, and the
+ // warning will happen.
+ File(p.join(globalServer.cachingPath, '.cache', 'foo-versions.json'))
+ .deleteSync();
+ server.serve('foo', '1.0.1', pubspec: {
+ 'environment': {'sdk': '^2.18.0'}
+ });
+
+ final buffer = StringBuffer();
+
+ // Just changing the patch version should not trigger a pub get.
+ await runEmbeddingToBuffer(
+ ['--verbose', 'run', 'myapp'],
+ buffer,
+ workingDirectory: d.path(appPath),
+ environment: {'_PUB_TEST_SDK_VERSION': '2.18.4'},
+ );
+
+ expect(
+ buffer.toString(),
+ allOf(contains('42'), isNot(contains('Resolving dependencies'))),
+ );
+
+ File(p.join(globalServer.cachingPath, '.cache', 'foo-versions.json'));
+ buffer.clear();
+
+ // Changing the minor version should.
+ await runEmbeddingToBuffer(
+ ['--verbose', 'run', 'myapp'],
+ buffer,
+ workingDirectory: d.path(appPath),
+ environment: {'_PUB_TEST_SDK_VERSION': '2.19.3'},
+ );
+ expect(
+ buffer.toString(),
+ allOf(
+ contains('42'),
+ contains('Resolving dependencies'),
+ contains('1.0.1 available'),
+ ),
+ );
+ });
}
String _filter(String input) {
diff --git a/tool/test-bin/pub_command_runner.dart b/tool/test-bin/pub_command_runner.dart
index 3c1bef9..756cd91 100644
--- a/tool/test-bin/pub_command_runner.dart
+++ b/tool/test-bin/pub_command_runner.dart
@@ -33,6 +33,31 @@
}
}
+class RunCommand extends Command<int> {
+ @override
+ String get name => 'run';
+
+ @override
+ String get description => 'runs a dart app';
+
+ @override
+ Future<int> run() async {
+ final executable = await getExecutableForCommand(argResults!.rest.first);
+ final packageConfig = executable.packageConfig;
+ final process = await Process.start(
+ Platform.executable,
+ [
+ if (packageConfig != null) '--packages=$packageConfig',
+ executable.executable,
+ ...argResults!.rest.skip(1)
+ ],
+ mode: ProcessStartMode.inheritStdio,
+ );
+
+ return await process.exitCode;
+ }
+}
+
class Runner extends CommandRunner<int> {
late ArgResults _options;
@@ -44,6 +69,7 @@
addCommand(
pubCommand(analytics: analytics, isVerbose: () => _options['verbose'])
..addSubcommand(ThrowingCommand()));
+ addCommand(RunCommand());
argParser.addFlag('verbose');
}
@@ -51,7 +77,9 @@
Future<int> run(Iterable<String> args) async {
try {
_options = super.parse(args);
-
+ if (_options['verbose']) {
+ log.verbosity = log.Verbosity.all;
+ }
return await runCommand(_options);
} on UsageException catch (error) {
log.exception(error);