| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import '../base/common.dart'; |
| import '../base/io.dart'; |
| import '../base/os.dart'; |
| import '../base/process.dart'; |
| import '../base/version.dart'; |
| import '../cache.dart'; |
| import '../dart/pub.dart'; |
| import '../globals.dart' as globals; |
| import '../runner/flutter_command.dart'; |
| import '../version.dart'; |
| |
| class VersionCommand extends FlutterCommand { |
| VersionCommand() : super() { |
| argParser.addFlag('force', |
| abbr: 'f', |
| help: 'Force switch to older Flutter versions that do not include a version command', |
| ); |
| // Don't use usesPubOption here. That will cause the version command to |
| // require a pubspec.yaml file, which it doesn't need. |
| argParser.addFlag('pub', |
| defaultsTo: true, |
| hide: true, |
| help: 'Whether to run "flutter pub get" after switching versions.', |
| ); |
| } |
| |
| @override |
| final String name = 'version'; |
| |
| @override |
| final String description = 'List or switch flutter versions.'; |
| |
| // The first version of Flutter which includes the flutter version command. Switching to older |
| // versions will require the user to manually upgrade. |
| Version minSupportedVersion = Version.parse('1.2.1'); |
| |
| Future<List<String>> getTags() async { |
| RunResult runResult; |
| try { |
| runResult = await processUtils.run( |
| <String>['git', 'tag', '-l', 'v*', '--sort=-creatordate'], |
| throwOnError: true, |
| workingDirectory: Cache.flutterRoot, |
| ); |
| } on ProcessException catch (error) { |
| throwToolExit( |
| 'Unable to get the tags. ' |
| 'This might be due to git not being installed or an internal error' |
| '\nError: $error.' |
| ); |
| } |
| return runResult.toString().split('\n'); |
| } |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| final List<String> tags = await getTags(); |
| if (argResults.rest.isEmpty) { |
| tags.forEach(globals.printStatus); |
| return FlutterCommandResult.success(); |
| } |
| |
| globals.printStatus( |
| '╔══════════════════════════════════════════════════════════════════════════════╗\n' |
| '║ Warning: "flutter version" will leave the SDK in a detached HEAD state. ║\n' |
| '║ If you are using the command to return to a previously installed SDK version ║\n' |
| '║ consider using the "flutter downgrade" command instead. ║\n' |
| '╚══════════════════════════════════════════════════════════════════════════════╝\n', |
| emphasis: true, |
| ); |
| if (globals.stdio.stdinHasTerminal) { |
| globals.terminal.usesTerminalUi = true; |
| final String result = await globals.terminal.promptForCharInput( |
| <String>['y', 'n'], |
| logger: globals.logger, |
| prompt: 'Are you sure you want to proceed?' |
| ); |
| if (result == 'n') { |
| return FlutterCommandResult.success(); |
| } |
| } |
| |
| final String version = argResults.rest[0].replaceFirst('v', ''); |
| if (!tags.contains('v$version')) { |
| globals.printError('There is no version: $version'); |
| } |
| |
| // check min supported version |
| final Version targetVersion = Version.parse(version); |
| if (targetVersion == null) { |
| throwToolExit('Failed to parse version "$version"'); |
| } |
| |
| bool withForce = false; |
| if (targetVersion < minSupportedVersion) { |
| if (!boolArg('force')) { |
| globals.printError( |
| 'Version command is not supported in $targetVersion and it is supported since version $minSupportedVersion ' |
| 'which means if you switch to version $minSupportedVersion then you can not use version command. ' |
| 'If you really want to switch to version $targetVersion, please use `--force` flag: `flutter version --force $targetVersion`.' |
| ); |
| return const FlutterCommandResult(ExitStatus.success); |
| } |
| withForce = true; |
| } |
| |
| try { |
| await processUtils.run( |
| <String>['git', 'checkout', 'v$version'], |
| throwOnError: true, |
| workingDirectory: Cache.flutterRoot, |
| ); |
| } catch (e) { |
| throwToolExit('Unable to checkout version branch for version $version.'); |
| } |
| |
| final FlutterVersion flutterVersion = FlutterVersion(); |
| |
| globals.printStatus('Switching Flutter to version ${flutterVersion.frameworkVersion}${withForce ? ' with force' : ''}'); |
| |
| // Check for and download any engine and pkg/ updates. |
| // We run the 'flutter' shell script re-entrantly here |
| // so that it will download the updated Dart and so forth |
| // if necessary. |
| globals.printStatus(''); |
| globals.printStatus('Downloading engine...'); |
| int code = await processUtils.stream(<String>[ |
| globals.fs.path.join('bin', 'flutter'), |
| '--no-color', |
| 'precache', |
| ], workingDirectory: Cache.flutterRoot, allowReentrantFlutter: true); |
| |
| if (code != 0) { |
| throwToolExit(null, exitCode: code); |
| } |
| |
| globals.printStatus(''); |
| globals.printStatus(flutterVersion.toString()); |
| |
| final String projectRoot = findProjectRoot(); |
| if (projectRoot != null && boolArg('pub')) { |
| globals.printStatus(''); |
| await pub.get( |
| context: PubContext.pubUpgrade, |
| directory: projectRoot, |
| upgrade: true, |
| checkLastModified: false, |
| ); |
| } |
| |
| // Run a doctor check in case system requirements have changed. |
| globals.printStatus(''); |
| globals.printStatus('Running flutter doctor...'); |
| code = await processUtils.stream( |
| <String>[ |
| globals.fs.path.join('bin', 'flutter'), |
| 'doctor', |
| ], |
| workingDirectory: Cache.flutterRoot, |
| allowReentrantFlutter: true, |
| ); |
| |
| if (code != 0) { |
| throwToolExit(null, exitCode: code); |
| } |
| |
| return FlutterCommandResult.success(); |
| } |
| } |