[rdct] create a special MigratePluginsFromCustomPlace option and use it to migrate plugins from the IDE to the frontend (RDCT-1393)

When a frontend process starts for the first time on a machine where the corresponding major version of the regular IDE has been already used, we need to migrate some plugins (e.g., keymaps) from the IDE to the frontend. Before it was done using the existing MigrateFromCustomPlace option. However, with such an approach, the whole config directory for the frontend process (which already has some files) is deleted and replaced by the IDE's config directory. And this causes problems, e.g., because it tries to back up and remove the 'process.lock' file. Since we need to migrate only plugins in this case, it's better to have a special config migration option for that. So MigratePluginsFromCustomPlace is introduced, and ConfigImportHelper is changed to run 'migratePlugins' only if this option is used.

This logic will be removed later when the frontend process starts to use the same directory for downloaded plugins as a regular IDE (see RDCT-1738).


(cherry picked from commit e1325d9c9b3866b692a0e20bcdb8cd8e15344ca0)

IJ-CR-147196

GitOrigin-RevId: 632de6d78c8e694dfde0bae87c4bab59d9eeddcd
This commit is contained in:
Nikolay Chashnikov
2024-10-17 23:39:47 +02:00
committed by intellij-monorepo-bot
parent 843c5961b2
commit 5db802c044
4 changed files with 75 additions and 23 deletions

View File

@@ -24,7 +24,7 @@ final class PerProcessPathCustomization {
// The config directory exists, but the plugins for the frontend process weren't migrated,
// so we trigger importing of config from the local IDE to migrate the plugins.
customTargetDirectoryToImportConfig = newConfig;
new CustomConfigMigrationOption.MigrateFromCustomPlace(oldConfigPath).writeConfigMarkerFile(newConfig);
new CustomConfigMigrationOption.MigratePluginsFromCustomPlace(oldConfigPath).writeConfigMarkerFile(newConfig);
}
CustomConfigFiles.prepareConfigDir(newConfig, oldConfigPath);
}

View File

