Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
25f332d8
Commit
25f332d8
authored
Mar 23, 2016
by
Devon Carew
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
re-work the doctor command
parent
1db09ffe
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
311 additions
and
335 deletions
+311
-335
android_sdk.dart
packages/flutter_tools/lib/src/android/android_sdk.dart
+26
-26
android_workflow.dart
packages/flutter_tools/lib/src/android/android_workflow.dart
+37
-25
build_apk.dart
packages/flutter_tools/lib/src/commands/build_apk.dart
+6
-2
doctor.dart
packages/flutter_tools/lib/src/commands/doctor.dart
+0
-12
upgrade.dart
packages/flutter_tools/lib/src/commands/upgrade.dart
+2
-2
doctor.dart
packages/flutter_tools/lib/src/doctor.dart
+101
-130
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+1
-1
ios_workflow.dart
packages/flutter_tools/lib/src/ios/ios_workflow.dart
+77
-93
mac.dart
packages/flutter_tools/lib/src/ios/mac.dart
+13
-16
flutter_command_runner.dart
.../flutter_tools/lib/src/runner/flutter_command_runner.dart
+1
-9
version.dart
packages/flutter_tools/lib/src/runner/version.dart
+47
-19
No files found.
packages/flutter_tools/lib/src/android/android_sdk.dart
View file @
25f332d8
...
...
@@ -102,20 +102,16 @@ class AndroidSdk {
String
get
adbPath
=>
getPlatformToolsPath
(
'adb'
);
bool
validateSdkWellFormed
({
bool
complain:
false
})
{
if
(!
FileSystemEntity
.
isFileSync
(
adbPath
))
{
if
(
complain
)
printError
(
'Android SDK file not found:
$adbPath
.'
);
return
false
;
}
/// Validate the Android SDK. This returns an empty list if there are no
/// issues; otherwise, it returns a list of issues found.
List
<
String
>
validateSdkWellFormed
()
{
if
(!
FileSystemEntity
.
isFileSync
(
adbPath
))
return
<
String
>[
'Android SDK file not found:
$adbPath
.'
];
if
(
sdkVersions
.
isEmpty
)
{
if
(
complain
)
printError
(
'Android SDK does not have the proper build-tools.'
);
return
false
;
}
if
(
sdkVersions
.
isEmpty
||
latestVersion
==
null
)
return
<
String
>[
'Android SDK does not have the proper build-tools.'
];
return
latestVersion
.
validateSdkWellFormed
(
complain:
complain
);
return
latestVersion
.
validateSdkWellFormed
();
}
String
getPlatformToolsPath
(
String
binaryName
)
{
...
...
@@ -215,12 +211,20 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> {
String
get
zipalignPath
=>
getBuildToolsPath
(
'zipalign'
);
bool
validateSdkWellFormed
({
bool
complain:
false
})
{
return
_exists
(
androidJarPath
,
complain:
complain
)
&&
_exists
(
aaptPath
,
complain:
complain
)
&&
_exists
(
dxPath
,
complain:
complain
)
&&
_exists
(
zipalignPath
,
complain:
complain
);
List
<
String
>
validateSdkWellFormed
()
{
if
(
_exists
(
androidJarPath
)
!=
null
)
return
<
String
>[
_exists
(
androidJarPath
)];
if
(
_exists
(
aaptPath
)
!=
null
)
return
<
String
>[
_exists
(
aaptPath
)];
if
(
_exists
(
dxPath
)
!=
null
)
return
<
String
>[
_exists
(
dxPath
)];
if
(
_exists
(
zipalignPath
)
!=
null
)
return
<
String
>[
_exists
(
zipalignPath
)];
return
<
String
>[];
}
String
getPlatformsPath
(
String
itemName
)
{
...
...
@@ -237,13 +241,9 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> {
@override
String
toString
()
=>
'[
${sdk.directory}
, SDK version
$sdkLevel
, build-tools
$buildToolsVersionName
]'
;
bool
_exists
(
String
path
,
{
bool
complain:
false
})
{
if
(!
FileSystemEntity
.
isFileSync
(
path
))
{
if
(
complain
)
printError
(
'Android SDK file not found:
$path
.'
);
return
false
;
}
return
true
;
String
_exists
(
String
path
)
{
if
(!
FileSystemEntity
.
isFileSync
(
path
))
return
'Android SDK file not found:
$path
.'
;
return
null
;
}
}
packages/flutter_tools/lib/src/android/android_workflow.dart
View file @
25f332d8
...
...
@@ -6,9 +6,8 @@ import '../doctor.dart';
import
'../globals.dart'
;
import
'android_sdk.dart'
;
class
AndroidWorkflow
extends
Workflow
{
@override
String
get
label
=>
'Android toolchain'
;
class
AndroidWorkflow
extends
DoctorValidator
implements
Workflow
{
AndroidWorkflow
()
:
super
(
'Android toolchain - develop for Android devices'
);
@override
bool
get
appliesToHostPlatform
=>
true
;
...
...
@@ -17,30 +16,43 @@ class AndroidWorkflow extends Workflow {
bool
get
canListDevices
=>
getAdbPath
(
androidSdk
)
!=
null
;
@override
bool
get
canLaunchDevices
=>
androidSdk
!=
null
&&
androidSdk
.
validateSdkWellFormed
(
complain:
false
)
;
bool
get
canLaunchDevices
=>
androidSdk
!=
null
&&
androidSdk
.
validateSdkWellFormed
(
).
isEmpty
;
@override
ValidationResult
validate
()
{
Validator
androidValidator
=
new
Validator
(
label
,
description:
'develop for Android devices'
);
ValidationType
sdkExists
()
{
return
androidSdk
==
null
?
ValidationType
.
missing
:
ValidationType
.
installed
;
};
androidValidator
.
addValidator
(
new
Validator
(
'Android Studio / Android SDK'
,
description:
'enable development for Android devices'
,
resolution:
'Download from https://developer.android.com/sdk/ (or visit '
'https://flutter.io/setup/#android-setup for detailed instructions)'
,
validatorFunction:
sdkExists
List
<
ValidationMessage
>
messages
=
<
ValidationMessage
>[];
ValidationType
type
=
ValidationType
.
missing
;
String
sdkVersionText
;
if
(
androidSdk
==
null
)
{
messages
.
add
(
new
ValidationMessage
.
error
(
'Android Studio / Android SDK not found. Download from https://developer.android.com/sdk/
\n
'
'(or visit https://flutter.io/setup/#android-setup for detailed instructions).'
));
}
else
{
type
=
ValidationType
.
partial
;
messages
.
add
(
new
ValidationMessage
(
'Android SDK at
${androidSdk.directory}
'
));
if
(
androidSdk
.
latestVersion
!=
null
)
{
sdkVersionText
=
'Android SDK
${androidSdk.latestVersion.buildToolsVersionName}
'
;
return
androidValidator
.
validate
();
messages
.
add
(
new
ValidationMessage
(
'Platform
${androidSdk.latestVersion.platformVersionName}
'
));
messages
.
add
(
new
ValidationMessage
(
'Build-tools
${androidSdk.latestVersion.buildToolsVersionName}
'
));
}
@override
void
diagnose
()
=>
validate
().
print
();
List
<
String
>
validationResult
=
androidSdk
.
validateSdkWellFormed
();
if
(
validationResult
.
isEmpty
)
{
type
=
ValidationType
.
installed
;
}
else
{
messages
.
addAll
(
validationResult
.
map
((
String
message
)
{
return
new
ValidationMessage
.
error
(
message
);
}));
messages
.
add
(
new
ValidationMessage
(
'Try re-installing or updating your Android SDK.'
));
}
}
return
new
ValidationResult
(
type
,
messages
,
statusInfo:
sdkVersionText
);
}
}
packages/flutter_tools/lib/src/commands/build_apk.dart
View file @
25f332d8
...
...
@@ -178,7 +178,9 @@ class BuildApkCommand extends FlutterCommand {
return
1
;
}
if
(!
androidSdk
.
validateSdkWellFormed
(
complain:
true
))
{
List
<
String
>
validationResult
=
androidSdk
.
validateSdkWellFormed
();
if
(
validationResult
.
isNotEmpty
)
{
validationResult
.
forEach
(
printError
);
printError
(
'Try re-installing or updating your Android SDK.'
);
return
1
;
}
...
...
@@ -375,7 +377,9 @@ Future<int> buildAndroid({
return
1
;
}
if
(!
androidSdk
.
validateSdkWellFormed
(
complain:
true
))
{
List
<
String
>
validationResult
=
androidSdk
.
validateSdkWellFormed
();
if
(
validationResult
.
isNotEmpty
)
{
validationResult
.
forEach
(
printError
);
printError
(
'Try re-installing or updating your Android SDK.'
);
return
1
;
}
...
...
packages/flutter_tools/lib/src/commands/doctor.dart
View file @
25f332d8
...
...
@@ -4,10 +4,8 @@
import
'dart:async'
;
import
'../artifacts.dart'
;
import
'../globals.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../runner/version.dart'
;
class
DoctorCommand
extends
FlutterCommand
{
@override
...
...
@@ -21,18 +19,8 @@ class DoctorCommand extends FlutterCommand {
@override
Future
<
int
>
runInProject
()
async
{
// general info
String
flutterRoot
=
ArtifactStore
.
flutterRoot
;
printStatus
(
'Flutter root:
$flutterRoot
.'
);
printStatus
(
''
);
// doctor
doctor
.
diagnose
();
printStatus
(
''
);
// version
printStatus
(
getVersion
(
flutterRoot
));
return
0
;
}
}
packages/flutter_tools/lib/src/commands/upgrade.dart
View file @
25f332d8
...
...
@@ -22,7 +22,7 @@ class UpgradeCommand extends FlutterCommand {
@override
Future
<
int
>
runInProject
()
async
{
printStatus
(
getVersion
(
ArtifactStore
.
flutterRoot
));
printStatus
(
FlutterVersion
.
getVersion
(
ArtifactStore
.
flutterRoot
).
toString
(
));
try
{
runCheckedSync
(<
String
>[
...
...
@@ -50,7 +50,7 @@ class UpgradeCommand extends FlutterCommand {
return
code
;
printStatus
(
''
);
printStatus
(
getVersion
(
ArtifactStore
.
flutterRoot
));
printStatus
(
FlutterVersion
.
getVersion
(
ArtifactStore
.
flutterRoot
).
toString
(
));
return
0
;
}
...
...
packages/flutter_tools/lib/src/doctor.dart
View file @
25f332d8
...
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:convert'
show
JSON
;
import
'dart:io'
;
import
'package:path/path.dart'
as
path
;
...
...
@@ -11,19 +12,20 @@ import 'base/context.dart';
import
'base/os.dart'
;
import
'globals.dart'
;
import
'ios/ios_workflow.dart'
;
// TODO(devoncarew): Make it easy to add version information to the `doctor` printout.
import
'runner/version.dart'
;
class
Doctor
{
Doctor
()
{
_iosWorkflow
=
new
IOSWorkflow
();
if
(
_iosWorkflow
.
appliesToHostPlatform
)
_validators
.
add
(
_iosWorkflow
);
_validators
.
add
(
new
_FlutterValidator
());
_androidWorkflow
=
new
AndroidWorkflow
();
if
(
_androidWorkflow
.
appliesToHostPlatform
)
_validators
.
add
(
_androidWorkflow
);
_iosWorkflow
=
new
IOSWorkflow
();
if
(
_iosWorkflow
.
appliesToHostPlatform
)
_validators
.
add
(
_iosWorkflow
);
_validators
.
add
(
new
_AtomValidator
());
}
...
...
@@ -55,13 +57,19 @@ class Doctor {
for
(
DoctorValidator
validator
in
_validators
)
{
ValidationResult
result
=
validator
.
validate
();
buffer
.
write
(
'
${result.leadingBox}
The
${validator.label
}
is '
);
buffer
.
write
(
'
${result.leadingBox}
${validator.title
}
is '
);
if
(
result
.
type
==
ValidationType
.
missing
)
buffer
.
write
ln
(
'not installed.'
);
buffer
.
write
(
'not installed.'
);
else
if
(
result
.
type
==
ValidationType
.
partial
)
buffer
.
write
ln
(
'partially installed; more components are available.'
);
buffer
.
write
(
'partially installed; more components are available.'
);
else
buffer
.
writeln
(
'fully installed.'
);
buffer
.
write
(
'fully installed.'
);
if
(
result
.
statusInfo
!=
null
)
buffer
.
write
(
' (
${result.statusInfo}
)'
);
buffer
.
writeln
();
if
(
result
.
type
!=
ValidationType
.
installed
)
allGood
=
false
;
}
...
...
@@ -77,11 +85,26 @@ class Doctor {
/// Print verbose information about the state of installed tooling.
void
diagnose
()
{
bool
firstLine
=
true
;
for
(
DoctorValidator
validator
in
_validators
)
{
if
(!
firstLine
)
printStatus
(
''
);
firstLine
=
false
;
validator
.
diagnose
();
ValidationResult
result
=
validator
.
validate
();
if
(
result
.
statusInfo
!=
null
)
printStatus
(
'
${result.leadingBox}
${validator.title}
(
${result.statusInfo}
)'
);
else
printStatus
(
'
${result.leadingBox}
${validator.title}
'
);
for
(
ValidationMessage
message
in
result
.
messages
)
{
if
(
message
.
isError
)
{
printStatus
(
' x
${message.message.replaceAll('\n', '\n ')}
'
);
}
else
{
printStatus
(
' •
${message.message.replaceAll('\n', '\n ')}
'
);
}
}
}
}
...
...
@@ -90,17 +113,8 @@ class Doctor {
bool
get
canLaunchAnything
=>
workflows
.
any
((
Workflow
workflow
)
=>
workflow
.
canLaunchDevices
);
}
abstract
class
DoctorValidator
{
String
get
label
;
ValidationResult
validate
();
/// Print verbose information about the state of the workflow.
void
diagnose
();
}
/// A series of tools and required install steps for a target platform (iOS or Android).
abstract
class
Workflow
extends
DoctorValidator
{
abstract
class
Workflow
{
/// Whether the workflow applies to this platform (as in, should we ever try and use it).
bool
get
appliesToHostPlatform
;
...
...
@@ -117,57 +131,21 @@ enum ValidationType {
installed
}
typedef
ValidationType
ValidationFunction
(
);
class
Validator
{
Validator
(
this
.
name
,
{
this
.
description
,
this
.
resolution
,
this
.
validatorFunction
});
final
String
name
;
final
String
description
;
final
String
resolution
;
final
ValidationFunction
validatorFunction
;
List
<
Validator
>
_children
=
<
Validator
>[];
ValidationResult
validate
()
{
List
<
ValidationResult
>
childResults
;
ValidationType
type
;
if
(
validatorFunction
!=
null
)
type
=
validatorFunction
();
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
)
);
}
return
new
ValidationResult
(
type
,
this
,
childResults
);
}
abstract
class
DoctorValidator
{
DoctorValidator
(
this
.
title
);
ValidationType
_combine
(
Iterable
<
ValidationType
>
types
)
{
if
(
types
.
contains
(
ValidationType
.
missing
)
&&
types
.
contains
(
ValidationType
.
installed
))
return
ValidationType
.
partial
;
if
(
types
.
contains
(
ValidationType
.
missing
))
return
ValidationType
.
missing
;
return
ValidationType
.
installed
;
}
final
String
title
;
void
addValidator
(
Validator
validator
)
=>
_children
.
add
(
validator
);
ValidationResult
validate
(
);
}
class
ValidationResult
{
ValidationResult
(
this
.
type
,
this
.
validator
,
[
this
.
childResults
=
const
<
ValidationResult
>[]]
);
ValidationResult
(
this
.
type
,
this
.
messages
,
{
this
.
statusInfo
}
);
final
ValidationType
type
;
final
Validator
validator
;
final
List
<
ValidationResult
>
childResults
;
// A short message about the status.
final
String
statusInfo
;
final
List
<
ValidationMessage
>
messages
;
String
get
leadingBox
{
if
(
type
==
ValidationType
.
missing
)
...
...
@@ -177,49 +155,42 @@ class ValidationResult {
else
return
'[-]'
;
}
}
void
print
([
String
indent
=
''
])
{
printSelf
(
indent
);
for
(
ValidationResult
child
in
childResults
)
child
.
print
(
indent
+
' '
);
}
void
printSelf
([
String
indent
=
''
])
{
String
result
=
indent
;
class
ValidationMessage
{
ValidationMessage
(
this
.
message
)
:
isError
=
false
;
ValidationMessage
.
error
(
this
.
message
)
:
isError
=
true
;
if
(
type
==
ValidationType
.
missing
)
result
+=
'
$leadingBox
'
;
else
if
(
type
==
ValidationType
.
installed
)
result
+=
'
$leadingBox
'
;
else
result
+=
'
$leadingBox
'
;
final
bool
isError
;
final
String
message
;
result
+=
'
${validator.name}
'
;
@override
String
toString
()
=>
message
;
}
if
(
validator
.
description
!=
null
)
result
+=
'-
${validator.description}
'
;
class
_FlutterValidator
extends
DoctorValidator
{
_FlutterValidator
()
:
super
(
'Flutter'
)
;
if
(
type
==
ValidationType
.
missing
)
result
+=
'(missing)'
;
else
if
(
type
==
ValidationType
.
installed
)
result
+=
'(installed)'
;
@override
ValidationResult
validate
()
{
List
<
ValidationMessage
>
messages
=
<
ValidationMessage
>[];
printStatus
(
result
);
FlutterVersion
version
=
FlutterVersion
.
getVersion
(
);
if
(
type
==
ValidationType
.
missing
&&
validator
.
resolution
!=
null
)
printStatus
(
'
$indent
${validator.resolution}
'
);
}
messages
.
add
(
new
ValidationMessage
(
'Flutter root at
${version.flutterRoot}
'
));
messages
.
add
(
new
ValidationMessage
(
'Framework revision
${version.frameworkRevisionShort}
'
'(
${version.frameworkAge}
)'
));
messages
.
add
(
new
ValidationMessage
(
'Engine revision
${version.engineRevisionShort}
'
));
List
<
ValidationResult
>
get
_allResults
{
List
<
ValidationResult
>
results
=
<
ValidationResult
>[
this
];
results
.
addAll
(
childResults
);
return
results
;
return
new
ValidationResult
(
ValidationType
.
installed
,
messages
,
statusInfo:
'
${version.frameworkRevisionShort}
- channel
${version.channel}
'
);
}
}
class
_AtomValidator
extends
DoctorValidator
{
static
String
getAtomHomePath
()
{
_AtomValidator
()
:
super
(
'Atom - a lightweight development environment for Flutter'
);
static
String
_getAtomHomePath
()
{
final
Map
<
String
,
String
>
env
=
Platform
.
environment
;
if
(
env
[
'ATOM_HOME'
]
!=
null
)
return
env
[
'ATOM_HOME'
];
...
...
@@ -228,43 +199,43 @@ class _AtomValidator extends DoctorValidator {
:
path
.
join
(
env
[
'HOME'
],
'.atom'
);
}
@override
String
get
label
=>
'Atom development environment'
;
@override
ValidationResult
validate
()
{
Validator
atomValidator
=
new
Validator
(
label
,
description:
'a lightweight development environment for Flutter'
);
List
<
ValidationMessage
>
messages
=
<
ValidationMessage
>[];
ValidationType
atomExists
()
{
bool
atomDirExists
=
FileSystemEntity
.
isDirectorySync
(
getAtomHomePath
());
return
atomDirExists
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
flutterPluginExists
()
{
String
flutterPluginPath
=
path
.
join
(
getAtomHomePath
(),
'packages'
,
'flutter'
);
bool
flutterPluginExists
=
FileSystemEntity
.
isDirectorySync
(
flutterPluginPath
);
return
flutterPluginExists
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
atomValidator
.
addValidator
(
new
Validator
(
'Atom editor'
,
resolution:
'Download at https://atom.io'
,
validatorFunction:
atomExists
int
installCount
=
0
;
bool
atomDirExists
=
FileSystemEntity
.
isDirectorySync
(
_getAtomHomePath
());
if
(!
atomDirExists
)
{
messages
.
add
(
new
ValidationMessage
.
error
(
'Atom not installed; download at https://atom.io.'
));
}
else
{
installCount
++;
}
atomValidator
.
addValidator
(
new
Validator
(
'Flutter plugin'
,
description:
'adds Flutter specific functionality to Atom'
,
resolution:
"Install the 'flutter' plugin in Atom or run 'apm install flutter'"
,
validatorFunction:
flutterPluginExists
String
flutterPluginPath
=
path
.
join
(
_getAtomHomePath
(),
'packages'
,
'flutter'
);
if
(!
FileSystemEntity
.
isDirectorySync
(
flutterPluginPath
))
{
messages
.
add
(
new
ValidationMessage
.
error
(
'Flutter plugin not installed; this adds Flutter specific functionality to Atom.
\n
'
'Install the
\'
flutter
\'
plugin in Atom or run
\'
apm install flutter
\'
.'
));
}
else
{
installCount
++;
return
atomValidator
.
validate
();
try
{
File
packageFile
=
new
File
(
path
.
join
(
flutterPluginPath
,
'package.json'
));
dynamic
packageInfo
=
JSON
.
decode
(
packageFile
.
readAsStringSync
());
String
version
=
packageInfo
[
'version'
];
messages
.
add
(
new
ValidationMessage
(
'Atom installed; flutter plugin version
$version
'
));
}
catch
(
error
)
{
printTrace
(
'Unable to read flutter plugin version:
$error
'
);
}
}
@override
void
diagnose
()
=>
validate
().
print
();
return
new
ValidationResult
(
installCount
==
2
?
ValidationType
.
installed
:
installCount
==
1
?
ValidationType
.
partial
:
ValidationType
.
missing
,
messages
);
}
}
packages/flutter_tools/lib/src/ios/devices.dart
View file @
25f332d8
...
...
@@ -79,7 +79,7 @@ class IOSDevice extends Device {
bool
get
supportsStartPaused
=>
false
;
static
List
<
IOSDevice
>
getAttachedDevices
([
IOSDevice
mockIOS
])
{
if
(!
doctor
.
iosWorkflow
.
hasI
d
eviceId
)
if
(!
doctor
.
iosWorkflow
.
hasI
D
eviceId
)
return
<
IOSDevice
>[];
List
<
IOSDevice
>
devices
=
[];
...
...
packages/flutter_tools/lib/src/ios/ios_workflow.dart
View file @
25f332d8
...
...
@@ -8,112 +8,96 @@ import '../base/process.dart';
import
'../doctor.dart'
;
import
'mac.dart'
;
class
IOSWorkflow
extends
Workflow
{
@override
String
get
label
=>
'iOS toolchain'
;
XCode
get
xcode
=>
XCode
.
instance
;
class
IOSWorkflow
extends
DoctorValidator
implements
Workflow
{
IOSWorkflow
()
:
super
(
'iOS toolchain - develop for iOS devices'
);
@override
bool
get
appliesToHostPlatform
=>
Platform
.
isMacOS
;
// We need xcode (+simctl) to list simulator devices, and idevice_id to list real devices.
@override
bool
get
canListDevices
=>
XCode
.
instanc
e
.
isInstalledAndMeetsVersionCheck
;
bool
get
canListDevices
=>
xcod
e
.
isInstalledAndMeetsVersionCheck
;
// We need xcode to launch simulator devices, and ideviceinstaller and ios-deploy
// for real devices.
@override
bool
get
canLaunchDevices
=>
XCode
.
instance
.
isInstalledAndMeetsVersionCheck
;
bool
get
canLaunchDevices
=>
xcode
.
isInstalledAndMeetsVersionCheck
;
bool
get
hasIDeviceId
=>
exitsHappy
(<
String
>[
'idevice_id'
,
'-h'
]);
@override
ValidationResult
validate
()
{
Validator
iosValidator
=
new
Validator
(
label
,
description:
'develop for iOS devices'
);
List
<
ValidationMessage
>
messages
=
<
ValidationMessage
>[];
int
installCount
=
0
;
String
xcodeVersionInfo
;
ValidationType
xcodeExists
()
{
return
XCode
.
instance
.
isInstalled
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
xcodeVersionSatisfactory
()
{
return
XCode
.
instance
.
isInstalledAndMeetsVersionCheck
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
xcodeEulaSigned
()
{
return
XCode
.
instance
.
eulaSigned
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
brewExists
()
{
return
exitsHappy
(<
String
>[
'brew'
,
'-v'
])
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
ideviceinstallerExists
()
{
return
exitsHappy
(<
String
>[
'ideviceinstaller'
,
'-h'
])
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
ValidationType
iosdeployExists
()
{
return
hasIdeviceId
?
ValidationType
.
installed
:
ValidationType
.
missing
;
};
Validator
xcodeValidator
=
new
Validator
(
'XCode'
,
description:
'enable development for iOS devices'
,
resolution:
'Download at https://developer.apple.com/xcode/download/'
,
validatorFunction:
xcodeExists
);
if
(
xcode
.
isInstalled
)
{
installCount
++;
iosValidator
.
addValidator
(
xcodeValidator
);
xcodeVersionInfo
=
xcode
.
xcodeVersionText
;
if
(
xcodeVersionInfo
.
contains
(
','
))
xcodeVersionInfo
=
xcodeVersionInfo
.
substring
(
0
,
xcodeVersionInfo
.
indexOf
(
','
));
xcodeValidator
.
addValidator
(
new
Validator
(
'version'
,
description:
'Xcode minimum version of
$kXcodeRequiredVersionMajor
.
$kXcodeRequiredVersionMinor
.0'
,
resolution:
'Download the latest version or update via the Mac App Store'
,
validatorFunction:
xcodeVersionSatisfactory
messages
.
add
(
new
ValidationMessage
(
xcode
.
xcodeVersionText
));
if
(!
xcode
.
isInstalledAndMeetsVersionCheck
)
{
messages
.
add
(
new
ValidationMessage
.
error
(
'Flutter requires a minimum XCode version of
$kXcodeRequiredVersionMajor
.
$kXcodeRequiredVersionMinor
.0.
\n
'
'Download the latest version or update via the Mac App Store.'
));
}
xcodeValidator
.
addValidator
(
new
Validator
(
'EULA'
,
description:
'XCode end user license agreement'
,
resolution:
"Open XCode or run the command 'sudo xcodebuild -license'"
,
validatorFunction:
xcodeEulaSigned
if
(!
xcode
.
eulaSigned
)
{
messages
.
add
(
new
ValidationMessage
.
error
(
'XCode end user license agreement not signed; open XCode or run the command
\'
sudo xcodebuild -license
\'
.'
));
}
}
else
{
messages
.
add
(
new
ValidationMessage
.
error
(
'XCode not installed; this is necessary for iOS development.
\n
'
'Download at https://developer.apple.com/xcode/download/.'
));
}
Validator
brewValidator
=
new
Validator
(
'brew'
,
description:
'install additional development packages'
,
resolution:
'Download at http://brew.sh/'
,
validatorFunction:
brewExists
);
// brew installed
if
(
exitsHappy
(<
String
>[
'brew'
,
'-v'
]))
{
installCount
++;
iosValidator
.
addValidator
(
brewValidator
)
;
List
<
String
>
installed
=
<
String
>[]
;
brewValidator
.
addValidator
(
new
Validator
(
'ideviceinstaller'
,
description:
'discover connected iOS devices'
,
resolution:
"Install via 'brew install ideviceinstaller'"
,
validatorFunction:
ideviceinstallerExists
if
(!
exitsHappy
(<
String
>[
'ideviceinstaller'
,
'-h'
]))
{
messages
.
add
(
new
ValidationMessage
.
error
(
'ideviceinstaller not available; this is used to discover connected iOS devices.
\n
'
'Install via
\'
brew install ideviceinstaller
\'
.'
));
}
else
{
installed
.
add
(
'ideviceinstaller'
);
}
brewValidator
.
addValidator
(
new
Validator
(
'ios-deploy'
,
description:
'deploy to connected iOS devices'
,
resolution:
"Install via 'brew install ios-deploy'"
,
validatorFunction:
iosdeployExists
if
(!
hasIDeviceId
)
{
messages
.
add
(
new
ValidationMessage
.
error
(
'ios-deploy not available; this is used to deploy to connected iOS devices.
\n
'
'Install via
\'
brew install ios-deploy
\'
.'
));
return
iosValidator
.
validate
(
);
}
else
{
installed
.
add
(
'ios-deploy'
);
}
@override
void
diagnose
()
=>
validate
().
print
();
bool
get
hasIdeviceId
=>
exitsHappy
(<
String
>[
'idevice_id'
,
'-h'
]);
if
(
installed
.
isNotEmpty
)
messages
.
add
(
new
ValidationMessage
(
installed
.
join
(
', '
)
+
' installed'
));
}
else
{
messages
.
add
(
new
ValidationMessage
.
error
(
'Brew not installed; use this to install tools for iOS device development.
\n
'
'Download brew at http://brew.sh/.'
));
}
/// Return whether the tooling to list and deploy to real iOS devices (not the
/// simulator) is installed on the user's machine.
bool
get
canWorkWithIOSDevices
{
return
exitsHappy
(<
String
>[
'ideviceinstaller'
,
'-h'
])
&&
hasIdeviceId
;
return
new
ValidationResult
(
installCount
==
2
?
ValidationType
.
installed
:
installCount
==
1
?
ValidationType
.
partial
:
ValidationType
.
missing
,
messages
,
statusInfo:
xcodeVersionInfo
);
}
}
packages/flutter_tools/lib/src/ios/mac.dart
View file @
25f332d8
...
...
@@ -54,27 +54,24 @@ class XCode {
}
}
bool
_xcodeVersionSatisfactory
;
bool
get
xcodeVersionSatisfactory
{
if
(
_xcodeVersionSatisfactory
!=
null
)
return
_xcodeVersionSatisfactory
;
String
_xcodeVersionText
;
try
{
String
output
=
runSync
(<
String
>[
'xcodebuild'
,
'-version'
]);
String
get
xcodeVersionText
{
if
(
_xcodeVersionText
==
null
)
_xcodeVersionText
=
runSync
(<
String
>[
'xcodebuild'
,
'-version'
]).
replaceAll
(
'
\n
'
,
', '
);
return
_xcodeVersionText
;
}
bool
get
xcodeVersionSatisfactory
{
RegExp
regex
=
new
RegExp
(
r'Xcode ([0-9.]+)'
);
String
version
=
regex
.
firstMatch
(
outpu
t
).
group
(
1
);
String
version
=
regex
.
firstMatch
(
xcodeVersionTex
t
).
group
(
1
);
List
<
String
>
components
=
version
.
split
(
'.'
);
int
major
=
int
.
parse
(
components
[
0
]);
int
minor
=
components
.
length
==
1
?
0
:
int
.
parse
(
components
[
1
]);
_xcodeVersionSatisfactory
=
_xcodeVersionCheckValid
(
major
,
minor
);
}
catch
(
error
)
{
_xcodeVersionSatisfactory
=
false
;
}
return
_xcodeVersionSatisfactory
;
return
_xcodeVersionCheckValid
(
major
,
minor
);
}
}
...
...
packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
View file @
25f332d8
...
...
@@ -200,16 +200,8 @@ class FlutterCommandRunner extends CommandRunner {
}
}
if
(
androidSdk
!=
null
)
{
printTrace
(
'Using Android SDK at
${androidSdk.directory}
.'
);
if
(
androidSdk
.
latestVersion
!=
null
)
printTrace
(
'
${androidSdk.latestVersion}
'
);
}
if
(
globalResults
[
'version'
])
{
printStatus
(
getVersion
(
ArtifactStore
.
flutterRoot
));
printStatus
(
''
);
doctor
.
summary
();
printStatus
(
FlutterVersion
.
getVersion
(
ArtifactStore
.
flutterRoot
).
toString
());
return
new
Future
<
int
>.
value
(
0
);
}
...
...
packages/flutter_tools/lib/src/runner/version.dart
View file @
25f332d8
...
...
@@ -5,26 +5,54 @@
import
'../artifacts.dart'
;
import
'../base/process.dart'
;
String
getVersion
(
String
flutterRoot
)
{
String
upstream
=
runSync
([
'git'
,
'rev-parse'
,
'--abbrev-ref'
,
'--symbolic'
,
'@{u}'
],
workingDirectory:
flutterRoot
).
trim
();
String
repository
;
int
slash
=
upstream
.
indexOf
(
'/'
);
class
FlutterVersion
{
FlutterVersion
(
this
.
flutterRoot
)
{
_channel
=
_runGit
(
'git rev-parse --abbrev-ref --symbolic @{u}'
);
int
slash
=
_channel
.
indexOf
(
'/'
);
if
(
slash
!=
-
1
)
{
String
remote
=
upstream
.
substring
(
0
,
slash
);
repository
=
runSync
([
'git'
,
'ls-remote'
,
'--get-url'
,
remote
],
workingDirectory:
flutterRoot
).
trim
();
upstream
=
upstream
.
substring
(
slash
+
1
);
String
remote
=
_channel
.
substring
(
0
,
slash
);
_repositoryUrl
=
_runGit
(
'git ls-remote --get-url
$remote
'
);
_channel
=
_channel
.
substring
(
slash
+
1
);
}
else
if
(
_channel
.
isEmpty
)
{
_channel
=
'unknown'
;
}
_frameworkRevision
=
_runGit
(
'git log -n 1 --pretty=format:%H'
);
_frameworkAge
=
_runGit
(
'git log -n 1 --pretty=format:%ar'
);
}
String
revision
=
runSync
([
'git'
,
'log'
,
'-n'
,
'1'
,
'--pretty=format:%H (%ar)'
],
workingDirectory:
flutterRoot
).
trim
();
String
from
=
repository
==
null
?
'Flutter from unknown source'
:
'Flutter from
$repository
(on
$upstream
)'
;
String
flutterVersion
=
'Framework:
$revision
'
;
String
engineRevision
=
'Engine:
${ArtifactStore.engineRevision}
'
;
final
String
flutterRoot
;
String
_repositoryUrl
;
String
get
repositoryUrl
=>
_repositoryUrl
;
String
_channel
;
/// `master`, `alpha`, `hackathon`, ...
String
get
channel
=>
_channel
;
String
_frameworkRevision
;
String
get
frameworkRevision
=>
_frameworkRevision
;
String
get
frameworkRevisionShort
=>
_runGit
(
'git rev-parse --short
$frameworkRevision
'
);
String
_frameworkAge
;
String
get
frameworkAge
=>
_frameworkAge
;
return
'
$from
\n
$flutterVersion
\n
$engineRevision
'
;
String
get
engineRevision
=>
ArtifactStore
.
engineRevision
;
String
get
engineRevisionShort
=>
_runGit
(
'git rev-parse --short
$engineRevision
'
);
String
_runGit
(
String
command
)
=>
runSync
(
command
.
split
(
' '
),
workingDirectory:
flutterRoot
);
@override
String
toString
()
{
String
from
=
repositoryUrl
==
null
?
'Flutter from unknown source'
:
'Flutter from
$repositoryUrl
(on channel
$channel
)'
;
String
flutterText
=
'Framework:
$frameworkRevisionShort
(
$frameworkAge
)'
;
String
engineText
=
'Engine:
$engineRevisionShort
'
;
return
'
$from
\n\n
$flutterText
\n
$engineText
'
;
}
static
FlutterVersion
getVersion
([
String
flutterRoot
])
{
return
new
FlutterVersion
(
flutterRoot
!=
null
?
flutterRoot
:
ArtifactStore
.
flutterRoot
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment