Commit ccf08e98 authored by Devon Carew's avatar Devon Carew

Merge pull request #1958 from devoncarew/more_validation

More work on validation
parents dc687285 d5a6fcee
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
// https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT // https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
// https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/SERVICES.TXT // https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/SERVICES.TXT
......
...@@ -7,8 +7,8 @@ import 'dart:io'; ...@@ -7,8 +7,8 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart'; import 'package:pub_semver/pub_semver.dart';
import '../base/globals.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../globals.dart';
// Android SDK layout: // Android SDK layout:
// //
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import '../base/globals.dart';
import '../doctor.dart'; import '../doctor.dart';
import '../globals.dart';
import 'android_sdk.dart'; import 'android_sdk.dart';
class AndroidWorkflow extends Workflow { class AndroidWorkflow extends Workflow {
...@@ -15,8 +15,11 @@ class AndroidWorkflow extends Workflow { ...@@ -15,8 +15,11 @@ class AndroidWorkflow extends Workflow {
bool get canLaunchDevices => androidSdk != null && androidSdk.validateSdkWellFormed(complain: false); bool get canLaunchDevices => androidSdk != null && androidSdk.validateSdkWellFormed(complain: false);
void diagnose() { ValidationResult validate() {
Validator androidValidator = new Validator('Develop for Android devices'); Validator androidValidator = new Validator(
'$name toolchain',
description: 'develop for Android devices'
);
Function _sdkExists = () { Function _sdkExists = () {
return androidSdk == null ? ValidationType.missing : ValidationType.installed; return androidSdk == null ? ValidationType.missing : ValidationType.installed;
...@@ -29,6 +32,8 @@ class AndroidWorkflow extends Workflow { ...@@ -29,6 +32,8 @@ class AndroidWorkflow extends Workflow {
validatorFunction: _sdkExists validatorFunction: _sdkExists
)); ));
androidValidator.validate().print(); return androidValidator.validate();
} }
void diagnose() => validate().print();
} }
...@@ -11,12 +11,12 @@ import 'package:path/path.dart' as path; ...@@ -11,12 +11,12 @@ import 'package:path/path.dart' as path;
import '../android/android_sdk.dart'; import '../android/android_sdk.dart';
import '../application_package.dart'; import '../application_package.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/globals.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../device.dart'; import '../device.dart';
import '../flx.dart' as flx; import '../flx.dart' as flx;
import '../globals.dart';
import '../toolchain.dart'; import '../toolchain.dart';
import 'adb.dart'; import 'adb.dart';
import 'android.dart'; import 'android.dart';
......
...@@ -8,10 +8,10 @@ import 'dart:io'; ...@@ -8,10 +8,10 @@ import 'dart:io';
import 'package:archive/archive.dart'; import 'package:archive/archive.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'base/globals.dart';
import 'base/os.dart'; import 'base/os.dart';
import 'base/process.dart'; import 'base/process.dart';
import 'build_configuration.dart'; import 'build_configuration.dart';
import 'globals.dart';
String _getNameForHostPlatform(HostPlatform platform) { String _getNameForHostPlatform(HostPlatform platform) {
switch (platform) { switch (platform) {
......
...@@ -6,7 +6,7 @@ import 'dart:async'; ...@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'globals.dart'; import '../globals.dart';
typedef String StringConverter(String string); typedef String StringConverter(String string);
......
...@@ -6,7 +6,7 @@ import 'dart:io'; ...@@ -6,7 +6,7 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'base/globals.dart'; import 'globals.dart';
enum BuildType { enum BuildType {
prebuilt, prebuilt,
......
...@@ -11,14 +11,14 @@ import 'package:den_api/den_api.dart'; ...@@ -11,14 +11,14 @@ import 'package:den_api/den_api.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class AnalyzeCommand extends FlutterCommand { class AnalyzeCommand extends FlutterCommand {
String get name => 'analyze'; String get name => 'analyze';
String get description => 'Runs a carefully configured dartanalyzer over the current project\'s Dart code.'; String get description => 'Analyze the project\'s Dart code.';
AnalyzeCommand() { AnalyzeCommand() {
argParser.addFlag('flutter-repo', help: 'Include all the examples and tests from the Flutter repository.', defaultsTo: false); argParser.addFlag('flutter-repo', help: 'Include all the examples and tests from the Flutter repository.', defaultsTo: false);
......
...@@ -11,12 +11,12 @@ import '../android/android_sdk.dart'; ...@@ -11,12 +11,12 @@ import '../android/android_sdk.dart';
import '../application_package.dart'; import '../application_package.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/globals.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../device.dart'; import '../device.dart';
import '../flx.dart' as flx; import '../flx.dart' as flx;
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../services.dart'; import '../services.dart';
import '../toolchain.dart'; import '../toolchain.dart';
......
...@@ -4,14 +4,14 @@ ...@@ -4,14 +4,14 @@
import 'dart:async'; import 'dart:async';
import '../base/globals.dart';
import '../flx.dart'; import '../flx.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../toolchain.dart'; import '../toolchain.dart';
class BuildCommand extends FlutterCommand { class BuildCommand extends FlutterCommand {
final String name = 'build'; final String name = 'build';
final String description = 'Packages your Flutter app into an FLX.'; final String description = 'Package your Flutter app into an FLX.';
BuildCommand() { BuildCommand() {
argParser.addFlag('precompiled', negatable: false); argParser.addFlag('precompiled', negatable: false);
......
...@@ -7,7 +7,7 @@ import 'dart:async'; ...@@ -7,7 +7,7 @@ import 'dart:async';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart'; import '../globals.dart';
class CacheCommand extends Command { class CacheCommand extends Command {
final String name = 'cache'; final String name = 'cache';
......
...@@ -11,8 +11,8 @@ import 'package:path/path.dart' as path; ...@@ -11,8 +11,8 @@ import 'package:path/path.dart' as path;
import '../android/android.dart' as android; import '../android/android.dart' as android;
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
import '../globals.dart';
import '../ios/setup_xcodeproj.dart'; import '../ios/setup_xcodeproj.dart';
class CreateCommand extends Command { class CreateCommand extends Command {
......
...@@ -10,9 +10,9 @@ import '../android/adb.dart'; ...@@ -10,9 +10,9 @@ import '../android/adb.dart';
import '../android/android_sdk.dart'; import '../android/android_sdk.dart';
import '../android/device_android.dart'; import '../android/device_android.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/globals.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart';
import '../ios/device_ios.dart'; import '../ios/device_ios.dart';
import '../ios/simulator.dart'; import '../ios/simulator.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
import 'dart:async'; import 'dart:async';
import '../base/globals.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class DevicesCommand extends FlutterCommand { class DevicesCommand extends FlutterCommand {
......
...@@ -5,20 +5,20 @@ ...@@ -5,20 +5,20 @@
import 'dart:async'; import 'dart:async';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../runner/version.dart'; import '../runner/version.dart';
class DoctorCommand extends FlutterCommand { class DoctorCommand extends FlutterCommand {
final String name = 'doctor'; final String name = 'doctor';
final String description = 'Diagnose the flutter tool.'; final String description = 'Show information about the installed tooling.';
bool get requiresProjectRoot => false; bool get requiresProjectRoot => false;
Future<int> runInProject() async { Future<int> runInProject() async {
// general info // general info
String flutterRoot = ArtifactStore.flutterRoot; String flutterRoot = ArtifactStore.flutterRoot;
printStatus('Flutter root is $flutterRoot.'); printStatus('Flutter root: $flutterRoot.');
printStatus(''); printStatus('');
// doctor // doctor
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
import 'run.dart'; import 'run.dart';
class ListenCommand extends RunCommandBase { class ListenCommand extends RunCommandBase {
......
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
import 'dart:async'; import 'dart:async';
import '../base/globals.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class LogsCommand extends FlutterCommand { class LogsCommand extends FlutterCommand {
final String name = 'logs'; final String name = 'logs';
final String description = 'Show logs for running Flutter apps.'; final String description = 'Show log output for running Flutter apps.';
LogsCommand() { LogsCommand() {
argParser.addFlag('clear', argParser.addFlag('clear',
......
...@@ -7,8 +7,8 @@ import 'dart:io'; ...@@ -7,8 +7,8 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../base/globals.dart';
import '../flx.dart'; import '../flx.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class RefreshCommand extends FlutterCommand { class RefreshCommand extends FlutterCommand {
......
...@@ -9,11 +9,11 @@ import 'package:path/path.dart' as path; ...@@ -9,11 +9,11 @@ import 'package:path/path.dart' as path;
import '../application_package.dart'; import '../application_package.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/globals.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
import '../device.dart'; import '../device.dart';
import '../flx.dart'; import '../flx.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../toolchain.dart'; import '../toolchain.dart';
import 'apk.dart'; import 'apk.dart';
......
...@@ -8,10 +8,10 @@ import 'dart:io'; ...@@ -8,10 +8,10 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../flx.dart' as flx; import '../flx.dart' as flx;
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import 'run.dart'; import 'run.dart';
......
...@@ -9,14 +9,14 @@ import 'package:path/path.dart' as path; ...@@ -9,14 +9,14 @@ import 'package:path/path.dart' as path;
import 'package:test/src/executable.dart' as executable; import 'package:test/src/executable.dart' as executable;
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../test/loader.dart' as loader; import '../test/loader.dart' as loader;
class TestCommand extends FlutterCommand { class TestCommand extends FlutterCommand {
String get name => 'test'; String get name => 'test';
String get description => 'Runs Flutter unit tests for the current project (Linux only).'; String get description => 'Run Flutter unit tests for the current project (Linux only).';
bool get requiresProjectRoot => false; bool get requiresProjectRoot => false;
......
...@@ -6,7 +6,7 @@ import 'dart:async'; ...@@ -6,7 +6,7 @@ import 'dart:async';
import '../android/device_android.dart'; import '../android/device_android.dart';
import '../application_package.dart'; import '../application_package.dart';
import '../base/globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class TraceCommand extends FlutterCommand { class TraceCommand extends FlutterCommand {
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
import 'dart:async'; import 'dart:async';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../runner/version.dart'; import '../runner/version.dart';
......
...@@ -7,8 +7,8 @@ import 'dart:io'; ...@@ -7,8 +7,8 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
Future<int> pubGet({ Future<int> pubGet({
String directory, String directory,
......
...@@ -7,8 +7,8 @@ import 'dart:async'; ...@@ -7,8 +7,8 @@ import 'dart:async';
import 'android/device_android.dart'; import 'android/device_android.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/globals.dart';
import 'build_configuration.dart'; import 'build_configuration.dart';
import 'globals.dart';
import 'ios/device_ios.dart'; import 'ios/device_ios.dart';
import 'toolchain.dart'; import 'toolchain.dart';
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import 'android/android_workflow.dart'; import 'android/android_workflow.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/globals.dart'; import 'globals.dart';
import 'ios/ios_workflow.dart'; import 'ios/ios_workflow.dart';
class Doctor { class Doctor {
...@@ -34,6 +34,35 @@ class Doctor { ...@@ -34,6 +34,35 @@ class Doctor {
List<Workflow> get workflows => _workflows; List<Workflow> get workflows => _workflows;
/// Print a summary of the state of the tooling, as well as how to get more info.
void summary() => printStatus(summaryText);
String get summaryText {
StringBuffer buffer = new StringBuffer();
bool allGood = true;
for (Workflow workflow in workflows) {
ValidationResult result = workflow.validate();
buffer.write('${result.leadingBox} The ${workflow.name} toolchain is ');
if (result.type == ValidationType.missing)
buffer.writeln('not installed.');
else if (result.type == ValidationType.partial)
buffer.writeln('partially installed; more components are available.');
else
buffer.writeln('fully installed.');
if (result.type != ValidationType.installed)
allGood = false;
}
if (!allGood) {
buffer.writeln();
buffer.write('Run "flutter doctor" for information about installing additional components.');
}
return buffer.toString();
}
/// Print verbose information about the state of installed tooling. /// Print verbose information about the state of installed tooling.
void diagnose() { void diagnose() {
for (int i = 0; i < workflows.length; i++) { for (int i = 0; i < workflows.length; i++) {
...@@ -63,6 +92,8 @@ abstract class Workflow { ...@@ -63,6 +92,8 @@ abstract class Workflow {
/// Could this thing launch *something*? It may still have minor issues. /// Could this thing launch *something*? It may still have minor issues.
bool get canLaunchDevices; bool get canLaunchDevices;
ValidationResult validate();
/// Print verbose information about the state of the workflow. /// Print verbose information about the state of the workflow.
void diagnose(); void diagnose();
...@@ -85,20 +116,28 @@ class Validator { ...@@ -85,20 +116,28 @@ class Validator {
final String resolution; final String resolution;
final ValidationFunction validatorFunction; final ValidationFunction validatorFunction;
List<Validator> _children = []; List<Validator> _children = <Validator>[];
ValidationResult validate() { ValidationResult validate() {
if (validatorFunction != null) List<ValidationResult> childResults;
return new ValidationResult(validatorFunction(), this); ValidationType type;
List<ValidationResult> results = _children.map((Validator child) { if (validatorFunction != null)
return child.validate(); type = validatorFunction();
}).toList();
childResults = _children.map((Validator child) => child.validate()).toList();
// If there's no immediate validator, the result we return is synthesized
// from the sub-tree of children. This is so we can show that the branch is
// not fully installed.
if (type == null) {
type = _combine(childResults
.expand((ValidationResult child) => child._allResults)
.map((ValidationResult result) => result.type)
);
}
ValidationType type = _combine(results.map((ValidationResult result) { return new ValidationResult(type, this, childResults);
return result.type;
}));
return new ValidationResult(type, this, results);
} }
ValidationType _combine(Iterable<ValidationType> types) { ValidationType _combine(Iterable<ValidationType> types) {
...@@ -119,6 +158,15 @@ class ValidationResult { ...@@ -119,6 +158,15 @@ class ValidationResult {
final Validator validator; final Validator validator;
final List<ValidationResult> childResults; final List<ValidationResult> childResults;
String get leadingBox {
if (type == ValidationType.missing)
return '[ ]';
else if (type == ValidationType.installed)
return '[✓]';
else
return '[-]';
}
void print([String indent = '']) { void print([String indent = '']) {
printSelf(indent); printSelf(indent);
...@@ -126,15 +174,15 @@ class ValidationResult { ...@@ -126,15 +174,15 @@ class ValidationResult {
child.print(indent + ' '); child.print(indent + ' ');
} }
void printSelf(String indent) { void printSelf([String indent = '']) {
String result = indent; String result = indent;
if (type == ValidationType.missing) if (type == ValidationType.missing)
result += '[ ] '; result += '$leadingBox ';
else if (type == ValidationType.installed) else if (type == ValidationType.installed)
result += '[✓] '; result += '$leadingBox ';
else else
result += '[-] '; result += '$leadingBox ';
result += '${validator.name} '; result += '${validator.name} ';
...@@ -151,4 +199,10 @@ class ValidationResult { ...@@ -151,4 +199,10 @@ class ValidationResult {
if (type == ValidationType.missing && validator.resolution != null) if (type == ValidationType.missing && validator.resolution != null)
printStatus('$indent ${validator.resolution}'); printStatus('$indent ${validator.resolution}');
} }
List<ValidationResult> get _allResults {
List<ValidationResult> results = <ValidationResult>[this];
results.addAll(childResults);
return results;
}
} }
...@@ -14,7 +14,7 @@ import 'package:path/path.dart' as path; ...@@ -14,7 +14,7 @@ import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/globals.dart'; import 'globals.dart';
import 'toolchain.dart'; import 'toolchain.dart';
const String defaultMainPath = 'lib/main.dart'; const String defaultMainPath = 'lib/main.dart';
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import '../android/android_sdk.dart'; import 'android/android_sdk.dart';
import '../device.dart'; import 'base/context.dart';
import '../doctor.dart'; import 'base/logger.dart';
import '../ios/mac.dart'; import 'device.dart';
import 'context.dart'; import 'doctor.dart';
import 'logger.dart'; import 'ios/mac.dart';
DeviceManager get deviceManager => context[DeviceManager]; DeviceManager get deviceManager => context[DeviceManager];
Logger get logger => context[Logger]; Logger get logger => context[Logger];
......
...@@ -3,21 +3,21 @@ ...@@ -3,21 +3,21 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../application_package.dart'; import '../application_package.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart';
import '../ios/setup_xcodeproj.dart';
import '../services.dart'; import '../services.dart';
import '../toolchain.dart'; import '../toolchain.dart';
import '../ios/setup_xcodeproj.dart';
import 'simulator.dart'; import 'simulator.dart';
const String _ideviceinstallerInstructions = const String _ideviceinstallerInstructions =
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
import 'dart:io'; import 'dart:io';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../doctor.dart'; import '../doctor.dart';
import '../globals.dart';
class IOSWorkflow extends Workflow { class IOSWorkflow extends Workflow {
IOSWorkflow() : super('iOS'); IOSWorkflow() : super('iOS');
...@@ -20,8 +20,11 @@ class IOSWorkflow extends Workflow { ...@@ -20,8 +20,11 @@ class IOSWorkflow extends Workflow {
// for real devices. // for real devices.
bool get canLaunchDevices => xcode.isInstalled; bool get canLaunchDevices => xcode.isInstalled;
void diagnose() { ValidationResult validate() {
Validator iosValidator = new Validator('Develop for iOS devices'); Validator iosValidator = new Validator(
'$name toolchain',
description: 'develop for iOS devices'
);
Function _xcodeExists = () { Function _xcodeExists = () {
return xcode.isInstalled ? ValidationType.installed : ValidationType.missing; return xcode.isInstalled ? ValidationType.installed : ValidationType.missing;
...@@ -48,30 +51,34 @@ class IOSWorkflow extends Workflow { ...@@ -48,30 +51,34 @@ class IOSWorkflow extends Workflow {
validatorFunction: _xcodeExists validatorFunction: _xcodeExists
)); ));
iosValidator.addValidator(new Validator( Validator brewValidator = new Validator(
'brew', 'brew',
description: 'install additional development packages', description: 'install additional development packages',
resolution: 'Download at http://brew.sh/', resolution: 'Download at http://brew.sh/',
validatorFunction: _brewExists validatorFunction: _brewExists
)); );
iosValidator.addValidator(new Validator( iosValidator.addValidator(brewValidator);
brewValidator.addValidator(new Validator(
'ideviceinstaller', 'ideviceinstaller',
description: 'discover connected iOS devices', description: 'discover connected iOS devices',
resolution: "Install via 'brew install ideviceinstaller'", resolution: "Install via 'brew install ideviceinstaller'",
validatorFunction: _ideviceinstallerExists validatorFunction: _ideviceinstallerExists
)); ));
iosValidator.addValidator(new Validator( brewValidator.addValidator(new Validator(
'ios-deploy', 'ios-deploy',
description: 'deploy to connected iOS devices', description: 'deploy to connected iOS devices',
resolution: "Install via 'brew install ios-deploy'", resolution: "Install via 'brew install ios-deploy'",
validatorFunction: _iosdeployExists validatorFunction: _iosdeployExists
)); ));
iosValidator.validate().print(); return iosValidator.validate();
} }
void diagnose() => validate().print();
bool get hasIdeviceId => exitsHappy(<String>['idevice_id', '-h']); bool get hasIdeviceId => exitsHappy(<String>['idevice_id', '-h']);
/// Return whether the tooling to list and deploy to real iOS devices (not the /// Return whether the tooling to list and deploy to real iOS devices (not the
......
...@@ -8,8 +8,8 @@ import 'dart:io'; ...@@ -8,8 +8,8 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
import '../runner/flutter_command_runner.dart'; import '../runner/flutter_command_runner.dart';
/// A map from file path to file contents. /// A map from file path to file contents.
......
...@@ -6,8 +6,8 @@ import 'dart:async'; ...@@ -6,8 +6,8 @@ import 'dart:async';
import 'dart:convert' show JSON; import 'dart:convert' show JSON;
import 'dart:io'; import 'dart:io';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart';
const String _xcrunPath = '/usr/bin/xcrun'; const String _xcrunPath = '/usr/bin/xcrun';
......
...@@ -9,9 +9,9 @@ import 'package:args/command_runner.dart'; ...@@ -9,9 +9,9 @@ import 'package:args/command_runner.dart';
import '../application_package.dart'; import '../application_package.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/globals.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart';
import '../toolchain.dart'; import '../toolchain.dart';
import 'flutter_command_runner.dart'; import 'flutter_command_runner.dart';
......
...@@ -12,9 +12,9 @@ import 'package:path/path.dart' as path; ...@@ -12,9 +12,9 @@ import 'package:path/path.dart' as path;
import '../android/android_sdk.dart'; import '../android/android_sdk.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../globals.dart';
import 'version.dart'; import 'version.dart';
const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo) const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
...@@ -45,6 +45,7 @@ class FlutterCommandRunner extends CommandRunner { ...@@ -45,6 +45,7 @@ class FlutterCommandRunner extends CommandRunner {
else else
packagesHelp = '\n(required, since the current directory does not contain a "packages" subdirectory)'; packagesHelp = '\n(required, since the current directory does not contain a "packages" subdirectory)';
argParser.addOption('package-root', argParser.addOption('package-root',
hide: !verboseHelp,
help: 'Path to your packages directory.$packagesHelp'); help: 'Path to your packages directory.$packagesHelp');
argParser.addOption('flutter-root', argParser.addOption('flutter-root',
help: 'The root directory of the Flutter repository. Uses \$$kFlutterRootEnvironmentVariableName if set,\n' help: 'The root directory of the Flutter repository. Uses \$$kFlutterRootEnvironmentVariableName if set,\n'
...@@ -122,7 +123,10 @@ class FlutterCommandRunner extends CommandRunner { ...@@ -122,7 +123,10 @@ class FlutterCommandRunner extends CommandRunner {
defaultsTo: 'out/ios_sim_Release/'); defaultsTo: 'out/ios_sim_Release/');
} }
final String usageFooter = 'Run "flutter -h -v" for verbose help output, including less commonly used options.'; String get usageFooter =>
'Run "flutter -h -v" for verbose help output, including less commonly used options.\n'
'\n'
'${doctor.summaryText}';
List<BuildConfiguration> get buildConfigurations { List<BuildConfiguration> get buildConfigurations {
if (_buildConfigurations == null) if (_buildConfigurations == null)
...@@ -191,6 +195,8 @@ class FlutterCommandRunner extends CommandRunner { ...@@ -191,6 +195,8 @@ class FlutterCommandRunner extends CommandRunner {
if (globalResults['version']) { if (globalResults['version']) {
printStatus(getVersion(ArtifactStore.flutterRoot)); printStatus(getVersion(ArtifactStore.flutterRoot));
printStatus('');
doctor.summary();
return new Future<int>.value(0); return new Future<int>.value(0);
} }
......
...@@ -10,7 +10,7 @@ import 'package:path/path.dart' as path; ...@@ -10,7 +10,7 @@ import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'artifacts.dart'; import 'artifacts.dart';
import 'base/globals.dart'; import 'globals.dart';
const String _kFlutterManifestPath = 'flutter.yaml'; const String _kFlutterManifestPath = 'flutter.yaml';
const String _kFlutterServicesManifestPath = 'flutter_services.yaml'; const String _kFlutterServicesManifestPath = 'flutter_services.yaml';
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter_tools/src/base/context.dart' hide context; import 'package:flutter_tools/src/base/context.dart' hide context;
import 'package:flutter_tools/src/base/globals.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/globals.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
main() => defineTests(); main() => defineTests();
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/globals.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/commands/daemon.dart'; import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:flutter_tools/src/globals.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
......
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