@@ -28,10 +28,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.NioFiles;
import com.intellij.openapi.util.registry.EarlyAccessRegistryManager;
@@ -127,6 +124,24 @@ public final class ConfigImportHelper {
ConfigImportSettings settings = findCustomConfigImportSettings();
log.info("Custom ConfigImportSettings instance: " + settings);
if (customMigrationOption instanceof CustomConfigMigrationOption.MigratePluginsFromCustomPlace migratePluginsOption) {
var oldConfigDir = migratePluginsOption.getConfigLocation();
if (isConfigDirectory(oldConfigDir)) {
var oldPluginsDir = computeOldPluginsDir(oldConfigDir, null);
var newPluginsDir = newConfigDir.getFileSystem().getPath(PathManager.getPluginsPath());
ConfigImportOptions importOptions = createConfigImportOptions(settings, customMigrationOption, log);
try {
migratePlugins(oldPluginsDir, oldConfigDir, newPluginsDir, newConfigDir, importOptions, Predicates.alwaysFalse());
}
catch (IOException e) {
log.warn(e);
}
}
else {
logInfoAboutNotAcceptedConfigDirectory(log, "Custom plugins location", oldConfigDir);
}
return;
}
List<String> otherProductPrefixes = settings != null ? settings.getProductsToImportFrom(args) : List.of();
ConfigDirsSearchResult guessedOldConfigDirs = findConfigDirectories(newConfigDir, settings, otherProductPrefixes);
@@ -210,13 +225,7 @@ public final class ConfigImportHelper {
oldConfigDir = oldConfigDirAndOldIdePath.first;
Path oldIdeHome = oldConfigDirAndOldIdePath.second;
var configImportOptions = new ConfigImportOptions(log);
configImportOptions.importSettings = settings;
configImportOptions.mergeVmOptions = customMigrationOption instanceof CustomConfigMigrationOption.MergeConfigs;
/* in remote dev host mode UI cannot be shown before `Application` is initialized because it replaces the standard `awt.toolkit`
with com.intellij.platform.impl.toolkit.IdeToolkit which depends on `Application` */
configImportOptions.setHeadless(AppMode.isRemoteDevHost());
var configImportOptions = createConfigImportOptions(settings, customMigrationOption, log);
if (!guessedOldConfigDirs.fromSameProduct) {
importScenarioStatistics = IMPORTED_FROM_OTHER_PRODUCT;
@@ -290,6 +299,19 @@ public final class ConfigImportHelper {
}
}
private static @NotNull ConfigImportOptions createConfigImportOptions(@Nullable ConfigImportSettings settings,
@Nullable CustomConfigMigrationOption customMigrationOption,
@NotNull Logger log) {
var configImportOptions = new ConfigImportOptions(log);
configImportOptions.importSettings = settings;
configImportOptions.mergeVmOptions = customMigrationOption instanceof CustomConfigMigrationOption.MergeConfigs;
/* in remote dev host mode UI cannot be shown before `Application` is initialized because it replaces the standard `awt.toolkit`
with com.intellij.platform.impl.toolkit.IdeToolkit which depends on `Application` */
configImportOptions.setHeadless(AppMode.isRemoteDevHost());
return configImportOptions;
}
private static void logInfoAboutNotAcceptedConfigDirectory(@NotNull Logger log, @NotNull String description, @NotNull Path path) {
StringBuilder builder = new StringBuilder();
builder.append(description + " was detected but not accepted: ");
@@ -832,16 +854,7 @@ public final class ConfigImportHelper {
return;
}
Path oldPluginsDir = oldConfigDir.resolve(PLUGINS);
if (!Files.isDirectory(oldPluginsDir)) {
oldPluginsDir = null;
if (oldIdeHome != null) {
oldPluginsDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_PLUGINS_PATH, ConfigImportHelper::defaultPluginsPath);
}
if (oldPluginsDir == null) {
oldPluginsDir = oldConfigDir.getFileSystem().getPath(defaultPluginsPath(getNameWithVersion(oldConfigDir)));
}
}
Path oldPluginsDir = computeOldPluginsDir(oldConfigDir, oldIdeHome);
Path newPluginsDir = newConfigDir.getFileSystem().getPath(PathManager.getPluginsPath());
@@ -858,6 +871,20 @@ public final class ConfigImportHelper {
}
}
private static @NotNull Path computeOldPluginsDir(@NotNull Path oldConfigDir, @Nullable Path oldIdeHome) {
Path oldPluginsDir = oldConfigDir.resolve(PLUGINS);
if (!Files.isDirectory(oldPluginsDir)) {
oldPluginsDir = null;
if (oldIdeHome != null) {
oldPluginsDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_PLUGINS_PATH, ConfigImportHelper::defaultPluginsPath);
}
if (oldPluginsDir == null) {
oldPluginsDir = oldConfigDir.getFileSystem().getPath(defaultPluginsPath(getNameWithVersion(oldConfigDir)));
}
}
return oldPluginsDir;
}
public static final class ConfigImportOptions {
final Logger log;
boolean headless;

View File

@@ -52,6 +52,15 @@ sealed class CustomConfigMigrationOption {
override fun getStringPresentation(): String = IMPORT_PREFIX + location.toString().replace(File.separatorChar, '/')
}
/**
* A variant of [MigrateFromCustomPlace] which migrates plugins only.
* This option is supposed to be used only to migrate plugins from a regular IDE to its frontend process.
* It'll be removed when the frontend process starts loading plugins from the same directory as a regular IDE (RDCT-1738).
*/
class MigratePluginsFromCustomPlace(val configLocation: Path) : CustomConfigMigrationOption() {
override fun getStringPresentation(): String = MIGRATE_PLUGINS_PREFIX + configLocation.toString().replace(File.separatorChar, '/')
}
class SetProperties(val properties: List<String>) : CustomConfigMigrationOption() {
override fun getStringPresentation(): String = PROPERTIES_PREFIX + properties.joinToString(separator = " ")
}
@@ -62,6 +71,7 @@ sealed class CustomConfigMigrationOption {
companion object {
private const val IMPORT_PREFIX = "import "
private const val MIGRATE_PLUGINS_PREFIX = "migrate-plugins "
private const val PROPERTIES_PREFIX = "properties "
private const val MERGE_CONFIGS_COMMAND = "merge-configs"
@@ -87,6 +97,10 @@ sealed class CustomConfigMigrationOption {
return MigrateFromCustomPlace(path)
}
line.startsWith(MIGRATE_PLUGINS_PREFIX) -> {
return MigratePluginsFromCustomPlace(markerFile.fileSystem.getPath(line.removePrefix(MIGRATE_PLUGINS_PREFIX)))
}
line.startsWith(PROPERTIES_PREFIX) -> {
val properties = line.removePrefix(PROPERTIES_PREFIX).split(' ')
return SetProperties(properties)

View File

@@ -27,6 +27,17 @@ class CustomConfigMigrationOptionTest : ConfigImportHelperBaseTest() {
assertEquals("Import path parsed incorrectly", path, (option as CustomConfigMigrationOption.MigrateFromCustomPlace).location.toString())
}
@Test
fun `marker file with migrate plugins path`() {
val path = PathManager.getDefaultConfigPathFor("IntelliJIdea2019.3")
Files.createDirectories(memoryFs.fs.getPath(path))
val configDir = createMarkerFile("migrate-plugins $path")
val option = readOption(configDir)
assertThat(option).isInstanceOf(CustomConfigMigrationOption.MigratePluginsFromCustomPlace::class.java)
assertEquals(path, (option as CustomConfigMigrationOption.MigratePluginsFromCustomPlace).configLocation.toString())
}
@Test
fun `marker file with properties to set`() {
val properties = listOf("intellij.first.ide.session", "intellij.config.imported.in.current.session")