Unverified Commit 0d95243f authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] Precache after channel switch (#118129)

Fixes https://github.com/flutter/flutter/issues/44118
parent 574a7181
...@@ -9,6 +9,8 @@ import '../runner/flutter_command.dart'; ...@@ -9,6 +9,8 @@ import '../runner/flutter_command.dart';
import '../runner/flutter_command_runner.dart'; import '../runner/flutter_command_runner.dart';
import '../version.dart'; import '../version.dart';
import 'upgrade.dart' show precacheArtifacts;
class ChannelCommand extends FlutterCommand { class ChannelCommand extends FlutterCommand {
ChannelCommand({ bool verboseHelp = false }) { ChannelCommand({ bool verboseHelp = false }) {
argParser.addFlag( argParser.addFlag(
...@@ -17,6 +19,12 @@ class ChannelCommand extends FlutterCommand { ...@@ -17,6 +19,12 @@ class ChannelCommand extends FlutterCommand {
help: 'Include all the available branches (including local branches) when listing channels.', help: 'Include all the available branches (including local branches) when listing channels.',
hide: !verboseHelp, hide: !verboseHelp,
); );
argParser.addFlag(
'cache-artifacts',
help: 'After switching channels, download all required binary artifacts. '
'This is the equivalent of running "flutter precache" with the "--all-platforms" flag.',
defaultsTo: true,
);
} }
@override @override
...@@ -134,6 +142,9 @@ class ChannelCommand extends FlutterCommand { ...@@ -134,6 +142,9 @@ class ChannelCommand extends FlutterCommand {
globals.printStatus('This is not an official channel. For a list of available channels, try "flutter channel".'); globals.printStatus('This is not an official channel. For a list of available channels, try "flutter channel".');
} }
await _checkout(branchName); await _checkout(branchName);
if (boolArg('cache-artifacts')) {
await precacheArtifacts(Cache.flutterRoot);
}
globals.printStatus("Successfully switched to flutter channel '$branchName'."); globals.printStatus("Successfully switched to flutter channel '$branchName'.");
globals.printStatus("To ensure that you're on the latest build from this channel, run 'flutter upgrade'"); globals.printStatus("To ensure that you're on the latest build from this channel, run 'flutter upgrade'");
} }
......
...@@ -22,8 +22,11 @@ class PrecacheCommand extends FlutterCommand { ...@@ -22,8 +22,11 @@ class PrecacheCommand extends FlutterCommand {
_platform = platform, _platform = platform,
_logger = logger, _logger = logger,
_featureFlags = featureFlags { _featureFlags = featureFlags {
argParser.addFlag('all-platforms', abbr: 'a', negatable: false, argParser.addFlag('all-platforms',
help: 'Precache artifacts for all host platforms.'); abbr: 'a',
negatable: false,
help: 'Precache artifacts for all host platforms.',
aliases: const <String>['all']);
argParser.addFlag('force', abbr: 'f', negatable: false, argParser.addFlag('force', abbr: 'f', negatable: false,
help: 'Force re-downloading of artifacts.'); help: 'Force re-downloading of artifacts.');
argParser.addFlag('android', argParser.addFlag('android',
......
...@@ -88,7 +88,6 @@ class UpgradeCommand extends FlutterCommand { ...@@ -88,7 +88,6 @@ class UpgradeCommand extends FlutterCommand {
@visibleForTesting @visibleForTesting
class UpgradeCommandRunner { class UpgradeCommandRunner {
String? workingDirectory; // set in runCommand() above String? workingDirectory; // set in runCommand() above
Future<FlutterCommandResult> runCommand({ Future<FlutterCommandResult> runCommand({
...@@ -205,7 +204,7 @@ class UpgradeCommandRunner { ...@@ -205,7 +204,7 @@ class UpgradeCommandRunner {
// Make sure the welcome message re-display is delayed until the end. // Make sure the welcome message re-display is delayed until the end.
final PersistentToolState persistentToolState = globals.persistentToolState!; final PersistentToolState persistentToolState = globals.persistentToolState!;
persistentToolState.setShouldRedisplayWelcomeMessage(false); persistentToolState.setShouldRedisplayWelcomeMessage(false);
await precacheArtifacts(); await precacheArtifacts(workingDirectory);
await updatePackages(flutterVersion); await updatePackages(flutterVersion);
await runDoctor(); await runDoctor();
// Force the welcome message to re-display following the upgrade. // Force the welcome message to re-display following the upgrade.
...@@ -318,27 +317,6 @@ class UpgradeCommandRunner { ...@@ -318,27 +317,6 @@ class UpgradeCommandRunner {
} }
} }
/// Update the engine repository and precache all artifacts.
///
/// Check for and download any engine and pkg/ updates. We run the 'flutter'
/// shell script reentrantly here so that it will download the updated
/// Dart and so forth if necessary.
Future<void> precacheArtifacts() async {
globals.printStatus('');
globals.printStatus('Upgrading engine...');
final int code = await globals.processUtils.stream(
<String>[
globals.fs.path.join('bin', 'flutter'), '--no-color', '--no-version-check', 'precache',
],
workingDirectory: workingDirectory,
allowReentrantFlutter: true,
environment: Map<String, String>.of(globals.platform.environment),
);
if (code != 0) {
throwToolExit(null, exitCode: code);
}
}
/// Update the user's packages. /// Update the user's packages.
Future<void> updatePackages(FlutterVersion flutterVersion) async { Future<void> updatePackages(FlutterVersion flutterVersion) async {
globals.printStatus(''); globals.printStatus('');
...@@ -367,3 +345,24 @@ class UpgradeCommandRunner { ...@@ -367,3 +345,24 @@ class UpgradeCommandRunner {
); );
} }
} }
/// Update the engine repository and precache all artifacts.
///
/// Check for and download any engine and pkg/ updates. We run the 'flutter'
/// shell script reentrantly here so that it will download the updated
/// Dart and so forth if necessary.
Future<void> precacheArtifacts([String? workingDirectory]) async {
globals.printStatus('');
globals.printStatus('Upgrading engine...');
final int code = await globals.processUtils.stream(
<String>[
globals.fs.path.join('bin', 'flutter'), '--no-color', '--no-version-check', 'precache',
],
allowReentrantFlutter: true,
environment: Map<String, String>.of(globals.platform.environment),
workingDirectory: workingDirectory,
);
if (code != 0) {
throwToolExit(null, exitCode: code);
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
...@@ -327,7 +328,7 @@ void main() { ...@@ -327,7 +328,7 @@ void main() {
environment: <String, String>{'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment} environment: <String, String>{'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment}
), ),
); );
await realCommandRunner.precacheArtifacts(); await precacheArtifacts();
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
...@@ -408,6 +409,7 @@ void main() { ...@@ -408,6 +409,7 @@ void main() {
late FakeProcessManager fakeProcessManager; late FakeProcessManager fakeProcessManager;
late Directory tempDir; late Directory tempDir;
late File flutterToolState; late File flutterToolState;
late FileSystem fs;
setUp(() { setUp(() {
Cache.disableLocking(); Cache.disableLocking();
...@@ -424,7 +426,8 @@ void main() { ...@@ -424,7 +426,8 @@ void main() {
stdout: 'v1.12.16-19-gb45b676af', stdout: 'v1.12.16-19-gb45b676af',
), ),
]); ]);
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_upgrade_test.'); fs = MemoryFileSystem.test();
tempDir = fs.systemTempDirectory.createTempSync('flutter_upgrade_test.');
flutterToolState = tempDir.childFile('.flutter_tool_state'); flutterToolState = tempDir.childFile('.flutter_tool_state');
}); });
...@@ -434,6 +437,7 @@ void main() { ...@@ -434,6 +437,7 @@ void main() {
}); });
testUsingContext('upgrade continue prints welcome message', () async { testUsingContext('upgrade continue prints welcome message', () async {
fakeProcessManager = FakeProcessManager.any();
final UpgradeCommand upgradeCommand = UpgradeCommand( final UpgradeCommand upgradeCommand = UpgradeCommand(
verboseHelp: false, verboseHelp: false,
commandRunner: fakeCommandRunner, commandRunner: fakeCommandRunner,
...@@ -451,6 +455,7 @@ void main() { ...@@ -451,6 +455,7 @@ void main() {
containsPair('redisplay-welcome-message', true), containsPair('redisplay-welcome-message', true),
); );
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs,
FlutterVersion: () => FakeFlutterVersion(), FlutterVersion: () => FakeFlutterVersion(),
ProcessManager: () => fakeProcessManager, ProcessManager: () => fakeProcessManager,
PersistentToolState: () => PersistentToolState.test( PersistentToolState: () => PersistentToolState.test(
...@@ -479,9 +484,6 @@ class FakeUpgradeCommandRunner extends UpgradeCommandRunner { ...@@ -479,9 +484,6 @@ class FakeUpgradeCommandRunner extends UpgradeCommandRunner {
@override @override
Future<void> attemptReset(String newRevision) async {} Future<void> attemptReset(String newRevision) async {}
@override
Future<void> precacheArtifacts() async {}
@override @override
Future<void> updatePackages(FlutterVersion flutterVersion) async {} Future<void> updatePackages(FlutterVersion flutterVersion) async {}
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:flutter_tools/executable.dart' as executable; import 'package:flutter_tools/executable.dart' as executable;
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/commands/analyze.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart'; import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
...@@ -15,6 +16,14 @@ import '../src/testbed.dart'; ...@@ -15,6 +16,14 @@ import '../src/testbed.dart';
import 'runner/utils.dart'; import 'runner/utils.dart';
void main() { void main() {
setUpAll(() {
Cache.disableLocking();
});
tearDownAll(() {
Cache.enableLocking();
});
test('Help for command line arguments is consistently styled and complete', () => Testbed().run(() { test('Help for command line arguments is consistently styled and complete', () => Testbed().run(() {
final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: true); final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: true);
executable.generateCommands( executable.generateCommands(
......
...@@ -242,16 +242,19 @@ void main() { ...@@ -242,16 +242,19 @@ void main() {
}); });
testUsingContext('can switch channels', () async { testUsingContext('can switch channels', () async {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
const FakeCommand( FakeCommand(
command: <String>['git', 'fetch'], command: <String>['git', 'fetch'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'], command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'checkout', 'beta', '--'] command: <String>['git', 'checkout', 'beta', '--']
), ),
FakeCommand(
command: <String>['bin/flutter', '--no-color', '--no-version-check', 'precache'],
),
]); ]);
final ChannelCommand command = ChannelCommand(); final ChannelCommand command = ChannelCommand();
...@@ -265,16 +268,19 @@ void main() { ...@@ -265,16 +268,19 @@ void main() {
); );
expect(testLogger.errorText, hasLength(0)); expect(testLogger.errorText, hasLength(0));
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
const FakeCommand( FakeCommand(
command: <String>['git', 'fetch'], command: <String>['git', 'fetch'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/stable'], command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/stable'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'checkout', 'stable', '--'] command: <String>['git', 'checkout', 'stable', '--']
), ),
FakeCommand(
command: <String>['bin/flutter', '--no-color', '--no-version-check', 'precache'],
),
]); ]);
await runner.run(<String>['channel', 'stable']); await runner.run(<String>['channel', 'stable']);
...@@ -286,16 +292,19 @@ void main() { ...@@ -286,16 +292,19 @@ void main() {
}); });
testUsingContext('switching channels prompts to run flutter upgrade', () async { testUsingContext('switching channels prompts to run flutter upgrade', () async {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
const FakeCommand( FakeCommand(
command: <String>['git', 'fetch'], command: <String>['git', 'fetch'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'], command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'checkout', 'beta', '--'] command: <String>['git', 'checkout', 'beta', '--']
), ),
FakeCommand(
command: <String>['bin/flutter', '--no-color', '--no-version-check', 'precache'],
),
]); ]);
final ChannelCommand command = ChannelCommand(); final ChannelCommand command = ChannelCommand();
...@@ -322,16 +331,19 @@ void main() { ...@@ -322,16 +331,19 @@ void main() {
// This verifies that bug https://github.com/flutter/flutter/issues/21134 // This verifies that bug https://github.com/flutter/flutter/issues/21134
// doesn't return. // doesn't return.
testUsingContext('removes version stamp file when switching channels', () async { testUsingContext('removes version stamp file when switching channels', () async {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
const FakeCommand( FakeCommand(
command: <String>['git', 'fetch'], command: <String>['git', 'fetch'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'], command: <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/beta'],
), ),
const FakeCommand( FakeCommand(
command: <String>['git', 'checkout', 'beta', '--'] command: <String>['git', 'checkout', 'beta', '--']
), ),
FakeCommand(
command: <String>['bin/flutter', '--no-color', '--no-version-check', 'precache'],
),
]); ]);
final File versionCheckFile = globals.cache.getStampFileFor( final File versionCheckFile = globals.cache.getStampFileFor(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment