Unverified Commit 9dbd6e61 authored by Andrew Kolos's avatar Andrew Kolos Committed by GitHub

[tools] Apply Android Studio version detection logic to explicitly configured...

[tools] Apply Android Studio version detection logic to explicitly configured installation directory (`flutter config --android-studio-dir`) (#125596)

Fixes #121468 (when considered along with https://github.com/flutter/flutter/pull/125247).

This applies the pre-existing Android Studio version detection logic to the install configured with `flutter config android-studio-dir`.
parent 4b74232a
...@@ -52,7 +52,10 @@ class AndroidStudio { ...@@ -52,7 +52,10 @@ class AndroidStudio {
_initAndValidate(); _initAndValidate();
} }
static AndroidStudio? fromMacOSBundle(String bundlePath) { static AndroidStudio? fromMacOSBundle(
String bundlePath, {
String? configuredPath,
}) {
final String studioPath = globals.fs.path.join(bundlePath, 'Contents'); final String studioPath = globals.fs.path.join(bundlePath, 'Contents');
final String plistFile = globals.fs.path.join(studioPath, 'Info.plist'); final String plistFile = globals.fs.path.join(studioPath, 'Info.plist');
final Map<String, dynamic> plistValues = globals.plistParser.parseFile(plistFile); final Map<String, dynamic> plistValues = globals.plistParser.parseFile(plistFile);
...@@ -99,7 +102,12 @@ class AndroidStudio { ...@@ -99,7 +102,12 @@ class AndroidStudio {
); );
} }
} }
return AndroidStudio(studioPath, version: version, presetPluginsPath: presetPluginsPath); return AndroidStudio(
studioPath,
version: version,
presetPluginsPath: presetPluginsPath,
configuredPath: configuredPath,
);
} }
static AndroidStudio? fromHomeDot(Directory homeDotDir) { static AndroidStudio? fromHomeDot(Directory homeDotDir) {
...@@ -238,13 +246,7 @@ class AndroidStudio { ...@@ -238,13 +246,7 @@ class AndroidStudio {
/// invalid. /// invalid.
static AndroidStudio? latestValid() { static AndroidStudio? latestValid() {
final String? configuredStudioPath = globals.config.getValue('android-studio-dir') as String?; final String? configuredStudioPath = globals.config.getValue('android-studio-dir') as String?;
if (configuredStudioPath != null) { if (configuredStudioPath != null && !globals.fs.directory(configuredStudioPath).existsSync()) {
String correctedConfiguredStudioPath = configuredStudioPath;
if (globals.platform.isMacOS && !correctedConfiguredStudioPath.endsWith('Contents')) {
correctedConfiguredStudioPath = globals.fs.path.join(correctedConfiguredStudioPath, 'Contents');
}
if (!globals.fs.directory(correctedConfiguredStudioPath).existsSync()) {
throwToolExit(''' throwToolExit('''
Could not find the Android Studio installation at the manually configured path "$configuredStudioPath". Could not find the Android Studio installation at the manually configured path "$configuredStudioPath".
Please verify that the path is correct and update it by running this command: flutter config --android-studio-dir '<path>' Please verify that the path is correct and update it by running this command: flutter config --android-studio-dir '<path>'
...@@ -254,15 +256,22 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -254,15 +256,22 @@ the configured path by running this command: flutter config --android-studio-dir
'''); ''');
} }
return AndroidStudio(correctedConfiguredStudioPath,
configuredPath: configuredStudioPath);
}
// Find all available Studio installations. // Find all available Studio installations.
final List<AndroidStudio> studios = allInstalled(); final List<AndroidStudio> studios = allInstalled();
if (studios.isEmpty) { if (studios.isEmpty) {
return null; return null;
} }
final AndroidStudio? manuallyConfigured = studios
.where((AndroidStudio studio) => studio.configuredPath != null &&
configuredStudioPath != null &&
_pathsAreEqual(studio.configuredPath!, configuredStudioPath))
.firstOrNull;
if (manuallyConfigured != null) {
return manuallyConfigured;
}
AndroidStudio? newest; AndroidStudio? newest;
for (final AndroidStudio studio in studios.where((AndroidStudio s) => s.isValid)) { for (final AndroidStudio studio in studios.where((AndroidStudio s) => s.isValid)) {
if (newest == null) { if (newest == null) {
...@@ -324,14 +333,15 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -324,14 +333,15 @@ the configured path by running this command: flutter config --android-studio-dir
} }
final String? configuredStudioDir = globals.config.getValue('android-studio-dir') as String?; final String? configuredStudioDir = globals.config.getValue('android-studio-dir') as String?;
FileSystemEntity? configuredStudioDirAsEntity;
if (configuredStudioDir != null) { if (configuredStudioDir != null) {
FileSystemEntity configuredStudio = globals.fs.file(configuredStudioDir); configuredStudioDirAsEntity = globals.fs.directory(configuredStudioDir);
if (configuredStudio.basename == 'Contents') { if (configuredStudioDirAsEntity.basename == 'Contents') {
configuredStudio = configuredStudio.parent; configuredStudioDirAsEntity = configuredStudioDirAsEntity.parent;
} }
if (!candidatePaths if (!candidatePaths
.any((FileSystemEntity e) => e.path == configuredStudio.path)) { .any((FileSystemEntity e) => _pathsAreEqual(e.path, configuredStudioDirAsEntity!.path))) {
candidatePaths.add(configuredStudio); candidatePaths.add(configuredStudioDirAsEntity);
} }
} }
...@@ -355,7 +365,16 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -355,7 +365,16 @@ the configured path by running this command: flutter config --android-studio-dir
} }
return candidatePaths return candidatePaths
.map<AndroidStudio?>((FileSystemEntity e) => AndroidStudio.fromMacOSBundle(e.path)) .map<AndroidStudio?>((FileSystemEntity e) {
if (configuredStudioDirAsEntity == null) {
return AndroidStudio.fromMacOSBundle(e.path);
}
return AndroidStudio.fromMacOSBundle(
e.path,
configuredPath: _pathsAreEqual(configuredStudioDirAsEntity.path, e.path) ? configuredStudioDir : null,
);
})
.whereType<AndroidStudio>() .whereType<AndroidStudio>()
.toList(); .toList();
} }
...@@ -440,7 +459,7 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -440,7 +459,7 @@ the configured path by running this command: flutter config --android-studio-dir
studioAppName: title, studioAppName: title,
); );
if (!alreadyFoundStudioAt(studio.directory, newerThan: studio.version)) { if (!alreadyFoundStudioAt(studio.directory, newerThan: studio.version)) {
studios.removeWhere((AndroidStudio other) => other.directory == studio.directory); studios.removeWhere((AndroidStudio other) => _pathsAreEqual(other.directory, studio.directory));
studios.add(studio); studios.add(studio);
} }
} }
...@@ -450,10 +469,24 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -450,10 +469,24 @@ the configured path by running this command: flutter config --android-studio-dir
} }
final String? configuredStudioDir = globals.config.getValue('android-studio-dir') as String?; final String? configuredStudioDir = globals.config.getValue('android-studio-dir') as String?;
if (configuredStudioDir != null && !alreadyFoundStudioAt(configuredStudioDir)) { if (configuredStudioDir != null) {
final AndroidStudio? matchingAlreadyFoundInstall = studios
.where((AndroidStudio other) => _pathsAreEqual(configuredStudioDir, other.directory))
.firstOrNull;
if (matchingAlreadyFoundInstall != null) {
studios.remove(matchingAlreadyFoundInstall);
studios.add(
AndroidStudio(
configuredStudioDir,
configuredPath: configuredStudioDir,
version: matchingAlreadyFoundInstall.version,
),
);
} else {
studios.add(AndroidStudio(configuredStudioDir, studios.add(AndroidStudio(configuredStudioDir,
configuredPath: configuredStudioDir)); configuredPath: configuredStudioDir));
} }
}
if (globals.platform.isLinux) { if (globals.platform.isLinux) {
void checkWellKnownPath(String path) { void checkWellKnownPath(String path) {
...@@ -528,3 +561,7 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -528,3 +561,7 @@ the configured path by running this command: flutter config --android-studio-dir
@override @override
String toString() => 'Android Studio ($version)'; String toString() => 'Android Studio ($version)';
} }
bool _pathsAreEqual(String path, String other) {
return globals.fs.path.canonicalize(path) == globals.fs.path.canonicalize(other);
}
...@@ -86,6 +86,7 @@ void main() { ...@@ -86,6 +86,7 @@ void main() {
}, },
}; };
late Config config;
late FileSystem fileSystem; late FileSystem fileSystem;
late FileSystemUtils fsUtils; late FileSystemUtils fsUtils;
late Platform platform; late Platform platform;
...@@ -93,6 +94,7 @@ void main() { ...@@ -93,6 +94,7 @@ void main() {
late FakeProcessManager processManager; late FakeProcessManager processManager;
setUp(() { setUp(() {
config = Config.test();
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
plistUtils = FakePlistUtils(); plistUtils = FakePlistUtils();
platform = FakePlatform( platform = FakePlatform(
...@@ -590,14 +592,6 @@ void main() { ...@@ -590,14 +592,6 @@ void main() {
final String jdkPathFor2022 = fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home'); final String jdkPathFor2022 = fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home');
processManager.addCommand(FakeCommand(
command: <String>[
fileSystem.path.join(jdkPathFor2022, 'bin', 'java'),
'-version',
],
stderr: '123',
)
);
final AndroidStudio studio = AndroidStudio.fromMacOSBundle( final AndroidStudio studio = AndroidStudio.fromMacOSBundle(
fileSystem.directory(studioInApplicationPlistFolder).parent.path, fileSystem.directory(studioInApplicationPlistFolder).parent.path,
)!; )!;
...@@ -607,18 +601,70 @@ void main() { ...@@ -607,18 +601,70 @@ void main() {
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
FileSystemUtils: () => fsUtils, FileSystemUtils: () => fsUtils,
ProcessManager: () => processManager, ProcessManager: () => FakeProcessManager.any(),
Platform: () => platform, Platform: () => platform,
PlistParser: () => plistUtils, PlistParser: () => plistUtils,
}); });
testUsingContext('discovers explicitly configured Android Studio', () {
final String extractedDownloadZip = fileSystem.path.join(
'/',
'Users',
'Dash',
'Desktop',
'android-studio'
);
config.setValue('android-studio-dir', extractedDownloadZip);
final String studioInApplicationPlistFolder = fileSystem.path.join(
extractedDownloadZip,
'Contents',
);
fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true);
final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist');
plistUtils.fileContents[plistFilePath] = macStudioInfoPlist2022_1;
final String studioInApplicationJavaBinary = fileSystem.path.join(
extractedDownloadZip,
'Contents', 'jbr', 'Contents', 'Home', 'bin', 'java',
);
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: const <String>[
'mdfind',
'kMDItemCFBundleIdentifier="com.google.android.studio*"',
],
stdout: extractedDownloadZip,
),
FakeCommand(
command: <String>[
studioInApplicationJavaBinary,
'-version',
],
),
]);
final AndroidStudio studio = AndroidStudio.allInstalled().single;
expect(studio.configuredPath, extractedDownloadZip);
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
Config:() => config,
FileSystem: () => fileSystem,
FileSystemUtils: () => fsUtils,
ProcessManager: () => processManager,
Platform: () => platform,
PlistParser: () => plistUtils,
});
}); });
group('installation detection on Windows', () { group('installation detection on Windows', () {
late Config config;
late Platform platform; late Platform platform;
late FileSystem fileSystem; late FileSystem fileSystem;
setUp(() { setUp(() {
config = Config.test();
platform = FakePlatform( platform = FakePlatform(
operatingSystem: 'windows', operatingSystem: 'windows',
environment: <String, String>{ environment: <String, String>{
...@@ -800,6 +846,27 @@ void main() { ...@@ -800,6 +846,27 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('discovers explicitly configured Android Studio', () {
const String androidStudioDir = r'C:\Users\Dash\Desktop\android-studio';
config.setValue('android-studio-dir', androidStudioDir);
fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2022.1\.home')
..createSync(recursive: true)
..writeAsStringSync(androidStudioDir);
fileSystem.directory(androidStudioDir)
.createSync(recursive: true);
final AndroidStudio studio = AndroidStudio.allInstalled().single;
expect(studio.version, equals(Version(2022, 1, null)));
expect(studio.configuredPath, androidStudioDir);
expect(studio.javaPath, fileSystem.path.join(androidStudioDir, 'jbr'));
}, overrides: <Type, Generator>{
Config: () => config,
Platform: () => platform,
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
}); });
group('installation detection on Linux', () { group('installation detection on Linux', () {
...@@ -1015,6 +1082,28 @@ void main() { ...@@ -1015,6 +1082,28 @@ void main() {
platform: platform, platform: platform,
), ),
}); });
testUsingContext('discovers explicitly configured Android Studio', () {
const String androidStudioDir = '/Users/Dash/Desktop/android-studio';
config.setValue('android-studio-dir', androidStudioDir);
const String studioHome = '$homeLinux/.cache/Google/AndroidStudio2022.3/.home';
fileSystem.file(studioHome)
..createSync(recursive: true)
..writeAsStringSync(androidStudioDir);
fileSystem.directory(androidStudioDir)
.createSync(recursive: true);
final AndroidStudio studio = AndroidStudio.allInstalled().single;
expect(studio.version, equals(Version(2022, 3, null)));
expect(studio.configuredPath, androidStudioDir);
expect(studio.javaPath, fileSystem.path.join(androidStudioDir, 'jbr'));
}, overrides: <Type, Generator>{
Config: () => config,
Platform: () => platform,
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
}); });
group('latestValid', () { group('latestValid', () {
...@@ -1162,6 +1251,16 @@ void main() { ...@@ -1162,6 +1251,16 @@ void main() {
} }
expect(AndroidStudio.allInstalled().length, 4); expect(AndroidStudio.allInstalled().length, 4);
for (final String javaPath in validJavaPaths) {
(globals.processManager as FakeProcessManager).addCommand(FakeCommand(
command: <String>[
fileSystem.path.join(javaPath),
'-version',
],
));
}
final AndroidStudio chosenInstall = AndroidStudio.latestValid()!; final AndroidStudio chosenInstall = AndroidStudio.latestValid()!;
expect(chosenInstall.directory, configuredAndroidStudioDir); expect(chosenInstall.directory, configuredAndroidStudioDir);
expect(chosenInstall.isValid, false); expect(chosenInstall.isValid, false);
......
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