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
0f929f9f
Unverified
Commit
0f929f9f
authored
May 22, 2021
by
Jonah Williams
Committed by
GitHub
May 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] require cmdline-tools for android licenses (#82560)
parent
c99f60b8
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
108 additions
and
57 deletions
+108
-57
android_sdk.dart
packages/flutter_tools/lib/src/android/android_sdk.dart
+20
-16
android_workflow.dart
packages/flutter_tools/lib/src/android/android_workflow.dart
+17
-7
android_sdk_test.dart
...er_tools/test/general.shard/android/android_sdk_test.dart
+35
-29
android_workflow_test.dart
...ols/test/general.shard/android/android_workflow_test.dart
+36
-5
No files found.
packages/flutter_tools/lib/src/android/android_sdk.dart
View file @
0f929f9f
...
...
@@ -47,13 +47,19 @@ class AndroidSdk {
List
<
AndroidSdkVersion
>
_sdkVersions
=
<
AndroidSdkVersion
>[];
AndroidSdkVersion
?
_latestVersion
;
/// Whether the `cmdline-tools` directory exists in the Android SDK.
///
/// This is required to use the newest SDK manager which only works with
/// the newer JDK.
bool
get
cmdlineToolsAvailable
=>
directory
.
childDirectory
(
'cmdline-tools'
).
existsSync
();
/// Whether the `platform-tools` or `cmdline-tools` directory exists in the Android SDK.
///
/// It is possible to have an Android SDK folder that is missing this with
/// the expectation that it will be downloaded later, e.g. by gradle or the
/// sdkmanager. The [licensesAvailable] property should be used to determine
/// whether the licenses are at least possibly accepted.
bool
get
platformToolsAvailable
=>
directory
.
childDirectory
(
'cmdline-tools'
).
existsSync
()
bool
get
platformToolsAvailable
=>
cmdlineToolsAvailable
||
directory
.
childDirectory
(
'platform-tools'
).
existsSync
();
/// Whether the `licenses` directory exists in the Android SDK.
...
...
@@ -262,7 +268,7 @@ class AndroidSdk {
return
null
;
}
String
?
getCmdlineToolsPath
(
String
binaryName
)
{
String
?
getCmdlineToolsPath
(
String
binaryName
,
{
bool
skipOldTools
=
false
}
)
{
// First look for the latest version of the command-line tools
final
File
cmdlineToolsLatestBinary
=
directory
.
childDirectory
(
'cmdline-tools'
)
...
...
@@ -301,6 +307,9 @@ class AndroidSdk {
}
}
}
if
(
skipOldTools
)
{
return
null
;
}
// Finally fallback to the old SDK tools
final
File
toolsBinary
=
directory
.
childDirectory
(
'tools'
).
childDirectory
(
'bin'
).
childFile
(
binaryName
);
...
...
@@ -386,23 +395,15 @@ class AndroidSdk {
}
/// Returns the filesystem path of the Android SDK manager tool.
///
/// The sdkmanager was previously in the tools directory but this component
/// was marked as obsolete in 3.6.
String
get
sdkManagerPath
{
String
?
get
sdkManagerPath
{
final
String
executable
=
globals
.
platform
.
isWindows
?
'sdkmanager.bat'
:
'sdkmanager'
;
final
String
?
path
=
getCmdlineToolsPath
(
executable
);
final
String
?
path
=
getCmdlineToolsPath
(
executable
,
skipOldTools:
true
);
if
(
path
!=
null
)
{
return
path
;
}
// If no binary was found, return the default location
return
directory
.
childDirectory
(
'tools'
)
.
childDirectory
(
'bin'
)
.
childFile
(
executable
)
.
path
;
return
null
;
}
/// First try Java bundled with Android Studio, then sniff JAVA_HOME, then fallback to PATH.
...
...
@@ -468,11 +469,14 @@ class AndroidSdk {
/// Returns the version of the Android SDK manager tool or null if not found.
String
?
get
sdkManagerVersion
{
if
(!
globals
.
processManager
.
canRun
(
sdkManagerPath
))
{
throwToolExit
(
'Android sdkmanager not found. Update to the latest Android SDK to resolve this.'
);
if
(
sdkManagerPath
==
null
||
!
globals
.
processManager
.
canRun
(
sdkManagerPath
))
{
throwToolExit
(
'Android sdkmanager not found. Update to the latest Android SDK and ensure that '
'the cmdline-tools are installed to resolve this.'
);
}
final
RunResult
result
=
globals
.
processUtils
.
runSync
(
<
String
>[
sdkManagerPath
,
'--version'
],
<
String
>[
sdkManagerPath
!
,
'--version'
],
environment:
sdkManagerEnv
,
);
if
(
result
.
exitCode
!=
0
)
{
...
...
packages/flutter_tools/lib/src/android/android_workflow.dart
View file @
0f929f9f
...
...
@@ -185,6 +185,10 @@ class AndroidValidator extends DoctorValidator {
}
return
ValidationResult
(
ValidationType
.
missing
,
messages
);
}
if
(!
androidSdk
.
cmdlineToolsAvailable
)
{
messages
.
add
(
const
ValidationMessage
.
error
(
'cmdline-tools component is missing'
));
return
ValidationResult
(
ValidationType
.
missing
,
messages
);
}
if
(
androidSdk
.
licensesAvailable
&&
!
androidSdk
.
platformToolsAvailable
)
{
messages
.
add
(
ValidationMessage
.
hint
(
_userMessages
.
androidSdkLicenseOnly
(
kAndroidHome
)));
...
...
@@ -199,7 +203,7 @@ class AndroidValidator extends DoctorValidator {
if
(
androidSdkLatestVersion
.
sdkLevel
<
kAndroidSdkMinVersion
||
androidSdkLatestVersion
.
buildToolsVersion
<
kAndroidSdkBuildToolsMinVersion
)
{
messages
.
add
(
ValidationMessage
.
error
(
_userMessages
.
androidSdkBuildToolsOutdated
(
_androidSdk
!.
sdkManagerPath
,
_androidSdk
!.
sdkManagerPath
!
,
kAndroidSdkMinVersion
,
kAndroidSdkBuildToolsMinVersion
.
toString
(),
_platform
,
...
...
@@ -250,7 +254,7 @@ class AndroidValidator extends DoctorValidator {
messages
.
add
(
ValidationMessage
(
_userMessages
.
androidJdkLocation
(
javaBinary
)));
// Check JDK version.
if
(!
await
_checkJavaVersion
(
javaBinary
,
messages
))
{
if
(!
await
_checkJavaVersion
(
javaBinary
,
messages
))
{
return
ValidationResult
(
ValidationType
.
partial
,
messages
,
statusInfo:
sdkVersionText
);
}
...
...
@@ -384,7 +388,7 @@ class AndroidLicenseValidator extends DoctorValidator {
try
{
final
Process
process
=
await
_processManager
.
start
(
<
String
>[
_androidSdk
.
sdkManagerPath
,
'--licenses'
],
<
String
>[
_androidSdk
.
sdkManagerPath
!
,
'--licenses'
],
environment:
_androidSdk
.
sdkManagerEnv
,
);
process
.
stdin
.
write
(
'n
\n
'
);
...
...
@@ -416,12 +420,15 @@ class AndroidLicenseValidator extends DoctorValidator {
}
if
(!
_canRunSdkManager
())
{
throwToolExit
(
_userMessages
.
androidMissingSdkManager
(
_androidSdk
.
sdkManagerPath
,
_platform
));
throwToolExit
(
'Android sdkmanager not found. Update to the latest Android SDK and ensure that '
'the cmdline-tools are installed to resolve this.'
);
}
try
{
final
Process
process
=
await
_processManager
.
start
(
<
String
>[
_androidSdk
.
sdkManagerPath
,
'--licenses'
],
<
String
>[
_androidSdk
.
sdkManagerPath
!
,
'--licenses'
],
environment:
_androidSdk
.
sdkManagerEnv
,
);
...
...
@@ -452,7 +459,7 @@ class AndroidLicenseValidator extends DoctorValidator {
return
exitCode
==
0
;
}
on
ProcessException
catch
(
e
)
{
throwToolExit
(
_userMessages
.
androidCannotRunSdkManager
(
_androidSdk
.
sdkManagerPath
,
_androidSdk
.
sdkManagerPath
!
,
e
.
toString
(),
_platform
,
));
...
...
@@ -460,7 +467,10 @@ class AndroidLicenseValidator extends DoctorValidator {
}
bool
_canRunSdkManager
()
{
final
String
sdkManagerPath
=
_androidSdk
.
sdkManagerPath
;
final
String
?
sdkManagerPath
=
_androidSdk
.
sdkManagerPath
;
if
(
sdkManagerPath
==
null
)
{
return
false
;
}
return
_processManager
.
canRun
(
sdkManagerPath
);
}
}
packages/flutter_tools/test/general.shard/android/android_sdk_test.dart
View file @
0f929f9f
...
...
@@ -80,7 +80,7 @@ void main() {
});
testUsingContext
(
'returns sdkmanager path under cmdline tools (highest version) on Linux/macOS'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
);
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
,
withSdkManager:
false
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
...
...
@@ -99,71 +99,77 @@ void main() {
Config:
()
=>
config
,
});
testUsingContext
(
'
Caches adb location after first access
'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
);
testUsingContext
(
'
Does not return sdkmanager under deprecated tools component
'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
,
withSdkManager:
false
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
final
File
adbFile
=
fileSystem
.
file
(
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
)
)..
createSync
(
recursive:
true
);
expect
(
sdk
.
adbPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
));
adbFile
.
deleteSync
(
recursive:
true
);
fileSystem
.
file
(
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'tools/bin/sdkmanager'
)
).
createSync
(
recursive:
true
);
expect
(
sdk
.
adbPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
)
);
expect
(
sdk
.
sdkManagerPath
,
null
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'
windows
'
),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'
linux
'
),
Config:
()
=>
config
,
});
testUsingContext
(
'
returns sdkmanager.bat path under cmdline tools for windows
'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
);
testUsingContext
(
'
Can look up cmdline tool from deprecated tools path
'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
,
withSdkManager:
false
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
fileSystem
.
file
(
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'
cmdline-tools'
,
'latest'
,
'bin'
,
'sdkmanager.bat
'
)
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'
tools/bin/foo
'
)
).
createSync
(
recursive:
true
);
expect
(
sdk
.
sdkManagerPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'latest'
,
'bin'
,
'sdkmanager.bat'
));
expect
(
sdk
.
getCmdlineToolsPath
(
'foo'
,
skipOldTools:
false
),
'/.tmp_rand0/flutter_mock_android_sdk.rand0/tools/bin/foo'
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'
windows
'
),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'
linux
'
),
Config:
()
=>
config
,
});
testUsingContext
(
"returns sdkmanager path under tools if cmdline doesn't exist"
,
()
{
testUsingContext
(
'Caches adb location after first access'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
final
File
adbFile
=
fileSystem
.
file
(
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
)
)..
createSync
(
recursive:
true
);
expect
(
sdk
.
sdkManagerPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'tools'
,
'bin'
,
'sdkmanager'
));
expect
(
sdk
.
adbPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
));
adbFile
.
deleteSync
(
recursive:
true
);
expect
(
sdk
.
adbPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'adb.exe'
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'windows'
),
Config:
()
=>
config
,
Platform:
()
=>
FakePlatform
(
operatingSystem:
'linux'
),
});
testUsingContext
(
"returns sdkmanager path under tools if cmdline doesn't exist on windows"
,
()
{
testUsingContext
(
'returns sdkmanager.bat path under cmdline tools for windows'
,
()
{
sdkDir
=
createSdkDirectory
(
fileSystem:
fileSystem
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
fileSystem
.
file
(
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'latest'
,
'bin'
,
'sdkmanager.bat'
)
).
createSync
(
recursive:
true
);
expect
(
sdk
.
sdkManagerPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'tools'
,
'bin'
,
'sdkmanager.bat'
));
expect
(
sdk
.
sdkManagerPath
,
fileSystem
.
path
.
join
(
sdk
.
directory
.
path
,
'cmdline-tools'
,
'latest'
,
'bin'
,
'sdkmanager.bat'
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Config:
()
=>
config
,
Platform:
()
=>
FakePlatform
(
operatingSystem:
'windows'
),
Config:
()
=>
config
,
});
testUsingContext
(
'returns sdkmanager version'
,
()
{
...
...
@@ -172,7 +178,7 @@ void main() {
processManager
.
addCommand
(
const
FakeCommand
(
command:
<
String
>[
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
tools
/bin/sdkmanager'
,
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
cmdline-tools/latest
/bin/sdkmanager'
,
'--version'
,
],
stdout:
'26.1.1
\n
'
,
...
...
@@ -193,7 +199,7 @@ void main() {
fileSystem:
fileSystem
,
);
processManager
.
addCommand
(
const
FakeCommand
(
command:
<
String
>[
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
tools
/bin/sdkmanager'
,
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
cmdline-tools/latest
/bin/sdkmanager'
,
'--version'
,
]));
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
...
...
@@ -217,7 +223,7 @@ void main() {
processManager
.
addCommand
(
const
FakeCommand
(
command:
<
String
>[
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
tools
/bin/sdkmanager'
,
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
cmdline-tools/latest
/bin/sdkmanager'
,
'--version'
,
],
stdout:
'
\n
'
,
...
...
@@ -239,7 +245,7 @@ void main() {
testUsingContext
(
'throws on sdkmanager version check if sdkmanager not found'
,
()
{
sdkDir
=
createSdkDirectory
(
withSdkManager:
false
,
fileSystem:
fileSystem
);
config
.
setValue
(
'android-sdk'
,
sdkDir
.
path
);
processManager
.
excludedExecutables
.
add
(
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
tools
/bin/sdkmanager'
);
processManager
.
excludedExecutables
.
add
(
'/.tmp_rand0/flutter_mock_android_sdk.rand0/
cmdline-tools/latest
/bin/sdkmanager'
);
final
AndroidSdk
sdk
=
AndroidSdk
.
locateAndroidSdk
();
expect
(()
=>
sdk
.
sdkManagerVersion
,
throwsToolExit
());
...
...
@@ -387,7 +393,7 @@ Directory createSdkDirectory({
}
if
(
withSdkManager
)
{
_createSdkFile
(
dir
,
'
tools
/bin/sdkmanager
$bat
'
);
_createSdkFile
(
dir
,
'
cmdline-tools/latest
/bin/sdkmanager
$bat
'
);
}
return
dir
;
}
...
...
packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
View file @
0f929f9f
...
...
@@ -289,9 +289,11 @@ Review licenses that have not been accepted (y/N)?
expect
(
licenseValidator
.
runLicenseManager
(),
throwsToolExit
());
});
testWithoutContext
(
'detects license-only SDK installation'
,
()
async
{
sdk
.
licensesAvailable
=
true
;
sdk
.
platformToolsAvailable
=
false
;
testWithoutContext
(
'detects license-only SDK installation with cmdline-tools'
,
()
async
{
sdk
..
licensesAvailable
=
true
..
platformToolsAvailable
=
false
..
cmdlineToolsAvailable
=
true
;
final
ValidationResult
validationResult
=
await
AndroidValidator
(
androidStudio:
null
,
androidSdk:
sdk
,
...
...
@@ -304,8 +306,8 @@ Review licenses that have not been accepted (y/N)?
expect
(
validationResult
.
type
,
ValidationType
.
partial
);
expect
(
validationResult
.
messages
.
last
.
message
,
UserMessages
().
androidSdkLicenseOnly
(
kAndroidHome
),
validationResult
.
messages
.
map
((
ValidationMessage
message
)
=>
message
.
message
)
,
contains
(
contains
(
UserMessages
().
androidSdkLicenseOnly
(
kAndroidHome
))
),
);
});
...
...
@@ -323,6 +325,7 @@ Review licenses that have not been accepted (y/N)?
sdk
..
licensesAvailable
=
true
..
platformToolsAvailable
=
true
..
cmdlineToolsAvailable
=
true
// Test with invalid SDK and build tools
..
directory
=
fileSystem
.
directory
(
'/foo/bar'
)
..
sdkManagerPath
=
'/foo/bar/sdkmanager'
...
...
@@ -376,6 +379,30 @@ Review licenses that have not been accepted (y/N)?
);
});
testWithoutContext
(
'detects missing cmdline tools'
,
()
async
{
sdk
..
licensesAvailable
=
true
..
platformToolsAvailable
=
true
..
cmdlineToolsAvailable
=
false
;
final
AndroidValidator
androidValidator
=
AndroidValidator
(
androidStudio:
null
,
androidSdk:
sdk
,
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
platform:
FakePlatform
()..
environment
=
<
String
,
String
>{
'HOME'
:
'/home/me'
},
userMessages:
UserMessages
(),
);
final
ValidationResult
validationResult
=
await
androidValidator
.
validate
();
expect
(
validationResult
.
type
,
ValidationType
.
missing
);
expect
(
validationResult
.
messages
.
last
.
message
,
'cmdline-tools component is missing'
,
);
});
testWithoutContext
(
'detects minimum required java version'
,
()
async
{
// Test with older version of JDK
const
String
javaVersionText
=
'openjdk version "1.7.0_212"'
;
...
...
@@ -393,6 +420,7 @@ Review licenses that have not been accepted (y/N)?
sdk
..
licensesAvailable
=
true
..
platformToolsAvailable
=
true
..
cmdlineToolsAvailable
=
true
..
directory
=
fileSystem
.
directory
(
'/foo/bar'
)
..
sdkManagerPath
=
'/foo/bar/sdkmanager'
;
sdk
.
latestVersion
=
sdkVersion
;
...
...
@@ -457,6 +485,9 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {
@override
bool
platformToolsAvailable
;
@override
bool
cmdlineToolsAvailable
;
@override
Directory
directory
;
...
...
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