diff --git a/platform/bootstrap/src/com/intellij/platform/ide/impl/startup/multiProcess/PerProcessPathCustomization.java b/platform/bootstrap/src/com/intellij/platform/ide/impl/startup/multiProcess/PerProcessPathCustomization.java index f3c103142957..463ddb8dca02 100644 --- a/platform/bootstrap/src/com/intellij/platform/ide/impl/startup/multiProcess/PerProcessPathCustomization.java +++ b/platform/bootstrap/src/com/intellij/platform/ide/impl/startup/multiProcess/PerProcessPathCustomization.java @@ -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); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java index 96d24fb22082..4f7956f1c550 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java @@ -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 otherProductPrefixes = settings != null ? settings.getProductsToImportFrom(args) : List.of(); ConfigDirsSearchResult guessedOldConfigDirs = findConfigDirectories(newConfigDir, settings, otherProductPrefixes); @@ -210,14 +225,8 @@ 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/application/CustomConfigMigrationOption.kt b/platform/platform-impl/src/com/intellij/openapi/application/CustomConfigMigrationOption.kt index 3e2db5330c3b..bceef567baf0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/CustomConfigMigrationOption.kt +++ b/platform/platform-impl/src/com/intellij/openapi/application/CustomConfigMigrationOption.kt @@ -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) : 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" @@ -86,6 +96,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(' ') diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/application/CustomConfigMigrationOptionTest.kt b/platform/platform-tests/testSrc/com/intellij/openapi/application/CustomConfigMigrationOptionTest.kt index d76b944906fe..0143c1dca5f1 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/application/CustomConfigMigrationOptionTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/openapi/application/CustomConfigMigrationOptionTest.kt @@ -26,6 +26,17 @@ class CustomConfigMigrationOptionTest : ConfigImportHelperBaseTest() { assertThat(option).isInstanceOf(CustomConfigMigrationOption.MigrateFromCustomPlace::class.java) 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`() {