Unverified Commit e1967eca authored by Andrew Kolos's avatar Andrew Kolos Committed by GitHub

handle exceptions raised while searching for configured android studio (#133180)

Fixes #133055
parent 12cf9de6
...@@ -236,16 +236,7 @@ class AndroidStudio { ...@@ -236,16 +236,7 @@ class AndroidStudio {
/// Android Studio found at that location is always returned, even if it is /// Android Studio found at that location is always returned, even if it is
/// invalid. /// invalid.
static AndroidStudio? latestValid() { static AndroidStudio? latestValid() {
final String? configuredStudioPath = globals.config.getValue('android-studio-dir') as String?; final Directory? configuredStudioDir = _configuredDir();
if (configuredStudioPath != null && !globals.fs.directory(configuredStudioPath).existsSync()) {
throwToolExit('''
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>'
To have flutter search for Android Studio installations automatically, remove
the configured path by running this command: flutter config --android-studio-dir ''
''');
}
// Find all available Studio installations. // Find all available Studio installations.
final List<AndroidStudio> studios = allInstalled(); final List<AndroidStudio> studios = allInstalled();
...@@ -255,8 +246,8 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -255,8 +246,8 @@ the configured path by running this command: flutter config --android-studio-dir
final AndroidStudio? manuallyConfigured = studios final AndroidStudio? manuallyConfigured = studios
.where((AndroidStudio studio) => studio.configuredPath != null && .where((AndroidStudio studio) => studio.configuredPath != null &&
configuredStudioPath != null && configuredStudioDir != null &&
_pathsAreEqual(studio.configuredPath!, configuredStudioPath)) _pathsAreEqual(studio.configuredPath!, configuredStudioDir.path))
.firstOrNull; .firstOrNull;
if (manuallyConfigured != null) { if (manuallyConfigured != null) {
...@@ -323,16 +314,14 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -323,16 +314,14 @@ the configured path by running this command: flutter config --android-studio-dir
)); ));
} }
final String? configuredStudioDir = globals.config.getValue('android-studio-dir') as String?; Directory? configuredStudioDir = _configuredDir();
FileSystemEntity? configuredStudioDirAsEntity;
if (configuredStudioDir != null) { if (configuredStudioDir != null) {
configuredStudioDirAsEntity = globals.fs.directory(configuredStudioDir); if (configuredStudioDir.basename == 'Contents') {
if (configuredStudioDirAsEntity.basename == 'Contents') { configuredStudioDir = configuredStudioDir.parent;
configuredStudioDirAsEntity = configuredStudioDirAsEntity.parent;
} }
if (!candidatePaths if (!candidatePaths
.any((FileSystemEntity e) => _pathsAreEqual(e.path, configuredStudioDirAsEntity!.path))) { .any((FileSystemEntity e) => _pathsAreEqual(e.path, configuredStudioDir!.path))) {
candidatePaths.add(configuredStudioDirAsEntity); candidatePaths.add(configuredStudioDir);
} }
} }
...@@ -357,13 +346,13 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -357,13 +346,13 @@ the configured path by running this command: flutter config --android-studio-dir
return candidatePaths return candidatePaths
.map<AndroidStudio?>((FileSystemEntity e) { .map<AndroidStudio?>((FileSystemEntity e) {
if (configuredStudioDirAsEntity == null) { if (configuredStudioDir == null) {
return AndroidStudio.fromMacOSBundle(e.path); return AndroidStudio.fromMacOSBundle(e.path);
} }
return AndroidStudio.fromMacOSBundle( return AndroidStudio.fromMacOSBundle(
e.path, e.path,
configuredPath: _pathsAreEqual(configuredStudioDirAsEntity.path, e.path) ? configuredStudioDir : null, configuredPath: _pathsAreEqual(configuredStudioDir.path, e.path) ? configuredStudioDir.path : null,
); );
}) })
.whereType<AndroidStudio>() .whereType<AndroidStudio>()
...@@ -493,6 +482,38 @@ the configured path by running this command: flutter config --android-studio-dir ...@@ -493,6 +482,38 @@ the configured path by running this command: flutter config --android-studio-dir
return studios; return studios;
} }
/// Gets the Android Studio install directory set by the user, if it is configured.
///
/// The returned [Directory], if not null, is guaranteed to have existed during
/// this function's execution.
static Directory? _configuredDir() {
final String? configuredPath = globals.config.getValue('android-studio-dir') as String?;
if (configuredPath == null) {
return null;
}
final Directory result = globals.fs.directory(configuredPath);
bool? configuredStudioPathExists;
String? exceptionMessage;
try {
configuredStudioPathExists = result.existsSync();
} on FileSystemException catch (e) {
exceptionMessage = e.toString();
}
if (configuredStudioPathExists == false || exceptionMessage != null) {
throwToolExit('''
Could not find the Android Studio installation at the manually configured path "$configuredPath".
${exceptionMessage == null ? '' : 'Encountered exception: $exceptionMessage\n\n'}
Please verify that the path is correct and update it by running this command: flutter config --android-studio-dir '<path>'
To have flutter search for Android Studio installations automatically, remove
the configured path by running this command: flutter config --android-studio-dir
''');
}
return result;
}
static String? extractStudioPlistValueWithMatcher(String plistValue, RegExp keyMatcher) { static String? extractStudioPlistValueWithMatcher(String plistValue, RegExp keyMatcher) {
return keyMatcher.stringMatch(plistValue)?.split('=').last.trim().replaceAll('"', ''); return keyMatcher.stringMatch(plistValue)?.split('=').last.trim().replaceAll('"', '');
} }
......
...@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/base/platform.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/version.dart'; import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/ios/plist_parser.dart'; import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:path/path.dart' show Context; // flutter_ignore: package_path_import -- We only use Context as an interface.
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -1287,6 +1288,20 @@ void main() { ...@@ -1287,6 +1288,20 @@ void main() {
Platform: () => platform, Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('handles file system exception when checking for explicitly configured Android Studio install', () {
const String androidStudioDir = '/Users/Dash/Desktop/android-studio';
config.setValue('android-studio-dir', androidStudioDir);
expect(() => AndroidStudio.latestValid(),
throwsToolExit(message: RegExp(r'[.\s\S]*Could not find[.\s\S]*FileSystemException[.\s\S]*')));
}, overrides: <Type, Generator>{
Config: () => config,
Platform: () => platform,
FileSystem: () => _FakeFileSystem(),
FileSystemUtils: () => _FakeFsUtils(),
ProcessManager: () => FakeProcessManager.any(),
});
}); });
} }
...@@ -1298,3 +1313,33 @@ class FakePlistUtils extends Fake implements PlistParser { ...@@ -1298,3 +1313,33 @@ class FakePlistUtils extends Fake implements PlistParser {
return fileContents[plistFilePath]!; return fileContents[plistFilePath]!;
} }
} }
class _FakeFileSystem extends Fake implements FileSystem {
@override
Directory directory(dynamic path) {
return _NonExistentDirectory();
}
@override
Context get path {
return MemoryFileSystem.test().path;
}
}
class _NonExistentDirectory extends Fake implements Directory {
@override
bool existsSync() {
throw const FileSystemException('OS Error: Filename, directory name, or volume label syntax is incorrect.');
}
@override
String get path => '';
@override
Directory get parent => _NonExistentDirectory();
}
class _FakeFsUtils extends Fake implements FileSystemUtils {
@override
String get homeDirPath => '/home/';
}
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