| // 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 '../android/android_workflow.dart' as android_workflow; |
| import '../base/common.dart'; |
| import '../doctor.dart'; |
| import '../experimental/extension_manager.dart'; |
| import '../globals.dart' as globals; |
| import '../runner/flutter_command.dart'; |
| |
| /// The `flutter doctor` command, which displays diagnostic information about the |
| /// installed developer environment and tooling. |
| class DoctorCommand extends FlutterCommand { |
| /// Creates a new [DoctorCommand]. |
| /// |
| /// If [doctor] is omitted, it defaults to [globals.doctor]. If |
| /// [androidLicenseValidator] is omitted, it is lazily resolved from the |
| /// active context when `--android-licenses` is supplied. |
| DoctorCommand({ |
| android_workflow.AndroidLicenseValidator? androidLicenseValidator, |
| Doctor? doctor, |
| this.extensionManager, |
| super.toolContext, |
| this.verbose = false, |
| }) : _androidLicenseValidator = androidLicenseValidator, |
| _explicitDoctor = doctor { |
| argParser.addFlag( |
| 'android-licenses', |
| negatable: false, |
| help: "Run the Android SDK manager tool to accept the SDK's licenses.", |
| ); |
| argParser.addOption( |
| 'check-for-remote-artifacts', |
| hide: !verbose, |
| help: |
| 'Used to determine if Flutter engine artifacts for all platforms ' |
| 'are available for download.', |
| valueHelp: 'engine revision git hash', |
| ); |
| } |
| |
| final Doctor? _explicitDoctor; |
| final android_workflow.AndroidLicenseValidator? _androidLicenseValidator; |
| final bool verbose; |
| final ExtensionManager? extensionManager; |
| |
| Doctor get _doctor => _explicitDoctor ?? globals.doctor!; |
| |
| @override |
| final name = 'doctor'; |
| |
| @override |
| final description = 'Show information about the installed tooling.'; |
| |
| @override |
| final String category = FlutterCommandCategory.sdk; |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| if (argResults?.wasParsed('check-for-remote-artifacts') ?? false) { |
| final String engineRevision = stringArg('check-for-remote-artifacts')!; |
| if (engineRevision.startsWith(RegExp(r'[a-f0-9]{1,40}'))) { |
| final bool success = await _doctor.checkRemoteArtifacts(engineRevision); |
| if (success) { |
| throwToolExit( |
| 'Artifacts for engine $engineRevision are missing or are ' |
| 'not yet available.', |
| exitCode: 1, |
| ); |
| } |
| } else { |
| throwToolExit( |
| 'Remote artifact revision $engineRevision is not a valid ' |
| 'git hash.', |
| ); |
| } |
| } |
| android_workflow.AndroidLicenseValidator? androidLicenseValidator = _androidLicenseValidator; |
| if (androidLicenseValidator == null && boolArg('android-licenses')) { |
| try { |
| androidLicenseValidator = android_workflow.androidLicenseValidator; |
| } on Exception { |
| // Fallback when running in hermetic test environments without AppContext. |
| } on Error { |
| // Catches UnsupportedError in testWithoutContext and StateError if AppContext is missing. |
| } |
| } |
| final bool success = await _doctor.diagnose( |
| androidLicenses: boolArg('android-licenses'), |
| verbose: verbose, |
| androidLicenseValidator: androidLicenseValidator, |
| extensionManager: extensionManager, |
| ); |
| return FlutterCommandResult(success ? ExitStatus.success : ExitStatus.warning); |
| } |
| } |