diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index 19e91f818f5..e941d7c4546 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart @@ -38,6 +38,11 @@ class UpgradeCommand extends FlutterCommand { 'working-directory', hide: true, help: 'Override the upgrade working directory for integration testing.' + ) + ..addFlag( + 'verify-only', + help: 'Verifies for any new flutter update, without fetching the update.', + negatable: false, ); } @@ -63,6 +68,7 @@ class UpgradeCommand extends FlutterCommand { flutterVersion: stringArg('working-directory') == null ? globals.flutterVersion : FlutterVersion(const SystemClock(), _commandRunner.workingDirectory), + verifyOnly: boolArg('verify-only'), ); } } @@ -78,6 +84,7 @@ class UpgradeCommandRunner { @required bool testFlow, @required GitTagVersion gitTagVersion, @required FlutterVersion flutterVersion, + @required bool verifyOnly, }) async { if (!continueFlow) { await runCommandFirstHalf( @@ -85,6 +92,7 @@ class UpgradeCommandRunner { gitTagVersion: gitTagVersion, flutterVersion: flutterVersion, testFlow: testFlow, + verifyOnly: verifyOnly, ); } else { await runCommandSecondHalf(flutterVersion); @@ -97,12 +105,24 @@ class UpgradeCommandRunner { @required GitTagVersion gitTagVersion, @required FlutterVersion flutterVersion, @required bool testFlow, + @required bool verifyOnly, }) async { final String upstreamRevision = await fetchRemoteRevision(); if (flutterVersion.frameworkRevision == upstreamRevision) { globals.printStatus('Flutter is already up to date on channel ${flutterVersion.channel}'); globals.printStatus('$flutterVersion'); return; + } else if (verifyOnly) { + globals.printStatus('A new version of Flutter is available on channel ${flutterVersion.channel}\n'); + // TODO(fujino): use a [FlutterVersion] once that class supports arbitrary revisions. + globals.printStatus('The latest revision: $upstreamRevision', emphasis: true); + globals.printStatus('Your current version: ${flutterVersion.frameworkRevision}\n'); + globals.printStatus('To upgrade now, run "flutter upgrade".'); + if (flutterVersion.channel == 'stable') { + globals.printStatus('\nSee the announcement and release notes:'); + globals.printStatus('https://flutter.dev/docs/development/tools/sdk/release-notes'); + } + return; } if (!force && gitTagVersion == const GitTagVersion.unknown()) { // If the commit is a recognized branch and not master, diff --git a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart index 3f68f95bb15..8e8d75b2dc1 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart @@ -54,6 +54,7 @@ void main() { testFlow: false, gitTagVersion: const GitTagVersion.unknown(), flutterVersion: flutterVersion, + verifyOnly: false, ); expect(result, throwsToolExit()); expect(processManager.hasRemainingExpectations, isFalse); @@ -69,6 +70,7 @@ void main() { testFlow: false, gitTagVersion: gitTagVersion, flutterVersion: flutterVersion, + verifyOnly: false, ); expect(result, throwsToolExit()); expect(processManager.hasRemainingExpectations, isFalse); @@ -87,6 +89,7 @@ void main() { testFlow: false, gitTagVersion: gitTagVersion, flutterVersion: flutterVersion, + verifyOnly: false, ); expect(await result, FlutterCommandResult.success()); expect(testLogger.statusText, contains('Flutter is already up to date')); @@ -96,6 +99,28 @@ void main() { Platform: () => fakePlatform, }); + testUsingContext('Correctly provides upgrade version on verify only', () async { + const String revision = 'abc123'; + when(flutterVersion.frameworkRevision).thenReturn(revision); + fakeCommandRunner.alreadyUpToDate = false; + final Future result = fakeCommandRunner.runCommand( + force: false, + continueFlow: false, + testFlow: false, + gitTagVersion: gitTagVersion, + flutterVersion: flutterVersion, + verifyOnly: true, + ); + expect(await result, FlutterCommandResult.success()); + expect(testLogger.statusText, contains('A new version of Flutter is available')); + expect(testLogger.statusText, contains(fakeCommandRunner.remoteRevision)); + expect(testLogger.statusText, contains(revision)); + expect(processManager.hasRemainingExpectations, isFalse); + }, overrides: { + ProcessManager: () => processManager, + Platform: () => fakePlatform, + }); + testUsingContext('fetchRemoteRevision returns revision if git succeeds', () async { const String revision = 'abc123'; @@ -255,6 +280,7 @@ void main() { testFlow: false, gitTagVersion: const GitTagVersion.unknown(), flutterVersion: flutterVersion, + verifyOnly: false, ); expect(await result, FlutterCommandResult.success()); expect(processManager.hasRemainingExpectations, isFalse); @@ -272,6 +298,7 @@ void main() { testFlow: false, gitTagVersion: gitTagVersion, flutterVersion: flutterVersion, + verifyOnly: false, ); expect(await result, FlutterCommandResult.success()); expect(processManager.hasRemainingExpectations, isFalse); @@ -287,6 +314,7 @@ void main() { testFlow: false, gitTagVersion: gitTagVersion, flutterVersion: flutterVersion, + verifyOnly: false, ); expect(await result, FlutterCommandResult.success()); expect(processManager.hasRemainingExpectations, isFalse);