Unverified Commit e197a96f authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Find Intellij installations with Spotlight query on macOS (#80479)

parent 58c8a71b
......@@ -84,6 +84,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
platform: globals.platform,
userMessages: userMessages,
plistParser: globals.plistParser,
processManager: globals.processManager,
),
...VsCodeValidator.installedValidators(globals.fs, globals.platform),
];
......
......@@ -3,15 +3,23 @@
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/user_messages.dart' hide userMessages;
import '../base/version.dart';
import '../convert.dart';
import '../doctor_validator.dart';
import '../ios/plist_parser.dart';
import 'intellij.dart';
const String _ultimateEditionTitle = 'IntelliJ IDEA Ultimate Edition';
const String _ultimateEditionId = 'IntelliJIdea';
const String _communityEditionTitle = 'IntelliJ IDEA Community Edition';
const String _communityEditionId = 'IdeaIC';
/// A doctor validator for both Intellij and Android Studio.
abstract class IntelliJValidator extends DoctorValidator {
IntelliJValidator(String title, this.installPath, {
......@@ -30,8 +38,8 @@ abstract class IntelliJValidator extends DoctorValidator {
String? get pluginsPath;
static const Map<String, String> _idToTitle = <String, String>{
'IntelliJIdea': 'IntelliJ IDEA Ultimate Edition',
'IdeaIC': 'IntelliJ IDEA Community Edition',
_ultimateEditionId: _ultimateEditionTitle,
_communityEditionId: _communityEditionTitle,
};
static final Version kMinIdeaVersion = Version(2017, 1, 0);
......@@ -45,6 +53,7 @@ abstract class IntelliJValidator extends DoctorValidator {
required Platform platform,
required UserMessages userMessages,
required PlistParser plistParser,
required ProcessManager processManager,
}) {
final FileSystemUtils fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform);
if (platform.isWindows) {
......@@ -68,6 +77,7 @@ abstract class IntelliJValidator extends DoctorValidator {
fileSystemUtils: fileSystemUtils,
userMessages: userMessages,
plistParser: plistParser,
processManager: processManager,
);
}
return <DoctorValidator>[];
......@@ -369,9 +379,9 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
final String? _homeDirPath;
static const Map<String, String> _dirNameToId = <String, String>{
'IntelliJ IDEA.app': 'IntelliJIdea',
'IntelliJ IDEA Ultimate.app': 'IntelliJIdea',
'IntelliJ IDEA CE.app': 'IdeaIC',
'IntelliJ IDEA.app': _ultimateEditionId,
'IntelliJ IDEA Ultimate.app': _ultimateEditionId,
'IntelliJ IDEA CE.app': _communityEditionId,
};
static Iterable<DoctorValidator> installed({
......@@ -379,6 +389,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
required FileSystemUtils fileSystemUtils,
required UserMessages userMessages,
required PlistParser plistParser,
required ProcessManager processManager,
}) {
final List<DoctorValidator> validators = <DoctorValidator>[];
final String? homeDirPath = fileSystemUtils.homeDirPath;
......@@ -423,6 +434,52 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
}
}
}
// Query Spotlight for unexpected installation locations.
String ceSpotlightResult = '';
String ultimateSpotlightResult = '';
try {
final ProcessResult ceQueryResult = processManager.runSync(<String>[
'mdfind',
'kMDItemCFBundleIdentifier="com.jetbrains.intellij.ce"',
]);
ceSpotlightResult = ceQueryResult.stdout as String;
final ProcessResult ultimateQueryResult = processManager.runSync(<String>[
'mdfind',
'kMDItemCFBundleIdentifier="com.jetbrains.intellij*"',
]);
ultimateSpotlightResult = ultimateQueryResult.stdout as String;
} on ProcessException {
// The Spotlight query is a nice-to-have, continue checking known installation locations.
}
for (final String installPath in LineSplitter.split(ceSpotlightResult)) {
if (!validators.whereType<IntelliJValidatorOnMac>().any((IntelliJValidatorOnMac e) => e.installPath == installPath)) {
validators.add(IntelliJValidatorOnMac(
_communityEditionTitle,
_communityEditionId,
installPath,
fileSystem: fileSystem,
userMessages: userMessages,
plistParser: plistParser,
homeDirPath: homeDirPath,
));
}
}
for (final String installPath in LineSplitter.split(ultimateSpotlightResult)) {
if (!validators.whereType<IntelliJValidatorOnMac>().any((IntelliJValidatorOnMac e) => e.installPath == installPath)) {
validators.add(IntelliJValidatorOnMac(
_ultimateEditionTitle,
_ultimateEditionId,
installPath,
fileSystem: fileSystem,
userMessages: userMessages,
plistParser: plistParser,
homeDirPath: homeDirPath,
));
}
}
} on FileSystemException catch (e) {
validators.add(ValidatorWithResult(
userMessages.intellijMacUnknownResult,
......
......@@ -14,6 +14,7 @@ import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
final Platform macPlatform = FakePlatform(
operatingSystem: 'macos',
......@@ -269,6 +270,55 @@ void main() {
expect(ValidationType.installed, result.type);
});
testWithoutContext('can locate installations on macOS from Spotlight', () {
final FileSystem fileSystem = MemoryFileSystem.test();
final String ceRandomLocation = fileSystem.path.join(
'/',
'random',
'IntelliJ CE (stable).app',
);
final String ultimateRandomLocation = fileSystem.path.join(
'/',
'random',
'IntelliJ UE (stable).app',
);
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>[
'mdfind',
'kMDItemCFBundleIdentifier="com.jetbrains.intellij.ce"',
],
stdout: ceRandomLocation,
),
FakeCommand(
command: const <String>[
'mdfind',
'kMDItemCFBundleIdentifier="com.jetbrains.intellij*"',
],
stdout: '$ultimateRandomLocation\n$ceRandomLocation',
),
]);
final Iterable<IntelliJValidatorOnMac> validators = IntelliJValidator.installedValidators(
fileSystem: fileSystem,
platform: macPlatform,
userMessages: UserMessages(),
processManager: processManager,
plistParser: FakePlistParser(<String, String>{
PlistParser.kCFBundleShortVersionStringKey: '2020.10',
}),
).whereType<IntelliJValidatorOnMac>();
expect(validators.length, 2);
final IntelliJValidatorOnMac ce = validators.where((IntelliJValidatorOnMac validator) => validator.id == 'IdeaIC').single;
expect(ce.title, 'IntelliJ IDEA Community Edition');
expect(ce.installPath, ceRandomLocation);
final IntelliJValidatorOnMac utlimate = validators.where((IntelliJValidatorOnMac validator) => validator.id == 'IntelliJIdea').single;
expect(utlimate.title, 'IntelliJ IDEA Ultimate Edition');
expect(utlimate.installPath, ultimateRandomLocation);
});
testWithoutContext('Intellij plugins path checking on mac', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory pluginsDirectory = fileSystem.directory('/foo/bar/Library/Application Support/JetBrains/TestID2020.10/plugins')
......
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