Unverified Commit b3f9944f authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove deprecated flutter command (#67478)

parent a4e0e2a8
......@@ -42,7 +42,6 @@ import 'src/commands/test.dart';
import 'src/commands/train.dart';
import 'src/commands/update_packages.dart';
import 'src/commands/upgrade.dart';
import 'src/commands/version.dart';
import 'src/features.dart';
import 'src/globals.dart' as globals;
// Files in `isolated` are intentionally excluded from google3 tooling.
......@@ -116,7 +115,6 @@ Future<void> main(List<String> args) async {
ShellCompletionCommand(),
TestCommand(verboseHelp: verboseHelp),
UpgradeCommand(),
VersionCommand(),
SymbolizeCommand(
stdio: globals.stdio,
fileSystem: globals.fs,
......
// 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 '../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';
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
bool get deprecated => true;
@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 {
globals.flutterVersion.fetchTagsAndUpdate();
RunResult runResult;
try {
runResult = await processUtils.run(
<String>['git', 'tag', '-l', '*.*.*', '--sort=-creatordate'],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} on ProcessException catch (error) {
throwToolExit(
'Unable to get the tags. '
'This is likely due to an internal git 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(RegExp('^v'), '');
final List<String> matchingTags = tags.where((String tag) => tag.contains(version)).toList();
String matchingTag;
// TODO(fujino): make this a tool exit and fix tests
if (matchingTags.isEmpty) {
globals.printError('There is no version: $version');
matchingTag = version;
} else {
matchingTag = matchingTags.first.trim();
}
// 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', matchingTag],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} on Exception catch (e) {
throwToolExit('Unable to checkout version branch for version $version: $e');
}
globals.printStatus('Switching Flutter to version $matchingTag${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('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);
}
final String projectRoot = findProjectRoot();
if (projectRoot != null && boolArg('pub')) {
globals.printStatus('');
await pub.get(
context: PubContext.pubUpgrade,
directory: projectRoot,
upgrade: true,
checkLastModified: false,
generateSyntheticPackage: 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();
}
}
// 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 'dart:convert';
import 'dart:io';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/version.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/mocks.dart' show MockProcess;
void main() {
group('version', () {
MockStdio mockStdio;
MockVersion mockVersion;
setUpAll(() {
Cache.disableLocking();
});
setUp(() {
mockStdio = MockStdio();
mockVersion = MockVersion();
when(mockStdio.stdinHasTerminal).thenReturn(false);
when(mockStdio.hasTerminal).thenReturn(false);
});
testUsingContext('version ls', () async {
final VersionCommand command = VersionCommand();
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
]);
expect(testLogger.statusText, equals(
'[!] The "version" command is deprecated '
'and will be removed in a future version of Flutter. '
'See https://flutter.dev/docs/development/tools/sdk/releases '
'for previous releases of Flutter.\n\n'
'v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0\r\n31.0.0-0.0.pre\n'
));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext('version switch prompt is accepted', () async {
when(mockStdio.stdinHasTerminal).thenReturn(true);
const String version = 'v10.0.0';
final VersionCommand command = VersionCommand();
when(globals.terminal.promptForCharInput(<String>['y', 'n'],
logger: anyNamed('logger'),
prompt: 'Are you sure you want to proceed?')
).thenAnswer((Invocation invocation) async => 'y');
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]);
expect(testLogger.statusText, contains('Switching Flutter to version $version'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
AnsiTerminal: () => MockTerminal(),
FlutterVersion: () => mockVersion,
});
testUsingContext('old dev version switch prompt is accepted', () async {
when(mockStdio.stdinHasTerminal).thenReturn(true);
const String version = '30.0.0-dev.0.0';
final VersionCommand command = VersionCommand();
when(globals.terminal.promptForCharInput(<String>['y', 'n'],
logger: anyNamed('logger'),
prompt: 'Are you sure you want to proceed?')
).thenAnswer((Invocation invocation) async => 'y');
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]);
expect(testLogger.statusText, contains('Switching Flutter to version $version'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
AnsiTerminal: () => MockTerminal(),
FlutterVersion: () => mockVersion,
});
testUsingContext('dev version switch prompt is accepted', () async {
when(mockStdio.stdinHasTerminal).thenReturn(true);
const String version = '31.0.0-0.0.pre';
final VersionCommand command = VersionCommand();
when(globals.terminal.promptForCharInput(<String>['y', 'n'],
logger: anyNamed('logger'),
prompt: 'Are you sure you want to proceed?')
).thenAnswer((Invocation invocation) async => 'y');
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]);
expect(testLogger.statusText, contains('Switching Flutter to version $version'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
AnsiTerminal: () => MockTerminal(),
FlutterVersion: () => mockVersion,
});
testUsingContext('version switch prompt is declined', () async {
when(mockStdio.stdinHasTerminal).thenReturn(true);
const String version = '10.0.0';
final VersionCommand command = VersionCommand();
when(globals.terminal.promptForCharInput(<String>['y', 'n'],
logger: anyNamed('logger'),
prompt: 'Are you sure you want to proceed?')
).thenAnswer((Invocation invocation) async => 'n');
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]);
expect(testLogger.statusText, isNot(contains('Switching Flutter to version $version')));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
AnsiTerminal: () => MockTerminal(),
FlutterVersion: () => mockVersion,
});
testUsingContext('switch to not supported version without force', () async {
const String version = '1.1.5';
final VersionCommand command = VersionCommand();
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]);
expect(testLogger.errorText, contains('Version command is not supported in'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext('switch to not supported version with force', () async {
const String version = '1.1.5';
final VersionCommand command = VersionCommand();
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
'--force',
version,
]);
expect(testLogger.statusText, contains('Switching Flutter to version $version with force'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext('tool exit on confusing version', () async {
const String version = 'master';
final VersionCommand command = VersionCommand();
expect(() async =>
await createTestCommandRunner(command).run(<String>[
'version',
'--no-pub',
version,
]),
throwsToolExit(),
);
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext("exit tool if can't get the tags", () async {
final VersionCommand command = VersionCommand();
try {
await command.getTags();
fail('ToolExit expected');
} on Exception catch (e) {
expect(e, isA<ToolExit>());
}
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(failGitTag: true),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext('Does not run pub when outside a project', () async {
final VersionCommand command = VersionCommand();
await createTestCommandRunner(command).run(<String>[
'version',
]);
expect(testLogger.statusText, contains('v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0\r\n31.0.0-0.0.pre\n'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
testUsingContext('Fetches upstream tags', () async {
final VersionCommand command = VersionCommand();
await createTestCommandRunner(command).run(<String>[
'version',
]);
verify(mockVersion.fetchTagsAndUpdate()).called(1);
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Stdio: () => mockStdio,
FlutterVersion: () => mockVersion,
});
});
}
class MockVersion extends Mock implements FlutterVersion {}
class MockTerminal extends Mock implements AnsiTerminal {}
class MockStdio extends Mock implements Stdio {}
class MockProcessManager extends Mock implements ProcessManager {
MockProcessManager({
this.failGitTag = false,
this.latestCommitFails = false,
});
String version = '';
final bool failGitTag;
final bool latestCommitFails;
@override
Future<ProcessResult> run(
List<dynamic> command, {
String workingDirectory,
Map<String, String> environment,
bool includeParentEnvironment = true,
bool runInShell = false,
Encoding stdoutEncoding = systemEncoding,
Encoding stderrEncoding = systemEncoding,
}) async {
if (command[0] == 'git' && command[1] == 'tag') {
if (failGitTag) {
return ProcessResult(0, 1, '', '');
}
return ProcessResult(0, 0, 'v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0\r\n31.0.0-0.0.pre', '');
}
if (command[0] == 'git' && command[1] == 'checkout') {
version = (command[2] as String).replaceFirst(RegExp('^v'), '');
}
return ProcessResult(0, 0, '', '');
}
@override
ProcessResult runSync(
List<dynamic> command, {
String workingDirectory,
Map<String, String> environment,
bool includeParentEnvironment = true,
bool runInShell = false,
Encoding stdoutEncoding = systemEncoding,
Encoding stderrEncoding = systemEncoding,
}) {
final String commandStr = command.join(' ');
if (commandStr == FlutterVersion.gitLog(<String>['-n', '1', '--pretty=format:%H']).join(' ')) {
return ProcessResult(0, 0, '000000000000000000000', '');
}
if (commandStr ==
'git describe --match *.*.* --first-parent --long --tags') {
if (version.isNotEmpty) {
return ProcessResult(0, 0, '$version-0-g00000000', '');
}
}
return ProcessResult(0, 0, '', '');
}
@override
Future<Process> start(
List<dynamic> command, {
String workingDirectory,
Map<String, String> environment,
bool includeParentEnvironment = true,
bool runInShell = false,
ProcessStartMode mode = ProcessStartMode.normal,
}) {
final Completer<Process> completer = Completer<Process>();
completer.complete(MockProcess());
return completer.future;
}
}
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