[flutter_tools] remove globals from terminal (#77953)

This commit is contained in:
Jonah Williams 2021-03-12 12:53:05 -08:00 committed by GitHub
parent 5a27340c45
commit a01f37245b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 110 additions and 49 deletions

View file

@ -146,7 +146,7 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
}
if (!exactMatch) {
status.cancel();
logger.printStatus('$warningMark Flutter tried to create the file `$newSettingsRelativeFile`, but failed.');
logger.printStatus('${logger.terminal.warningMark} Flutter tried to create the file `$newSettingsRelativeFile`, but failed.');
// Print how to manually update the file.
logger.printStatus(fileSystem.file(fileSystem.path.join(flutterRoot, 'packages','flutter_tools',
'gradle', 'manual_migration_settings.gradle.md')).readAsStringSync());
@ -155,7 +155,7 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
// Copy the new file.
newSettingsFile.writeAsStringSync(settingsAarContent);
status.stop();
logger.printStatus('$successMark `$newSettingsRelativeFile` created successfully.');
logger.printStatus('${logger.terminal.successMark} `$newSettingsRelativeFile` created successfully.');
}
/// An implementation of the [AndroidBuilder] that delegates to gradle.
@ -286,7 +286,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
assert(localGradleErrors != null);
if (!project.android.isSupportedVersion) {
_exitWithUnsupportedProjectMessage(_usage);
_exitWithUnsupportedProjectMessage(_usage, _logger.terminal);
}
final Directory buildDirectory = project.android.buildDirectory;
@ -295,7 +295,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
BuildEvent('app-using-android-x', flutterUsage: _usage).send();
} else if (!usesAndroidX) {
BuildEvent('app-not-using-android-x', flutterUsage: _usage).send();
_logger.printStatus("$warningMark Your app isn't using AndroidX.", emphasis: true);
_logger.printStatus("${_logger.terminal.warningMark} Your app isn't using AndroidX.", emphasis: true);
_logger.printStatus(
'To avoid potential build failures, you can quickly migrate your app '
'by following the steps on https://goo.gl/CP92wY .',
@ -523,7 +523,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
}
_logger.printStatus(
'$successMark Built ${_fileSystem.path.relative(bundleFile.path)}$appSize.',
'${_logger.terminal.successMark} Built ${_fileSystem.path.relative(bundleFile.path)}$appSize.',
color: TerminalColor.green,
);
return;
@ -557,7 +557,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
? '' // Don't display the size when building a debug variant.
: ' (${getSizeAsMB(apkFile.lengthSync())})';
_logger.printStatus(
'$successMark Built ${_fileSystem.path.relative(apkFile.path)}$appSize.',
'${_logger.terminal.successMark} Built ${_fileSystem.path.relative(apkFile.path)}$appSize.',
color: TerminalColor.green,
);
@ -748,7 +748,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
);
}
_logger.printStatus(
'$successMark Built ${_fileSystem.path.relative(repoDirectory.path)}.',
'${_logger.terminal.successMark} Built ${_fileSystem.path.relative(repoDirectory.path)}.',
color: TerminalColor.green,
);
}
@ -878,10 +878,10 @@ String _calculateSha(File file) {
return _hex(sha1.convert(bytes).bytes);
}
void _exitWithUnsupportedProjectMessage(Usage usage) {
void _exitWithUnsupportedProjectMessage(Usage usage, Terminal terminal) {
BuildEvent('unsupported-project', eventError: 'gradle-plugin', flutterUsage: usage).send();
throwToolExit(
'$warningMark Your app is using an unsupported Gradle project. '
'${terminal.warningMark} Your app is using an unsupported Gradle project. '
'To fix this problem, create a new project by running `flutter create -t app <app-directory>` '
'and then move the dart code, assets and pubspec.yaml to the new project.',
);

View file

@ -8,7 +8,6 @@ import 'package:meta/meta.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../base/process.dart';
import '../base/terminal.dart';
import '../globals.dart' as globals;
import '../project.dart';
import '../reporting/reporting.dart';
@ -88,7 +87,7 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError(
bool usesAndroidX,
bool shouldBuildPluginAsAar,
}) async {
globals.printStatus('$warningMark Gradle does not have execution permission.', emphasis: true);
globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true);
globals.printStatus(
'You should change the ownership of the project directory to your user, '
'or move the project to a directory with execute permissions.',
@ -126,7 +125,7 @@ final GradleHandledError networkErrorHandler = GradleHandledError(
bool shouldBuildPluginAsAar,
}) async {
globals.printError(
'$warningMark Gradle threw an error while downloading artifacts from the network. '
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
'Retrying to download...'
);
try {
@ -155,7 +154,7 @@ final GradleHandledError r8FailureHandler = GradleHandledError(
bool usesAndroidX,
bool shouldBuildPluginAsAar,
}) async {
globals.printStatus('$warningMark The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
globals.printStatus('${globals.logger.terminal.warningMark} The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
globals.printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4);
globals.printStatus('To learn more, see: https://developer.android.com/studio/build/shrink-code', indent: 4);
return GradleBuildStatus.exit;
@ -265,7 +264,7 @@ final GradleHandledError licenseNotAcceptedHandler = GradleHandledError(
assert(licenseFailure != null);
final Match licenseMatch = licenseFailure.firstMatch(line);
globals.printStatus(
'$warningMark Unable to download needed Android SDK components, as the '
'${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the '
'following licenses have not been accepted:\n'
'${licenseMatch.group(1)}\n\n'
'To resolve this, please run the following command in a Terminal:\n'
@ -329,7 +328,7 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
}
}
globals.printStatus(
'\n$warningMark Gradle project does not define a task suitable '
'\n${globals.logger.terminal.warningMark} Gradle project does not define a task suitable '
'for the requested build.'
);
if (productFlavors.isEmpty) {

View file

@ -12,7 +12,6 @@ import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../base/version.dart';
import '../build_info.dart';
@ -260,7 +259,7 @@ void writeLocalProperties(File properties) {
void exitWithNoSdkMessage() {
BuildEvent('unsupported-project', eventError: 'android-sdk-not-found', flutterUsage: globals.flutterUsage).send();
throwToolExit(
'$warningMark No Android SDK found. '
'${globals.logger.terminal.warningMark} No Android SDK found. '
'Try setting the ANDROID_SDK_ROOT environment variable.'
);
}

View file

@ -7,7 +7,6 @@
import 'package:meta/meta.dart';
import '../convert.dart';
import '../globals.dart' as globals;
import 'io.dart' as io;
import 'logger.dart';
import 'platform.dart';
@ -22,16 +21,6 @@ enum TerminalColor {
grey,
}
/// Warning mark to use in stdout or stderr.
String get warningMark {
return globals.terminal.bolden(globals.terminal.color('[!]', TerminalColor.red));
}
/// Success mark to use in stdout.
String get successMark {
return globals.terminal.bolden(globals.terminal.color('', TerminalColor.green));
}
/// A class that contains the context settings for command text output to the
/// console.
class OutputPreferences {
@ -39,13 +28,17 @@ class OutputPreferences {
bool wrapText,
int wrapColumn,
bool showColor,
}) : wrapText = wrapText ?? globals.stdio.hasTerminal,
io.Stdio stdio,
}) : _stdio = stdio,
wrapText = wrapText ?? stdio.hasTerminal,
_overrideWrapColumn = wrapColumn,
showColor = showColor ?? globals.platform.stdoutSupportsAnsi ?? false;
showColor = showColor ?? false;
/// A version of this class for use in tests.
OutputPreferences.test({this.wrapText = false, int wrapColumn = kDefaultTerminalColumns, this.showColor = false})
: _overrideWrapColumn = wrapColumn;
: _overrideWrapColumn = wrapColumn, _stdio = null;
final io.Stdio _stdio;
/// If [wrapText] is true, then any text sent to the context's [Logger]
/// instance (e.g. from the [printError] or [printStatus] functions) will be
@ -65,7 +58,7 @@ class OutputPreferences {
/// terminal, or to [kDefaultTerminalColumns] if not writing to a terminal.
final int _overrideWrapColumn;
int get wrapColumn {
return _overrideWrapColumn ?? globals.stdio.terminalColumns ?? kDefaultTerminalColumns;
return _overrideWrapColumn ?? _stdio?.terminalColumns ?? kDefaultTerminalColumns;
}
/// Whether or not to output ANSI color codes when writing to the output
@ -106,6 +99,12 @@ abstract class Terminal {
/// or whether an automatic selection should be made instead.
bool get stdinHasTerminal;
/// Warning mark to use in stdout or stderr.
String get warningMark;
/// Success mark to use in stdout.
String get successMark;
String bolden(String message);
String color(String message, TerminalColor color);
@ -199,6 +198,16 @@ class AnsiTerminal implements Terminal {
@override
bool usesTerminalUi = false;
@override
String get warningMark {
return bolden(color('[!]', TerminalColor.red));
}
@override
String get successMark {
return bolden(color('', TerminalColor.green));
}
@override
String bolden(String message) {
assert(message != null);
@ -355,4 +364,10 @@ class _TestTerminal implements Terminal {
@override
bool get stdinHasTerminal => false;
@override
String get successMark => '';
@override
String get warningMark => '[!]';
}

View file

@ -24,6 +24,7 @@ import 'base/io.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'base/terminal.dart';
import 'base/time.dart';
import 'base/user_messages.dart';
import 'build_info.dart';
@ -275,6 +276,11 @@ Future<T> runInContext<T>(
platform: globals.platform,
processManager: globals.processManager,
),
OutputPreferences: () => OutputPreferences(
wrapText: globals.stdio.hasTerminal ?? false,
showColor: globals.platform.stdoutSupportsAnsi,
stdio: globals.stdio,
),
PersistentToolState: () => PersistentToolState(
fileSystem: globals.fs,
logger: globals.logger,

View file

@ -106,8 +106,12 @@ XcodeProjectInterpreter get xcodeProjectInterpreter => context.get<XcodeProjectI
XCDevice get xcdevice => context.get<XCDevice>();
final OutputPreferences _defaultOutputPreferences = OutputPreferences();
OutputPreferences get outputPreferences => context.get<OutputPreferences>() ?? _defaultOutputPreferences;
final OutputPreferences _default = OutputPreferences(
wrapText: stdio.hasTerminal ?? false,
showColor: platform.stdoutSupportsAnsi,
stdio: stdio,
);
OutputPreferences get outputPreferences => context.get<OutputPreferences>() ?? _default;
final BotDetector _defaultBotDetector = BotDetector(
httpClientFactory: context.get<HttpClientFactory>() ?? () => HttpClient(),

View file

@ -14,7 +14,6 @@ import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/io.dart' as io;
import '../base/terminal.dart';
import '../base/user_messages.dart';
import '../base/utils.dart';
import '../build_info.dart';
@ -1046,7 +1045,7 @@ abstract class FlutterCommand extends Command<void> {
void _printDeprecationWarning() {
if (deprecated) {
globals.printStatus('$warningMark The "$name" command is deprecated and '
globals.printStatus('${globals.logger.terminal.warningMark} The "$name" 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.');
@ -1326,7 +1325,7 @@ abstract class FlutterCommand extends Command<void> {
);
final String help = <String>[
if (deprecated)
'$warningMark Deprecated. This command will be removed in a future version of Flutter.',
'${globals.logger.terminal.warningMark} Deprecated. This command will be removed in a future version of Flutter.',
description,
'',
'Global options:',

View file

@ -11,6 +11,7 @@ import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/symbolize.dart';
import 'package:flutter_tools/src/convert.dart';
@ -24,7 +25,6 @@ import '../../src/fakes.dart';
void main() {
MemoryFileSystem fileSystem;
FakeStdio stdio;
SymbolizeCommand command;
setUpAll(() {
Cache.disableLocking();
@ -33,11 +33,6 @@ void main() {
setUp(() {
fileSystem = MemoryFileSystem.test();
stdio = FakeStdio();
command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: DwarfSymbolizationService.test(),
);
});
testUsingContext('Regression test for type error in codec', () async {
@ -60,28 +55,54 @@ void main() {
testUsingContext('symbolize exits when --debug-info argument is missing', () async {
final SymbolizeCommand command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: DwarfSymbolizationService.test(),
);
final Future<void> result = createTestCommandRunner(command)
.run(const <String>['symbolize']);
expect(result, throwsToolExit(message: '"--debug-info" is required to symbolize stack traces.'));
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('symbolize exits when --debug-info file is missing', () async {
final SymbolizeCommand command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: DwarfSymbolizationService.test(),
);
final Future<void> result = createTestCommandRunner(command)
.run(const <String>['symbolize', '--debug-info=app.debug']);
expect(result, throwsToolExit(message: 'app.debug does not exist.'));
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('symbolize exits when --input file is missing', () async {
final SymbolizeCommand command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: DwarfSymbolizationService.test(),
);
fileSystem.file('app.debug').createSync();
final Future<void> result = createTestCommandRunner(command)
.run(const <String>['symbolize', '--debug-info=app.debug', '--input=foo.stack', '--output=results/foo.result']);
expect(result, throwsToolExit(message: ''));
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('symbolize succeeds when DwarfSymbolizationService does not throw', () async {
final SymbolizeCommand command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: DwarfSymbolizationService.test(),
);
fileSystem.file('app.debug').writeAsBytesSync(<int>[1, 2, 3]);
fileSystem.file('foo.stack').writeAsStringSync('hello');
@ -90,10 +111,12 @@ void main() {
expect(fileSystem.file('results/foo.result'), exists);
expect(fileSystem.file('results/foo.result').readAsBytesSync(), <int>[104, 101, 108, 108, 111, 10]); // hello
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('symbolize throws when DwarfSymbolizationService throws', () async {
command = SymbolizeCommand(
final SymbolizeCommand command = SymbolizeCommand(
stdio: stdio,
fileSystem: fileSystem,
dwarfSymbolizationService: ThrowingDwarfSymbolizationService(),
@ -107,6 +130,8 @@ void main() {
'symbolize', '--debug-info=app.debug', '--input=foo.stack', '--output=results/foo.result']),
throwsToolExit(message: 'test'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences.test(),
});
}

View file

@ -15,7 +15,6 @@ import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
@ -196,7 +195,7 @@ void main() {
expect(() {
updateLocalProperties(project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory));
}, throwsToolExit(
message: '$warningMark No Android SDK found. Try setting the ANDROID_SDK_ROOT environment variable.',
message: '${globals.logger.terminal.warningMark} No Android SDK found. Try setting the ANDROID_SDK_ROOT environment variable.',
));
}, overrides: <Type, Generator>{
AndroidSdk: () => null,

View file

@ -27,7 +27,6 @@ void main() {
group('FlutterCommandRunner', () {
MemoryFileSystem fileSystem;
Platform platform;
FlutterCommandRunner runner;
setUpAll(() {
Cache.disableLocking();
@ -45,12 +44,11 @@ void main() {
},
version: '1 2 3 4 5',
);
runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
});
group('run', () {
testUsingContext('checks that Flutter installation is up-to-date', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterVersion version = globals.flutterVersion as FakeFlutterVersion;
await runner.run(<String>['dummy']);
@ -61,9 +59,11 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform,
FlutterVersion: () => FakeFlutterVersion(),
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('does not check that Flutter installation is up-to-date with --machine flag', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterVersion version = globals.flutterVersion as FakeFlutterVersion;
await runner.run(<String>['dummy', '--machine', '--version']);
@ -74,9 +74,11 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform,
FlutterVersion: () => FakeFlutterVersion(),
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('Fetches tags when --version is used', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterVersion version = globals.flutterVersion as FakeFlutterVersion;
await runner.run(<String>['--version']);
@ -87,9 +89,11 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform,
FlutterVersion: () => FakeFlutterVersion(),
OutputPreferences: () => OutputPreferences.test(),
});
testUsingContext('Doesnt crash on invalid .packages file', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('.packages')
..createSync()
@ -101,6 +105,7 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform,
OutputPreferences: () => OutputPreferences.test(),
});
group('getRepoPackages', () {
@ -127,6 +132,7 @@ void main() {
});
testUsingContext('', () {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final List<String> packagePaths = runner.getRepoPackages()
.map((Directory d) => d.path).toList();
expect(packagePaths, <String>[
@ -138,11 +144,13 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform,
FlutterVersion: () => FakeFlutterVersion(),
OutputPreferences: () => OutputPreferences.test(),
});
});
group('wrapping', () {
testUsingContext('checks that output wrapping is turned on when writing to a terminal', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
runner.addCommand(fakeCommand);
await runner.run(<String>['fake']);
@ -151,9 +159,11 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
Stdio: () => FakeStdio(hasFakeTerminal: true),
OutputPreferences: () => OutputPreferences.test(),
}, initializeFlutterRoot: false);
testUsingContext('checks that output wrapping is turned off when not writing to a terminal', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
runner.addCommand(fakeCommand);
await runner.run(<String>['fake']);
@ -162,9 +172,11 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
Stdio: () => FakeStdio(hasFakeTerminal: false),
OutputPreferences: () => OutputPreferences.test(),
}, initializeFlutterRoot: false);
testUsingContext('checks that output wrapping is turned off when set on the command line and writing to a terminal', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
runner.addCommand(fakeCommand);
await runner.run(<String>['--no-wrap', 'fake']);
@ -173,9 +185,11 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
Stdio: () => FakeStdio(hasFakeTerminal: true),
OutputPreferences: () => OutputPreferences.test(),
}, initializeFlutterRoot: false);
testUsingContext('checks that output wrapping is turned on when set on the command line, but not writing to a terminal', () async {
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
runner.addCommand(fakeCommand);
await runner.run(<String>['--wrap', 'fake']);
@ -184,6 +198,7 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
Stdio: () => FakeStdio(hasFakeTerminal: false),
OutputPreferences: () => OutputPreferences.test(),
}, initializeFlutterRoot: false);
});
});