From 410d9921bc472fdf720e06fc158126e3a506c879 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 5 Jan 2022 16:50:19 -0800 Subject: [PATCH] Migrate emulators, packages, upgrade, and downgrade to null safety (#95712) --- .../lib/src/commands/downgrade.dart | 75 ++++++++++--------- .../lib/src/commands/emulators.dart | 39 +++++----- .../lib/src/commands/packages.dart | 44 +++++------ .../lib/src/commands/upgrade.dart | 56 +++++++------- packages/flutter_tools/lib/src/dart/pub.dart | 4 +- 5 files changed, 112 insertions(+), 106 deletions(-) diff --git a/packages/flutter_tools/lib/src/commands/downgrade.dart b/packages/flutter_tools/lib/src/commands/downgrade.dart index cb5684debc0..bb0eb428a9d 100644 --- a/packages/flutter_tools/lib/src/commands/downgrade.dart +++ b/packages/flutter_tools/lib/src/commands/downgrade.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:process/process.dart'; import '../base/common.dart'; @@ -31,13 +29,13 @@ import '../version.dart'; class DowngradeCommand extends FlutterCommand { DowngradeCommand({ bool verboseHelp = false, - PersistentToolState persistentToolState, - Logger logger, - ProcessManager processManager, - FlutterVersion flutterVersion, - Terminal terminal, - Stdio stdio, - FileSystem fileSystem, + PersistentToolState? persistentToolState, + Logger? logger, + ProcessManager? processManager, + FlutterVersion? flutterVersion, + Terminal? terminal, + Stdio? stdio, + FileSystem? fileSystem, }) : _terminal = terminal, _flutterVersion = flutterVersion, _persistentToolState = persistentToolState, @@ -61,14 +59,14 @@ class DowngradeCommand extends FlutterCommand { ); } - Terminal _terminal; - FlutterVersion _flutterVersion; - PersistentToolState _persistentToolState; - ProcessUtils _processUtils; - ProcessManager _processManager; - Logger _logger; - Stdio _stdio; - FileSystem _fileSystem; + Terminal? _terminal; + FlutterVersion? _flutterVersion; + PersistentToolState? _persistentToolState; + ProcessUtils? _processUtils; + ProcessManager? _processManager; + Logger? _logger; + Stdio? _stdio; + FileSystem? _fileSystem; @override String get description => 'Downgrade Flutter to the last active version for the current channel.'; @@ -89,25 +87,26 @@ class DowngradeCommand extends FlutterCommand { _flutterVersion ??= globals.flutterVersion; _persistentToolState ??= globals.persistentToolState; _processManager ??= globals.processManager; - _processUtils ??= ProcessUtils(processManager: _processManager, logger: _logger); + _processUtils ??= ProcessUtils(processManager: _processManager!, logger: _logger!); _stdio ??= globals.stdio; _fileSystem ??= globals.fs; - String workingDirectory = Cache.flutterRoot; - if (argResults.wasParsed('working-directory')) { - workingDirectory = stringArg('working-directory'); + String workingDirectory = Cache.flutterRoot!; + if (argResults!.wasParsed('working-directory')) { + workingDirectory = stringArg('working-directory')!; _flutterVersion = FlutterVersion(workingDirectory: workingDirectory); } - final String currentChannel = _flutterVersion.channel; - final Channel channel = getChannelForName(currentChannel); + final String currentChannel = _flutterVersion!.channel; + final Channel? channel = getChannelForName(currentChannel); if (channel == null) { throwToolExit( 'Flutter is not currently on a known channel. Use "flutter channel " ' 'to switch to an official channel.', ); } - final String lastFlutterVersion = _persistentToolState.lastActiveVersion(channel); - final String currentFlutterVersion = _flutterVersion.frameworkRevision; + final PersistentToolState persistentToolState = _persistentToolState!; + final String? lastFlutterVersion = persistentToolState.lastActiveVersion(channel); + final String? currentFlutterVersion = _flutterVersion?.frameworkRevision; if (lastFlutterVersion == null || currentFlutterVersion == lastFlutterVersion) { final String trailing = await _createErrorMessage(workingDirectory, channel); throwToolExit( @@ -117,7 +116,8 @@ class DowngradeCommand extends FlutterCommand { } // Detect unknown versions. - final RunResult parseResult = await _processUtils.run([ + final ProcessUtils processUtils = _processUtils!; + final RunResult parseResult = await processUtils.run([ 'git', 'describe', '--tags', lastFlutterVersion, ], workingDirectory: workingDirectory); if (parseResult.exitCode != 0) { @@ -126,25 +126,28 @@ class DowngradeCommand extends FlutterCommand { final String humanReadableVersion = parseResult.stdout; // If there is a terminal attached, prompt the user to confirm the downgrade. - if (_stdio.hasTerminal && boolArg('prompt')) { - _terminal.usesTerminalUi = true; - final String result = await _terminal.promptForCharInput( + final Stdio stdio = _stdio!; + final Terminal terminal = _terminal!; + final Logger logger = _logger!; + if (stdio.hasTerminal && boolArg('prompt')) { + terminal.usesTerminalUi = true; + final String result = await terminal.promptForCharInput( const ['y', 'n'], prompt: 'Downgrade flutter to version $humanReadableVersion?', - logger: _logger, + logger: logger, ); if (result == 'n') { return FlutterCommandResult.success(); } } else { - _logger.printStatus('Downgrading Flutter to version $humanReadableVersion'); + logger.printStatus('Downgrading Flutter to version $humanReadableVersion'); } // To downgrade the tool, we perform a git checkout --hard, and then // switch channels. The version recorded must have existed on that branch // so this operation is safe. try { - await _processUtils.run( + await processUtils.run( ['git', 'reset', '--hard', lastFlutterVersion], throwOnError: true, workingDirectory: workingDirectory, @@ -158,7 +161,7 @@ class DowngradeCommand extends FlutterCommand { ); } try { - await _processUtils.run( + await processUtils.run( ['git', 'checkout', currentChannel, '--'], throwOnError: true, workingDirectory: workingDirectory, @@ -172,7 +175,7 @@ class DowngradeCommand extends FlutterCommand { ); } await FlutterVersion.resetFlutterVersionFreshnessCheck(); - _logger.printStatus('Success'); + logger.printStatus('Success'); return FlutterCommandResult.success(); } @@ -183,11 +186,11 @@ class DowngradeCommand extends FlutterCommand { if (channel == currentChannel) { continue; } - final String sha = _persistentToolState.lastActiveVersion(channel); + final String? sha = _persistentToolState?.lastActiveVersion(channel); if (sha == null) { continue; } - final RunResult parseResult = await _processUtils.run([ + final RunResult parseResult = await _processUtils!.run([ 'git', 'describe', '--tags', sha, ], workingDirectory: workingDirectory); if (parseResult.exitCode == 0) { diff --git a/packages/flutter_tools/lib/src/commands/emulators.dart b/packages/flutter_tools/lib/src/commands/emulators.dart index 6b520dc8178..89a3b7450b0 100644 --- a/packages/flutter_tools/lib/src/commands/emulators.dart +++ b/packages/flutter_tools/lib/src/commands/emulators.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 +import 'package:args/args.dart'; import '../base/common.dart'; import '../base/utils.dart'; @@ -39,22 +39,22 @@ class EmulatorsCommand extends FlutterCommand { @override Future runCommand() async { - if (globals.doctor.workflows.every((Workflow w) => !w.canListEmulators)) { + if (globals.doctor!.workflows.every((Workflow w) => !w.canListEmulators)) { throwToolExit( 'Unable to find any emulator sources. Please ensure you have some\n' 'Android AVD images ${globals.platform.isMacOS ? 'or an iOS Simulator ' : ''}available.', exitCode: 1); } - - if (argResults.wasParsed('launch')) { - final bool coldBoot = argResults.wasParsed('cold'); - await _launchEmulator(stringArg('launch'), coldBoot: coldBoot); - } else if (argResults.wasParsed('create')) { + final ArgResults argumentResults = argResults!; + if (argumentResults.wasParsed('launch')) { + final bool coldBoot = argumentResults.wasParsed('cold'); + await _launchEmulator(stringArg('launch')!, coldBoot: coldBoot); + } else if (argumentResults.wasParsed('create')) { await _createEmulator(name: stringArg('name')); } else { - final String searchText = - argResults.rest != null && argResults.rest.isNotEmpty - ? argResults.rest.first + final String? searchText = + argumentResults.rest != null && argumentResults.rest.isNotEmpty + ? argumentResults.rest.first : null; await _listEmulators(searchText); } @@ -62,9 +62,9 @@ class EmulatorsCommand extends FlutterCommand { return FlutterCommandResult.success(); } - Future _launchEmulator(String id, {bool coldBoot}) async { + Future _launchEmulator(String id, { required bool coldBoot }) async { final List emulators = - await emulatorManager.getEmulatorsMatching(id); + await emulatorManager!.getEmulatorsMatching(id); if (emulators.isEmpty) { globals.printStatus("No emulator found that matches '$id'."); @@ -78,23 +78,26 @@ class EmulatorsCommand extends FlutterCommand { } } - Future _createEmulator({ String name }) async { + Future _createEmulator({ String? name }) async { final CreateEmulatorResult createResult = - await emulatorManager.createEmulator(name: name); + await emulatorManager!.createEmulator(name: name); if (createResult.success) { globals.printStatus("Emulator '${createResult.emulatorName}' created successfully."); } else { globals.printStatus("Failed to create emulator '${createResult.emulatorName}'.\n"); - globals.printStatus(createResult.error.trim()); + final String? error = createResult.error; + if (error != null) { + globals.printStatus(error.trim()); + } _printAdditionalInfo(); } } - Future _listEmulators(String searchText) async { + Future _listEmulators(String? searchText) async { final List emulators = searchText == null - ? await emulatorManager.getAllAvailableEmulators() - : await emulatorManager.getEmulatorsMatching(searchText); + ? await emulatorManager!.getAllAvailableEmulators() + : await emulatorManager!.getEmulatorsMatching(searchText); if (emulators.isEmpty) { globals.printStatus('No emulators available.'); diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart index 71cc3aa0dc9..796084f171d 100644 --- a/packages/flutter_tools/lib/src/commands/packages.dart +++ b/packages/flutter_tools/lib/src/commands/packages.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:args/args.dart'; import '../base/common.dart'; @@ -55,7 +53,7 @@ class PackagesCommand extends FlutterCommand { String get category => FlutterCommandCategory.project; @override - Future runCommand() async => null; + Future runCommand() async => FlutterCommandResult.fail(); } class PackagesGetCommand extends FlutterCommand { @@ -79,15 +77,16 @@ class PackagesGetCommand extends FlutterCommand { @override String get invocation { - return '${runner.executableName} pub $name []'; + return '${runner!.executableName} pub $name []'; } /// The pub packages usage values are incorrect since these are calculated/sent /// before pub get completes. This needs to be performed after dependency resolution. @override Future get usageValues async { - final String workingDirectory = argResults.rest.length == 1 ? argResults.rest[0] : null; - final String target = findProjectRoot(globals.fs, workingDirectory); + final ArgResults argumentResults = argResults!; + final String? workingDirectory = argumentResults.rest.length == 1 ? argumentResults.rest[0] : null; + final String? target = findProjectRoot(globals.fs, workingDirectory); if (target == null) { return const CustomDimensions(); } @@ -118,7 +117,7 @@ class PackagesGetCommand extends FlutterCommand { Future _runPubGet(String directory, FlutterProject flutterProject) async { if (flutterProject.manifest.generateSyntheticPackage) { final Environment environment = Environment( - artifacts: globals.artifacts, + artifacts: globals.artifacts!, logger: globals.logger, cacheDir: globals.cache.getRoot(), engineVersion: globals.flutterVersion.engineRevision, @@ -159,12 +158,13 @@ class PackagesGetCommand extends FlutterCommand { @override Future runCommand() async { - if (argResults.rest.length > 1) { + final ArgResults argumentResults = argResults!; + if (argumentResults.rest.length > 1) { throwToolExit('Too many arguments.\n$usage'); } - final String workingDirectory = argResults.rest.length == 1 ? argResults.rest[0] : null; - final String target = findProjectRoot(globals.fs, workingDirectory); + final String? workingDirectory = argumentResults.rest.length == 1 ? argumentResults.rest[0] : null; + final String? target = findProjectRoot(globals.fs, workingDirectory); if (target == null) { throwToolExit( 'Expected to find project root in ' @@ -207,12 +207,12 @@ class PackagesTestCommand extends FlutterCommand { @override String get invocation { - return '${runner.executableName} pub test []'; + return '${runner!.executableName} pub test []'; } @override Future runCommand() async { - await pub.batch(['run', 'test', ...argResults.rest], context: PubContext.runTest, retry: false); + await pub.batch(['run', 'test', ...argResults!.rest], context: PubContext.runTest, retry: false); return FlutterCommandResult.success(); } } @@ -241,12 +241,12 @@ class PackagesForwardCommand extends FlutterCommand { @override String get invocation { - return '${runner.executableName} pub $_commandName []'; + return '${runner!.executableName} pub $_commandName []'; } @override Future runCommand() async { - final List subArgs = argResults.rest.toList() + final List subArgs = argResults!.rest.toList() ..removeWhere((String arg) => arg == '--'); await pub.interactively([_commandName, ...subArgs], stdio: globals.stdio); return FlutterCommandResult.success(); @@ -268,12 +268,12 @@ class PackagesPassthroughCommand extends FlutterCommand { @override String get invocation { - return '${runner.executableName} packages pub []'; + return '${runner!.executableName} packages pub []'; } @override Future runCommand() async { - await pub.interactively(argResults.rest, stdio: globals.stdio); + await pub.interactively(argResults!.rest, stdio: globals.stdio); return FlutterCommandResult.success(); } } @@ -298,14 +298,14 @@ class PackagesInteractiveGetCommand extends FlutterCommand { @override String get invocation { - return '${runner.executableName} pub $_commandName []'; + return '${runner!.executableName} pub $_commandName []'; } @override Future runCommand() async { - List rest = argResults.rest; + List rest = argResults!.rest; final bool isHelp = rest.contains('-h') || rest.contains('--help'); - String target; + String? target; if (rest.length == 1 && (rest.single.contains('/') || rest.single.contains(r'\'))) { // For historical reasons, if there is one argument to the command and it contains // a multiple-component path (i.e. contains a slash) then we use that to determine @@ -316,7 +316,7 @@ class PackagesInteractiveGetCommand extends FlutterCommand { target = findProjectRoot(globals.fs); } - FlutterProject flutterProject; + FlutterProject? flutterProject; if (!isHelp) { if (target == null) { throwToolExit('Expected to find project root in current working directory.'); @@ -325,7 +325,7 @@ class PackagesInteractiveGetCommand extends FlutterCommand { if (flutterProject.manifest.generateSyntheticPackage) { final Environment environment = Environment( - artifacts: globals.artifacts, + artifacts: globals.artifacts!, logger: globals.logger, cacheDir: globals.cache.getRoot(), engineVersion: globals.flutterVersion.engineRevision, @@ -351,7 +351,7 @@ class PackagesInteractiveGetCommand extends FlutterCommand { directory: target, stdio: globals.stdio, touchesPackageConfig: !isHelp, - generateSyntheticPackage: flutterProject?.manifest?.generateSyntheticPackage ?? false, + generateSyntheticPackage: flutterProject?.manifest.generateSyntheticPackage ?? false, ); await flutterProject?.regeneratePlatformSpecificTooling(); diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index b7c2ba6e986..3ed0cff563a 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:meta/meta.dart'; import '../base/common.dart'; @@ -13,6 +11,7 @@ import '../base/process.dart'; import '../cache.dart'; import '../dart/pub.dart'; import '../globals.dart' as globals; +import '../persistent_tool_state.dart'; import '../runner/flutter_command.dart'; import '../version.dart'; @@ -21,8 +20,8 @@ const String _flutterInstallDocs = 'https://flutter.dev/docs/get-started/install class UpgradeCommand extends FlutterCommand { UpgradeCommand({ - @required bool verboseHelp, - UpgradeCommandRunner commandRunner, + required bool verboseHelp, + UpgradeCommandRunner? commandRunner, }) : _commandRunner = commandRunner ?? UpgradeCommandRunner() { argParser @@ -70,7 +69,7 @@ class UpgradeCommand extends FlutterCommand { @override Future runCommand() { - _commandRunner.workingDirectory = stringArg('working-directory') ?? Cache.flutterRoot; + _commandRunner.workingDirectory = stringArg('working-directory') ?? Cache.flutterRoot!; return _commandRunner.runCommand( force: boolArg('force'), continueFlow: boolArg('continue'), @@ -87,15 +86,15 @@ class UpgradeCommand extends FlutterCommand { @visibleForTesting class UpgradeCommandRunner { - String workingDirectory; + String? workingDirectory; Future runCommand({ - @required bool force, - @required bool continueFlow, - @required bool testFlow, - @required GitTagVersion gitTagVersion, - @required FlutterVersion flutterVersion, - @required bool verifyOnly, + required bool force, + required bool continueFlow, + required bool testFlow, + required GitTagVersion gitTagVersion, + required FlutterVersion flutterVersion, + required bool verifyOnly, }) async { if (!continueFlow) { await runCommandFirstHalf( @@ -112,11 +111,11 @@ class UpgradeCommandRunner { } Future runCommandFirstHalf({ - @required bool force, - @required GitTagVersion gitTagVersion, - @required FlutterVersion flutterVersion, - @required bool testFlow, - @required bool verifyOnly, + required bool force, + required GitTagVersion gitTagVersion, + required FlutterVersion flutterVersion, + required bool testFlow, + required bool verifyOnly, }) async { final FlutterVersion upstreamVersion = await fetchLatestVersion(localVersion: flutterVersion); if (flutterVersion.frameworkRevision == upstreamVersion.frameworkRevision) { @@ -172,11 +171,11 @@ class UpgradeCommandRunner { } void recordState(FlutterVersion flutterVersion) { - final Channel channel = getChannelForName(flutterVersion.channel); + final Channel? channel = getChannelForName(flutterVersion.channel); if (channel == null) { return; } - globals.persistentToolState.updateLastActiveVersion(flutterVersion.frameworkRevision, channel); + globals.persistentToolState!.updateLastActiveVersion(flutterVersion.frameworkRevision, channel); } Future flutterUpgradeContinue() async { @@ -200,12 +199,13 @@ class UpgradeCommandRunner { // re-entrantly with the `--continue` flag Future runCommandSecondHalf(FlutterVersion flutterVersion) async { // Make sure the welcome message re-display is delayed until the end. - globals.persistentToolState.setShouldRedisplayWelcomeMessage(false); + final PersistentToolState persistentToolState = globals.persistentToolState!; + persistentToolState.setShouldRedisplayWelcomeMessage(false); await precacheArtifacts(); await updatePackages(flutterVersion); await runDoctor(); // Force the welcome message to re-display following the upgrade. - globals.persistentToolState.setShouldRedisplayWelcomeMessage(true); + persistentToolState.setShouldRedisplayWelcomeMessage(true); } Future hasUncommittedChanges() async { @@ -235,7 +235,8 @@ class UpgradeCommandRunner { /// Exits tool if the tracking remote is not standard. void verifyStandardRemote(FlutterVersion localVersion) { // If repositoryUrl of the local version is null, exit - if (localVersion.repositoryUrl == null) { + final String? repositoryUrl = localVersion.repositoryUrl; + if (repositoryUrl == null) { throwToolExit( 'Unable to upgrade Flutter: The tool could not determine the remote ' 'upstream which is being tracked by the SDK.\n' @@ -244,7 +245,7 @@ class UpgradeCommandRunner { } // Strip `.git` suffix before comparing the remotes - final String trackingUrl = stripDotGit(localVersion.repositoryUrl); + final String trackingUrl = stripDotGit(repositoryUrl); final String flutterGitUrl = stripDotGit(globals.flutterGit); // Exempt the official flutter git SSH remote from this check @@ -287,18 +288,18 @@ class UpgradeCommandRunner { // URLs without ".git" suffix will remain unaffected. String stripDotGit(String url) { final RegExp pattern = RegExp(r'(.*)(\.git)$'); - final RegExpMatch match = pattern.firstMatch(url); + final RegExpMatch? match = pattern.firstMatch(url); if (match == null) { return url; } - return match.group(1); + return match.group(1)!; } /// Returns the remote HEAD flutter version. /// /// Exits tool if HEAD isn't pointing to a branch, or there is no upstream. Future fetchLatestVersion({ - @required FlutterVersion localVersion, + required FlutterVersion localVersion, }) async { String revision; try { @@ -380,14 +381,13 @@ class UpgradeCommandRunner { Future updatePackages(FlutterVersion flutterVersion) async { globals.printStatus(''); globals.printStatus(flutterVersion.toString()); - final String projectRoot = findProjectRoot(globals.fs); + final String? projectRoot = findProjectRoot(globals.fs); if (projectRoot != null) { globals.printStatus(''); await pub.get( context: PubContext.pubUpgrade, directory: projectRoot, upgrade: true, - generateSyntheticPackage: false, ); } } diff --git a/packages/flutter_tools/lib/src/dart/pub.dart b/packages/flutter_tools/lib/src/dart/pub.dart index 1a0e5027967..174458af5c0 100644 --- a/packages/flutter_tools/lib/src/dart/pub.dart +++ b/packages/flutter_tools/lib/src/dart/pub.dart @@ -101,7 +101,7 @@ abstract class Pub { bool upgrade = false, bool offline = false, bool generateSyntheticPackage = false, - String flutterRootOverride, + String? flutterRootOverride, bool checkUpToDate = false, bool shouldSkipThirdPartyGenerator = true, bool printProgress = true, @@ -135,7 +135,7 @@ abstract class Pub { /// stdout/stderr stream of pub to the corresponding streams of this process. Future interactively( List arguments, { - String directory, + String? directory, required io.Stdio stdio, bool touchesPackageConfig = false, bool generateSyntheticPackage = false,