From 134b3c97f5b9333a1217d52ca979562728aa233e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 1 Oct 2015 13:53:28 +0200 Subject: [PATCH] test "import settings" --- .../testSrc/ApplicationStoreTest.kt | 88 +++++++++-- .../components/impl/ComponentManagerImpl.java | 5 +- .../ChooseComponentsToExportDialog.java | 43 +++--- .../ide/actions/ExportSettingsAction.kt | 142 ++++++++++++------ .../ide/actions/ImportSettingsAction.kt | 86 +++++------ .../components/impl/ServiceManagerImpl.java | 22 +-- .../com/intellij/openapi/util/io/fileUtil.kt | 19 ++- .../src/copyAppSettingsToRepository.kt | 2 +- 8 files changed, 255 insertions(+), 152 deletions(-) diff --git a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt index 3e8a1fc3e03f..532ca9cc66b2 100644 --- a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt @@ -16,24 +16,27 @@ package com.intellij.configurationStore import com.intellij.ide.actions.ExportableItem +import com.intellij.ide.actions.exportSettings import com.intellij.ide.actions.getExportableComponentsMap +import com.intellij.ide.actions.getPaths import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.* +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.testFramework.* import com.intellij.util.SmartList -import com.intellij.util.xmlb.XmlSerializer import com.intellij.util.xmlb.XmlSerializerUtil import com.intellij.util.xmlb.annotations.Attribute -import com.intellij.util.xmlb.serialize import gnu.trove.THashMap import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.data.MapEntry import org.intellij.lang.annotations.Language -import org.jdom.Element import org.junit.Before import org.junit.ClassRule import org.junit.Rule import org.junit.Test +import org.picocontainer.MutablePicoContainer +import org.picocontainer.defaults.InstanceComponentAdapter import java.io.ByteArrayInputStream import java.io.File import java.io.InputStream @@ -113,14 +116,65 @@ internal class ApplicationStoreTest { } @Test fun `export settings`() { + testAppConfig.refreshVfs() + val storageManager = ApplicationManager.getApplication().stateStore.stateStorageManager val optionsPath = storageManager.expandMacros(StoragePathMacros.APP_CONFIG) val rootConfigPath = storageManager.expandMacros(ROOT_CONFIG) val map = getExportableComponentsMap(false, true, storageManager) - assertThat(map.size()).isNotEqualTo(0) + assertThat(map).isNotEmpty() - val key = File(optionsPath, "filetypes.xml") - assertThat(map.get(key)).containsExactly(ExportableItem(listOf(key, File(rootConfigPath, "filetypes")), "File types", RoamingType.DEFAULT)) + fun test(item: ExportableItem) { + val file = item.files.first() + assertThat(map.get(file)).containsExactly(item) + assertThat(file).doesNotExist() + } + + test(ExportableItem(listOf(File(optionsPath, "filetypes.xml"), File(rootConfigPath, "filetypes")), "File types", RoamingType.DEFAULT)) + test(ExportableItem(listOf(File(optionsPath, "customization.xml")), "Menus and toolbars customization", RoamingType.DEFAULT)) + } + + @Test fun `import settings`() { + testAppConfig.refreshVfs() + + val component = A() + componentStore.initComponent(component, false) + + component.options.foo = "new" + + saveStore() + + val storageManager = componentStore.storageManager + + val configPath = storageManager.expandMacros(ROOT_CONFIG) + val configDir = Paths.get(configPath) + + val componentPath = configDir.resolve("a.xml") + assertThat(componentPath).isRegularFile() + val componentFile = componentPath.toFile() + + // additional export path + val additionalPath = configDir.resolve("foo") + additionalPath.writeChild("bar.icls", "") + val additionalFile = additionalPath.toFile() + val exportedData = BufferExposingByteArrayOutputStream() + exportSettings(setOf(componentFile, additionalFile), exportedData, configPath) + + val relativePaths = getPaths(ByteArrayInputStream(exportedData.internalBuffer, 0, exportedData.size())) + assertThat(relativePaths).containsOnly("a.xml", "foo/", "foo/bar.icls", "IntelliJ IDEA Global Settings") + val list = listOf(ExportableItem(listOf(componentFile, additionalFile), "")) + + fun File.to(that: B) = MapEntry.entry(this, that) + + val picoContainer = ApplicationManager.getApplication().picoContainer as MutablePicoContainer + val componentKey = A::class.java.name + picoContainer.registerComponent(InstanceComponentAdapter(componentKey, component)) + try { + assertThat(getExportableComponentsMap(false, false, storageManager, relativePaths)).containsOnly(componentFile to list, additionalFile to list) + } + finally { + picoContainer.unregisterComponent(componentKey) + } } private fun createComponentData(foo: String) = """""" @@ -146,16 +200,16 @@ internal class ApplicationStoreTest { """) } - @State(name = "A", storages = arrayOf(Storage(file = "a.xml"))) - private open class A : PersistentStateComponent { + @State(name = "A", storages = arrayOf(Storage(file = "a.xml")), additionalExportFile = "foo") + private open class A : PersistentStateComponent { data class State(@Attribute var foo: String = "", @Attribute var bar: String = "") - var state = State() + var options = State() - override fun getState() = state.serialize() + override fun getState() = options - override fun loadState(state: Element) { - this.state = XmlSerializer.deserialize(state, State::class.java)!! + override fun loadState(state: State) { + this.options = state } } @@ -167,15 +221,15 @@ internal class ApplicationStoreTest { val component = A() componentStore.initComponent(component, false) - assertThat(component.state).isEqualTo(A.State("old")) + assertThat(component.options).isEqualTo(A.State("old")) saveStore() assertThat(file).hasContent(oldContent) assertThat(oldModificationTime).isEqualTo(file.getLastModifiedTime()) - component.state.bar = "2" - component.state.foo = "1" + component.options.bar = "2" + component.options.foo = "1" saveStore() assertThat(file).hasContent("\n \n") @@ -191,7 +245,7 @@ internal class ApplicationStoreTest { val component = AWorkspace() componentStore.initComponent(component, false) - assertThat(component.state).isEqualTo(A.State("old")) + assertThat(component.options).isEqualTo(A.State("old")) saveStore() @@ -242,6 +296,8 @@ internal class ApplicationStoreTest { override fun setPath(path: String) { storageManager.addMacro(StoragePathMacros.APP_CONFIG, path) + // yes, in tests APP_CONFIG equals to ROOT_CONFIG (as ICS does) + storageManager.addMacro(ROOT_CONFIG, path) } } diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index 291ddf091b47..04179e2f8bca 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -365,9 +365,8 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } @Nullable - public final PluginId getConfig(@NotNull Class componentImplementation) { - ComponentConfigComponentAdapter adapter = getComponentAdapter(componentImplementation); - return adapter == null ? null : adapter.myPluginId; + public final PluginId getConfig(@NotNull ComponentAdapter adapter) { + return adapter instanceof ComponentConfigComponentAdapter ? ((ComponentConfigComponentAdapter)adapter).myPluginId : null; } public final boolean isWorkspaceComponent(@NotNull Class componentImplementation) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java index cf83ac0e14ad..c8421c8b107f 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java @@ -33,7 +33,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.FieldPanel; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; -import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -57,19 +57,21 @@ public class ChooseComponentsToExportDialog extends DialogWrapper { private final boolean myShowFilePath; private final String myDescription; - public ChooseComponentsToExportDialog(@NotNull MultiMap fileToComponents, + public ChooseComponentsToExportDialog(@NotNull Map> fileToComponents, boolean showFilePath, final String title, String description) { super(false); myDescription = description; myShowFilePath = showFilePath; Map componentToContainingListElement = new LinkedHashMap(); - for (ExportableItem component : fileToComponents.values()) { - if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) { - ComponentElementProperties componentElementProperties = new ComponentElementProperties(); - componentElementProperties.addComponent(component); + for (List list : fileToComponents.values()) { + for (ExportableItem component : list) { + if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) { + ComponentElementProperties componentElementProperties = new ComponentElementProperties(); + componentElementProperties.addComponent(component); - componentToContainingListElement.put(component, componentElementProperties); + componentToContainingListElement.put(component, componentElementProperties); + } } } myChooser = new ElementsChooser(true); @@ -149,21 +151,24 @@ public class ChooseComponentsToExportDialog extends DialogWrapper { private static boolean addToExistingListElement(@NotNull ExportableItem component, @NotNull Map componentToContainingListElement, - @NotNull MultiMap fileToComponents) { + @NotNull Map> fileToComponents) { File file = null; for (File exportFile : component.getFiles()) { - for (ExportableItem tiedComponent : fileToComponents.get(exportFile)) { - if (tiedComponent == component) { - continue; - } + List list = fileToComponents.get(exportFile); + if (!ContainerUtil.isEmpty(list)) { + for (ExportableItem tiedComponent : list) { + if (tiedComponent == component) { + continue; + } - final ComponentElementProperties elementProperties = componentToContainingListElement.get(tiedComponent); - if (elementProperties != null && !FileUtil.filesEqual(exportFile, file)) { - LOG.assertTrue(file == null, "Component " + component + " serialize itself into " + file + " and " + exportFile); - // found - elementProperties.addComponent(component); - componentToContainingListElement.put(component, elementProperties); - file = exportFile; + final ComponentElementProperties elementProperties = componentToContainingListElement.get(tiedComponent); + if (elementProperties != null && !FileUtil.filesEqual(exportFile, file)) { + LOG.assertTrue(file == null, "Component " + component + " serialize itself into " + file + " and " + exportFile); + // found + elementProperties.addComponent(component); + componentToContainingListElement.put(component, elementProperties); + file = exportFile; + } } } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.kt b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.kt index d547d67d234e..9fe114d806a6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.kt +++ b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.kt @@ -37,15 +37,19 @@ import com.intellij.openapi.project.DumbAware import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtilRt +import com.intellij.openapi.util.io.systemIndependentPath import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.util.PairProcessor import com.intellij.util.PlatformUtils import com.intellij.util.ReflectionUtil -import com.intellij.util.containers.MultiMap +import com.intellij.util.SmartList import com.intellij.util.io.ZipUtil import gnu.trove.THashSet -import java.io.* +import java.io.File +import java.io.IOException +import java.io.OutputStream +import java.io.OutputStreamWriter import java.util.* import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -80,26 +84,7 @@ private class ExportSettingsAction : AnAction(), DumbAware { return } - val zipOut = MyZipOutputStream(BufferedOutputStream(FileOutputStream(saveFile))) - try { - val writtenItemRelativePaths = THashSet() - val configRoot = FileUtilRt.toSystemIndependentName(PathManager.getConfigPath()) - for (file in exportFiles) { - if (file.exists()) { - val relativePath = FileUtilRt.getRelativePath(configRoot, FileUtilRt.toSystemIndependentName(file.absolutePath), '/')!! - ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths) - } - } - - exportInstalledPlugins(zipOut) - - val zipEntry = ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER) - zipOut.putNextEntry(zipEntry) - zipOut.closeEntry() - } - finally { - zipOut.doClose() - } + exportSettings(exportFiles, saveFile.outputStream().buffered(), FileUtilRt.toSystemIndependentName(PathManager.getConfigPath())) ShowFilePathAction.showDialog(AnAction.getEventProject(e), IdeBundle.message("message.settings.exported.successfully"), IdeBundle.message("title.export.successful"), saveFile, null) } @@ -109,6 +94,29 @@ private class ExportSettingsAction : AnAction(), DumbAware { } } +// not internal only to test +fun exportSettings(exportFiles: Set, out: OutputStream, configPath: String) { + val zipOut = MyZipOutputStream(out) + try { + val writtenItemRelativePaths = THashSet() + for (file in exportFiles) { + if (file.exists()) { + val relativePath = FileUtilRt.getRelativePath(configPath, FileUtilRt.toSystemIndependentName(file.absolutePath), '/')!! + ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths) + } + } + + exportInstalledPlugins(zipOut) + + val zipEntry = ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER) + zipOut.putNextEntry(zipEntry) + zipOut.closeEntry() + } + finally { + zipOut.doClose() + } +} + private class MyZipOutputStream(out: OutputStream) : ZipOutputStream(out) { override fun close() { } @@ -118,7 +126,7 @@ private class MyZipOutputStream(out: OutputStream) : ZipOutputStream(out) { } } -data class ExportableItem(val files: List, val presentableName: String, val roamingType: RoamingType) +data class ExportableItem(val files: List, val presentableName: String, val roamingType: RoamingType = RoamingType.DEFAULT) private val LOG = Logger.getInstance(ExportSettingsAction::class.java) @@ -143,8 +151,23 @@ private fun exportInstalledPlugins(zipOut: MyZipOutputStream) { } } -fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: Boolean, storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.stateStorageManager): MultiMap { - val result = MultiMap.createLinkedSet() +fun MutableMap>.putValue(key: K, value: V) { + var list = get(key) + if (list == null) { + list = SmartList(value) + put(key, list) + } + else { + list.add(value) + } +} + +// onlyPaths - include only specified paths (relative to config dir, ends with "/" if directory) +fun getExportableComponentsMap(onlyExisting: Boolean, + computePresentableNames: Boolean, + storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.stateStorageManager, + onlyPaths: Set? = null): Map> { + val result = LinkedHashMap>() val processor = { component: ExportableComponent -> val item = ExportableItem(component.exportFiles.toList(), component.presentableName, RoamingType.DEFAULT) for (exportFile in item.files) { @@ -156,10 +179,27 @@ fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: B ApplicationManager.getApplication().getComponents(ExportableApplicationComponent::class.java).forEach(processor) ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent::class.java).forEach(processor) - if (onlyExisting) { + @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") + val configPath = storageManager.expandMacros(StoragePathMacros.ROOT_CONFIG) + + fun isSkipFile(file: File): Boolean { + if (onlyPaths != null) { + var relativePath = FileUtilRt.getRelativePath(configPath, file.systemIndependentPath, '/')!! + if (!file.name.contains('.') && !file.isFile) { + relativePath += '/' + } + if (!onlyPaths.contains(relativePath)) { + return true + } + } + + return onlyExisting && !file.exists() + } + + if (onlyExisting || onlyPaths != null) { val it = result.keySet().iterator() while (it.hasNext()) { - if (!it.next().exists()) { + if (isSkipFile(it.next())) { it.remove() } } @@ -183,30 +223,32 @@ fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: B } val storage = storages[storageIndex] - if (storage.roamingType != RoamingType.DISABLED && storage.storageClass == StateStorage::class && storage.scheme == StorageScheme.DEFAULT && !storage.file.isNullOrEmpty()) { - var additionalExportFile: File? = null - var additionalExportPath = stateAnnotation.additionalExportFile - if (additionalExportPath.isNotEmpty()) { - // backward compatibility - path can contain macro - @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") - if (additionalExportPath[0] != '$') { - additionalExportPath = StoragePathMacros.ROOT_CONFIG + "/" + additionalExportPath - } - additionalExportFile = File(storageManager.expandMacros(additionalExportPath)) - if (onlyExisting && !additionalExportFile.exists()) { - additionalExportFile = null - } - } + if (!(storage.roamingType != RoamingType.DISABLED && storage.storageClass == StateStorage::class && storage.scheme == StorageScheme.DEFAULT && !storage.file.isNullOrEmpty())) { + return true + } - val file = File(storageManager.expandMacros(storage.file)) - val fileExists = !onlyExisting || file.exists() - if (fileExists || additionalExportFile != null) { - val files = if (additionalExportFile == null) listOf(file) else if (fileExists) listOf(file, additionalExportFile) else listOf(additionalExportFile) - val item = ExportableItem(files, if (computePresentableNames) getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor) else "", storage.roamingType) - result.putValue(file, item) - if (additionalExportFile != null) { - result.putValue(additionalExportFile, item) - } + var additionalExportFile: File? = null + var additionalExportPath = stateAnnotation.additionalExportFile + if (additionalExportPath.isNotEmpty()) { + // backward compatibility - path can contain macro + @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") + if (additionalExportPath[0] != '$') { + additionalExportPath = StoragePathMacros.ROOT_CONFIG + "/" + additionalExportPath + } + additionalExportFile = File(storageManager.expandMacros(additionalExportPath)) + if (isSkipFile(additionalExportFile)) { + additionalExportFile = null + } + } + + val file = File(storageManager.expandMacros(storage.file)) + val isFileIncluded = !isSkipFile(file) + if (isFileIncluded || additionalExportFile != null) { + val files = if (additionalExportFile == null) listOf(file) else if (isFileIncluded) listOf(file, additionalExportFile) else listOf(additionalExportFile) + val item = ExportableItem(files, if (computePresentableNames) getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor) else "", storage.roamingType) + result.putValue(file, item) + if (additionalExportFile != null) { + result.putValue(additionalExportFile, item) } } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.kt b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.kt index 44e4d5c57f8e..a92a0d5e3c88 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.kt +++ b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.kt @@ -30,13 +30,14 @@ import com.intellij.openapi.ui.Messages import com.intellij.openapi.updateSettings.impl.UpdateSettings import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtilRt +import com.intellij.openapi.util.io.parentPath import com.intellij.util.Consumer import gnu.trove.THashSet import java.io.File import java.io.IOException -import java.util.* +import java.io.InputStream import java.util.zip.ZipException -import java.util.zip.ZipFile +import java.util.zip.ZipInputStream private class ImportSettingsAction : AnAction(), DumbAware { override fun actionPerformed(e: AnActionEvent) { @@ -68,40 +69,26 @@ private class ImportSettingsAction : AnAction(), DumbAware { return } - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - val magicEntry = ZipFile(saveFile).getEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER) - if (magicEntry == null) { + val relativePaths = getPaths(saveFile.inputStream()) + if (!relativePaths.contains(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER)) { Messages.showErrorDialog( IdeBundle.message("error.file.contains.no.settings.to.import", presentableFileName(saveFile), promptLocationMessage()), IdeBundle.message("title.invalid.file")) return } - val fileToComponents = getExportableComponentsMap(false, true) - val components = getComponentsStored(saveFile, fileToComponents.values()) - fileToComponents.values().retainAll(components) - val dialog = ChooseComponentsToExportDialog(fileToComponents, false, + val configPath = FileUtil.toSystemIndependentName(PathManager.getConfigPath()) + val dialog = ChooseComponentsToExportDialog(getExportableComponentsMap(false, true, onlyPaths = relativePaths), false, IdeBundle.message("title.select.components.to.import"), IdeBundle.message("prompt.check.components.to.import")) if (!dialog.showAndGet()) { return } - val chosenComponents = dialog.exportableComponents - val relativeNamesToExtract = THashSet() - for (chosenComponent in chosenComponents) { - for (exportFile in chosenComponent.files) { - relativeNamesToExtract.add(FileUtil.toSystemIndependentName(FileUtilRt.getRelativePath(File(PathManager.getConfigPath()), exportFile)!!)) - } - } - - relativeNamesToExtract.add(PluginManager.INSTALLED_TXT) - val tempFile = File(PathManager.getPluginTempPath(), saveFile.name) FileUtil.copy(saveFile, tempFile) - val outDir = File(PathManager.getConfigPath()) - val filenameFilter = ImportSettingsFilenameFilter(relativeNamesToExtract) - StartupActionScriptManager.addActionCommand(StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter)) + val filenameFilter = ImportSettingsFilenameFilter(getRelativeNamesToExtract(dialog.exportableComponents)) + StartupActionScriptManager.addActionCommand(StartupActionScriptManager.UnzipCommand(tempFile, File(configPath), filenameFilter)) // remove temp file StartupActionScriptManager.addActionCommand(StartupActionScriptManager.DeleteCommand(tempFile)) @@ -119,38 +106,39 @@ private class ImportSettingsAction : AnAction(), DumbAware { } } + private fun getRelativeNamesToExtract(chosenComponents: Set): Set { + val result = THashSet() + for (chosenComponent in chosenComponents) { + for (exportFile in chosenComponent.files) { + result.add(FileUtil.toSystemIndependentName(FileUtilRt.getRelativePath(File(PathManager.getConfigPath()), exportFile)!!)) + } + } + + result.add(PluginManager.INSTALLED_TXT) + return result + } + private fun presentableFileName(file: File) = "'" + FileUtil.toSystemDependentName(file.path) + "'" private fun promptLocationMessage() = IdeBundle.message("message.please.ensure.correct.settings") +} - private fun getComponentsStored(settings: File, registeredComponents: Collection): List { - val zipEntries = THashSet() - val zipFile = ZipFile(settings) - try { - val enumeration = zipFile.entries() - while (enumeration.hasMoreElements()) { - zipEntries.add(enumeration.nextElement().name) +fun getPaths(input: InputStream): Set { + val result = THashSet() + val zipIn = ZipInputStream(input) + try { + while (true) { + val entry = zipIn.nextEntry ?: break + var path = entry.name + result.add(path) + while (true) { + path = path.parentPath ?: break + result.add("$path/") } } - finally { - zipFile.close() - } - - val configPath = File(PathManager.getConfigPath()) - val components = ArrayList() - for (component in registeredComponents) { - for (exportFile in component.files) { - var relativePath = FileUtilRt.getRelativePath(configPath, exportFile)!! - relativePath = FileUtilRt.toSystemIndependentName(relativePath) - if (exportFile.name.indexOf('.') == -1 && !exportFile.isFile) { - relativePath += '/' - } - if (zipEntries.contains(relativePath)) { - components.add(component) - break - } - } - } - return components + } + finally { + zipIn.close() } + return result } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index cd4904a749c2..ce4f2dbf54cf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -40,6 +40,7 @@ import com.intellij.util.pico.ConstructorInjectionComponentAdapter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.picocontainer.*; +import org.picocontainer.defaults.InstanceComponentAdapter; import java.util.Arrays; import java.util.Collection; @@ -142,17 +143,18 @@ public class ServiceManagerImpl implements BaseComponent { } } else if (o instanceof ComponentAdapter && !(o instanceof ExtensionComponentAdapter)) { - try { - aClass = ((ComponentAdapter)o).getComponentImplementation(); - } - catch (Throwable e) { - LOG.error(e); - continue; - } + PluginId pluginId = componentManager.getConfig((ComponentAdapter)o); + // allow InstanceComponentAdapter without pluginId to test + if (pluginId != null || o instanceof InstanceComponentAdapter) { + try { + aClass = ((ComponentAdapter)o).getComponentImplementation(); + } + catch (Throwable e) { + LOG.error(e); + continue; + } - PluginId pluginId = componentManager.getConfig(aClass); - if (pluginId != null) { - processor.process(aClass, PluginManager.getPlugin(pluginId)); + processor.process(aClass, pluginId == null ? null : PluginManager.getPlugin(pluginId)); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt b/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt index 69ef520354da..19ca3fc6823b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt +++ b/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt @@ -17,9 +17,20 @@ package com.intellij.openapi.util.io import java.io.File -public val File.systemIndependentPath: String - get() = getPath().replace(File.separatorChar, '/') +val File.systemIndependentPath: String + get() = path.replace(File.separatorChar, '/') +val File.parentSystemIndependentPath: String + get() = getParent().replace(File.separatorChar, '/') -public val File.parentSystemIndependentPath: String - get() = getParent().replace(File.separatorChar, '/') \ No newline at end of file +val String.parentPath: String? + get() { + if (isEmpty()) { + return null + } + var end = Math.max(lastIndexOf('/'), lastIndexOf('\\')) + if (end == length() - 1) { + end = Math.max(lastIndexOf('/', end - 1), lastIndexOf('\\', end - 1)) + } + return if (end == -1) null else substring(0, end) + } \ No newline at end of file diff --git a/plugins/settings-repository/src/copyAppSettingsToRepository.kt b/plugins/settings-repository/src/copyAppSettingsToRepository.kt index 435a9116a2dc..70764071438e 100644 --- a/plugins/settings-repository/src/copyAppSettingsToRepository.kt +++ b/plugins/settings-repository/src/copyAppSettingsToRepository.kt @@ -42,7 +42,7 @@ fun copyLocalConfig(storageManager: StateStorageManagerImpl = ApplicationManager } } - val roamingType = getRoamingType(fileToComponents.get(file)) + val roamingType = getRoamingType(fileToComponents.get(file)!!) if (file.isFile) { val fileBytes = FileUtil.loadFileBytes(file) streamProvider.doSave(fileSpec, fileBytes, fileBytes.size(), roamingType)