From 148fafa5cbabd1c609f08aa9b09bf0348ea3a859 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 27 Dec 2016 14:28:06 +0100 Subject: [PATCH] =?UTF-8?q?read-only=20sources=20must=20works=20without=20?= =?UTF-8?q?configured=20ICS=20repo=20=E2=80=94=20StreamProvider=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SchemeManagerImpl.kt | 20 ++++----- .../src/StreamProviderWrapper.kt | 19 ++++----- .../src/XmlElementStorage.kt | 42 +++++++++---------- .../testSrc/ApplicationStoreTest.kt | 13 +++--- .../testSrc/MockStreamProvider.kt | 14 ++++--- .../com/intellij/ui/layout/LayoutBuilder.kt | 4 +- .../intellij/ui/layout/MigLayoutBuilder.kt | 25 +++++++++++ .../src/com/intellij/ui/layout/Row.kt | 4 ++ .../configurationStore/StreamProvider.kt | 17 ++++++-- .../SchemeManagerIprProvider.kt | 12 +++--- plugins/settings-repository/src/IcsManager.kt | 38 +++++++++++++---- .../src/ReadOnlySourceManager.kt | 8 ++-- plugins/settings-repository/src/autoSync.kt | 2 +- .../src/repositoryListEditor.kt | 20 +++++---- plugins/settings-repository/src/sync.kt | 38 ++++++++--------- 15 files changed, 172 insertions(+), 104 deletions(-) diff --git a/platform/configuration-store-impl/src/SchemeManagerImpl.kt b/platform/configuration-store-impl/src/SchemeManagerImpl.kt index c93dd0de68de..fc66de876304 100644 --- a/platform/configuration-store-impl/src/SchemeManagerImpl.kt +++ b/platform/configuration-store-impl/src/SchemeManagerImpl.kt @@ -278,16 +278,15 @@ class SchemeManagerImpl(val fileSpec: String, val oldSchemes = schemes val schemes = oldSchemes.toMutableList() val newSchemesOffset = schemes.size - if (provider != null && provider.isApplicable(fileSpec, roamingType)) { - provider.processChildren(fileSpec, roamingType, { canRead(it) }) { name, input, readOnly -> - catchAndLog(name) { - val scheme = loadScheme(name, input, schemes, filesToDelete) - if (readOnly && scheme != null) { - readOnlyExternalizableSchemes.put(scheme.name, scheme) - } + if (provider != null && provider.processChildren(fileSpec, roamingType, { canRead(it) }) { name, input, readOnly -> + catchAndLog(name) { + val scheme = loadScheme(name, input, schemes, filesToDelete) + if (readOnly && scheme != null) { + readOnlyExternalizableSchemes.put(scheme.name, scheme) } - true } + true + }) { } else { ioDirectory.directoryStreamIfExists({ canRead(it.fileName.toString()) }) { @@ -717,14 +716,13 @@ class SchemeManagerImpl(val fileSpec: String, } private fun deleteFiles(errors: MutableList, filesToDelete: MutableSet) { - if (provider != null && provider.enabled) { + if (provider != null) { val iterator = filesToDelete.iterator() for (name in iterator) { errors.catch { val spec = "$fileSpec/$name" - if (provider.isApplicable(spec, roamingType)) { + if (provider.delete(spec, roamingType)) { iterator.remove() - provider.delete(spec, roamingType) } } } diff --git a/platform/configuration-store-impl/src/StreamProviderWrapper.kt b/platform/configuration-store-impl/src/StreamProviderWrapper.kt index d3751393c286..6bf219ab3a10 100644 --- a/platform/configuration-store-impl/src/StreamProviderWrapper.kt +++ b/platform/configuration-store-impl/src/StreamProviderWrapper.kt @@ -10,28 +10,25 @@ class StreamProviderWrapper : StreamProvider { override val enabled: Boolean get() = streamProvider.let { it != null && it.enabled } - override fun isApplicable(fileSpec: String, roamingType: RoamingType): Boolean { - return enabled && streamProvider!!.isApplicable(fileSpec, roamingType) - } + override fun isApplicable(fileSpec: String, roamingType: RoamingType) = streamProvider?.isApplicable(fileSpec, roamingType) ?: false - override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> R): R { - return streamProvider!!.read(fileSpec, roamingType, consumer) - } + override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> Unit) = streamProvider?.read(fileSpec, roamingType, consumer) ?: false override fun processChildren(path: String, roamingType: RoamingType, filter: Function1, - processor: Function3) { - streamProvider!!.processChildren(path, roamingType, filter, processor) + processor: Function3): Boolean { + return streamProvider?.let { + it.processChildren(path, roamingType, filter, processor) + true + } ?: false } override fun write(fileSpec: String, content: ByteArray, size: Int, roamingType: RoamingType) { streamProvider!!.write(fileSpec, content, size, roamingType) } - override fun delete(fileSpec: String, roamingType: RoamingType) { - streamProvider!!.delete(fileSpec, roamingType) - } + override fun delete(fileSpec: String, roamingType: RoamingType) = streamProvider?.delete(fileSpec, roamingType) ?: false } fun StreamProvider?.getOriginalProvider() = if (this is StreamProviderWrapper) streamProvider else null \ No newline at end of file diff --git a/platform/configuration-store-impl/src/XmlElementStorage.kt b/platform/configuration-store-impl/src/XmlElementStorage.kt index 626c1dcb5c3f..ed308b9c4a98 100644 --- a/platform/configuration-store-impl/src/XmlElementStorage.kt +++ b/platform/configuration-store-impl/src/XmlElementStorage.kt @@ -47,25 +47,25 @@ abstract class XmlElementStorage protected constructor(val fileSpec: String, override fun hasState(storageData: StateMap, componentName: String) = storageData.hasState(componentName) - override fun loadData(): StateMap { - val element: Element? - // we don't use local data if has stream provider - if (provider != null && provider.isApplicable(fileSpec, roamingType)) { - element = LOG.catchAndLog { - loadDataFromProvider().apply { dataLoadedFromProvider(this) } + override fun loadData() = loadElement()?.let { loadState(it) } ?: StateMap.EMPTY + + private fun loadElement(useStreamProvider: Boolean = true): Element? { + var element: Element? = null + LOG.catchAndLog { + if (!useStreamProvider || !(provider?.read(fileSpec, roamingType) { + it?.let { + element = loadElement(it) + } + } ?: false)) { + element = loadLocalData() } } - else { - element = loadLocalData() - } - return element?.let { loadState(element) } ?: StateMap.EMPTY + return element } protected open fun dataLoadedFromProvider(element: Element?) { } - private fun loadDataFromProvider(): Element? = provider!!.read(fileSpec, roamingType) { it?.let(::loadElement) } - private fun loadState(element: Element): StateMap { beforeElementLoaded(element) return StateMap.fromMap(FileStorageCoreUtil.load(element, pathMacroSubstitutor, true)) @@ -127,15 +127,15 @@ abstract class XmlElementStorage protected constructor(val fileSpec: String, } val provider = storage.provider - if (provider != null && provider.isApplicable(storage.fileSpec, storage.roamingType)) { - if (element == null) { - provider.delete(storage.fileSpec, storage.roamingType) - } - else { - // we should use standard line-separator (\n) - stream provider can share file content on any OS - provider.write(storage.fileSpec, element.toBufferExposingByteArray(), storage.roamingType) + if (element == null) { + if (provider == null || !provider.delete(storage.fileSpec, storage.roamingType)) { + saveLocally(null) } } + else if (provider != null && provider.isApplicable(storage.fileSpec, storage.roamingType)) { + // we should use standard line-separator (\n) - stream provider can share file content on any OS + provider.write(storage.fileSpec, element.toBufferExposingByteArray(), storage.roamingType) + } else { saveLocally(element) } @@ -163,14 +163,14 @@ abstract class XmlElementStorage protected constructor(val fileSpec: String, updatedFrom(changedComponentNames, deleted, true) } - fun updatedFrom(changedComponentNames: MutableSet, deleted: Boolean, streamProvider: Boolean) { + fun updatedFrom(changedComponentNames: MutableSet, deleted: Boolean, useStreamProvider: Boolean) { if (roamingType == RoamingType.DISABLED) { // storage roaming was changed to DISABLED, but settings repository has old state return } LOG.catchAndLog { - val newElement = if (deleted) null else if (streamProvider) loadDataFromProvider() else loadLocalData() + val newElement = if (deleted) null else loadElement(useStreamProvider) val states = storageDataRef.get() if (newElement == null) { // if data was loaded, mark as changed all loaded components diff --git a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt index d53084807b2a..3d96c2904891 100644 --- a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt @@ -323,7 +323,8 @@ internal class ApplicationStoreTest { private fun writeConfig(fileName: String, @Language("XML") data: String) = testAppConfig.writeChild(fileName, data) private class MyStreamProvider : StreamProvider { - override fun processChildren(path: String, roamingType: RoamingType, filter: (String) -> Boolean, processor: (String, InputStream, Boolean) -> Boolean) { + override fun processChildren(path: String, roamingType: RoamingType, filter: (String) -> Boolean, processor: (String, InputStream, Boolean) -> Boolean): Boolean { + return true } val data: MutableMap> = THashMap() @@ -341,13 +342,15 @@ internal class ApplicationStoreTest { return map } - override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> R): R { + override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> Unit): Boolean { val data = getMap(roamingType).get(fileSpec) - return data?.let { ByteArrayInputStream(it.toByteArray()) }.let(consumer) + data?.let { ByteArrayInputStream(it.toByteArray()) }.let(consumer) + return true } - override fun delete(fileSpec: String, roamingType: RoamingType) { - data[roamingType]?.remove(fileSpec) + override fun delete(fileSpec: String, roamingType: RoamingType): Boolean { + data.get(roamingType)?.remove(fileSpec) + return true } } diff --git a/platform/configuration-store-impl/testSrc/MockStreamProvider.kt b/platform/configuration-store-impl/testSrc/MockStreamProvider.kt index fe4c80e4c815..c7593602ff4d 100644 --- a/platform/configuration-store-impl/testSrc/MockStreamProvider.kt +++ b/platform/configuration-store-impl/testSrc/MockStreamProvider.kt @@ -11,17 +11,18 @@ class MockStreamProvider(private val dir: Path) : StreamProvider { dir.resolve(fileSpec).write(content, 0, size) } - override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> R): R { + override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> Unit): Boolean { val file = dir.resolve(fileSpec) try { - return file.inputStream().use(consumer) + file.inputStream().use(consumer) } catch (e: NoSuchFileException) { - return consumer(null) + consumer(null) } + return true } - override fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean) { + override fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean): Boolean { dir.resolve(path).directoryStreamIfExists({ filter(it.fileName.toString()) }) { for (file in it) { val attributes = file.basicAttributesIfExists() @@ -40,9 +41,12 @@ class MockStreamProvider(private val dir: Path) : StreamProvider { } } } + + return true } - override fun delete(fileSpec: String, roamingType: RoamingType) { + override fun delete(fileSpec: String, roamingType: RoamingType): Boolean { dir.resolve(fileSpec).delete() + return true } } diff --git a/platform/platform-impl/src/com/intellij/ui/layout/LayoutBuilder.kt b/platform/platform-impl/src/com/intellij/ui/layout/LayoutBuilder.kt index 3b62939d7f90..c86517fbd917 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/LayoutBuilder.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/LayoutBuilder.kt @@ -26,9 +26,7 @@ import javax.swing.ButtonGroup import javax.swing.JLabel class LayoutBuilder(val `$`: LayoutBuilderImpl, val buttonGroup: ButtonGroup? = null) { - inline fun row(label: String, init: Row.() -> Unit) { - row(label = Label(label), init = init) - } + inline fun row(label: String, init: Row.() -> Unit) = row(label = Label(label), init = init) inline fun row(label: JLabel? = null, separated: Boolean = false, init: Row.() -> Unit): Row { val row = `$`.newRow(label, buttonGroup, separated) diff --git a/platform/platform-impl/src/com/intellij/ui/layout/MigLayoutBuilder.kt b/platform/platform-impl/src/com/intellij/ui/layout/MigLayoutBuilder.kt index 2a8ba406fcea..692cfee2a0fc 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/MigLayoutBuilder.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/MigLayoutBuilder.kt @@ -81,6 +81,7 @@ internal class MigLayoutBuilder : LayoutBuilderImpl { } lc.noVisualPadding() + lc.hideMode = 3 container.layout = MigLayout(lc) @@ -209,6 +210,19 @@ private class MigLayoutRow(private val componentConstraints: MutableMap protected abstract val builder: LayoutBuilderImpl diff --git a/platform/projectModel-api/src/com/intellij/configurationStore/StreamProvider.kt b/platform/projectModel-api/src/com/intellij/configurationStore/StreamProvider.kt index eda9fd779588..e49ed1040431 100644 --- a/platform/projectModel-api/src/com/intellij/configurationStore/StreamProvider.kt +++ b/platform/projectModel-api/src/com/intellij/configurationStore/StreamProvider.kt @@ -24,6 +24,9 @@ interface StreamProvider { val enabled: Boolean get() = true + /** + * Called only on `write` + */ fun isApplicable(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT) = true /** @@ -33,14 +36,22 @@ interface StreamProvider { */ fun write(fileSpec: String, content: ByteArray, size: Int = content.size, roamingType: RoamingType = RoamingType.DEFAULT) - fun read(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT, consumer: (InputStream?) -> R): R + /** + * `true` if provider is applicable for file. + */ + fun read(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT, consumer: (InputStream?) -> Unit): Boolean - fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean) + /** + * `true` if provider is fully responsible and local sources must be not used. + */ + fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean): Boolean /** * Delete file or directory + * + * `true` if provider is fully responsible and local sources must be not used. */ - fun delete(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT) + fun delete(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT): Boolean } @TestOnly diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/SchemeManagerIprProvider.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/SchemeManagerIprProvider.kt index ce4929252d00..f40bb9d9caee 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/SchemeManagerIprProvider.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/SchemeManagerIprProvider.kt @@ -27,24 +27,26 @@ import java.io.InputStream class SchemeManagerIprProvider(private val subStateTagName: String) : StreamProvider { private val nameToData = ContainerUtil.newConcurrentMap() - override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> R): R { - val name = PathUtilRt.getFileName(fileSpec) - return nameToData.get(name)?.let(ByteArray::inputStream).let { consumer(it) } + override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> Unit): Boolean { + nameToData.get(PathUtilRt.getFileName(fileSpec))?.let(ByteArray::inputStream).let { consumer(it) } + return true } - override fun delete(fileSpec: String, roamingType: RoamingType) { + override fun delete(fileSpec: String, roamingType: RoamingType): Boolean { nameToData.remove(PathUtilRt.getFileName(fileSpec)) + return true } override fun processChildren(path: String, roamingType: RoamingType, filter: (String) -> Boolean, - processor: (String, InputStream, Boolean) -> Boolean) { + processor: (String, InputStream, Boolean) -> Boolean): Boolean { for ((name, data) in nameToData) { if (filter(name) && !data.inputStream().use { processor(name, it, false) }) { break } } + return true } override fun write(fileSpec: String, content: ByteArray, size: Int, roamingType: RoamingType) { diff --git a/plugins/settings-repository/src/IcsManager.kt b/plugins/settings-repository/src/IcsManager.kt index 8966318a5a8b..d88a8b02aae0 100644 --- a/plugins/settings-repository/src/IcsManager.kt +++ b/plugins/settings-repository/src/IcsManager.kt @@ -47,7 +47,7 @@ internal const val PLUGIN_NAME = "Settings Repository" internal val LOG = logger() -val icsManager by lazy(LazyThreadSafetyMode.NONE) { +internal val icsManager by lazy(LazyThreadSafetyMode.NONE) { ApplicationLoadListener.EP_NAME.findExtension(IcsApplicationLoadListener::class.java).icsManager } @@ -58,6 +58,7 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: val settings: IcsSettings val repositoryManager: RepositoryManager = GitRepositoryManager(credentialsStore, dir.resolve("repository")) + val readOnlySourcesManager = ReadOnlySourceManager(this, dir) init { settings = try { @@ -69,8 +70,6 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: } } - val readOnlySourcesManager = ReadOnlySourceManager(settings, dir) - val repositoryService: RepositoryService = GitRepositoryService() private val commitAlarm = SingleAlarm(Runnable { @@ -98,7 +97,11 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: } inner class ApplicationLevelProvider : IcsStreamProvider(null) { - override fun delete(fileSpec: String, roamingType: RoamingType) { + override fun delete(fileSpec: String, roamingType: RoamingType): Boolean { + if (!repositoryActive) { + return false + } + if (syncManager.writeAndDeleteProhibited) { throw IllegalStateException("Delete is prohibited now") } @@ -106,6 +109,8 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: if (repositoryManager.delete(toRepositoryPath(fileSpec, roamingType))) { scheduleCommit() } + + return true } } @@ -179,9 +184,9 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: override val enabled: Boolean get() = this@IcsManager.active - override fun isApplicable(fileSpec: String, roamingType: RoamingType): Boolean = enabled + override fun isApplicable(fileSpec: String, roamingType: RoamingType): Boolean = repositoryActive - override fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean) { + override fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean): Boolean { val fullPath = toRepositoryPath(path, roamingType, null) // first of all we must load read-only schemes - scheme could be overridden if bundled or read-only, so, such schemes must be loaded first @@ -189,7 +194,12 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: repository.processChildren(fullPath, filter) { name, input -> processor(name, input, true) } } + if (!repositoryActive) { + return false + } + repositoryManager.processChildren(fullPath, filter) { name, input -> processor(name, input, false) } + return true } override fun write(fileSpec: String, content: ByteArray, size: Int, roamingType: RoamingType) { @@ -206,9 +216,17 @@ class IcsManager @JvmOverloads constructor(dir: Path, val schemeManagerFactory: protected open fun isAutoCommit(fileSpec: String, roamingType: RoamingType) = true - override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> R): R = repositoryManager.read(toRepositoryPath(fileSpec, roamingType, projectId), consumer) + override fun read(fileSpec: String, roamingType: RoamingType, consumer: (InputStream?) -> Unit): Boolean { + if (!repositoryActive) { + return false + } - override fun delete(fileSpec: String, roamingType: RoamingType) { + repositoryManager.read(toRepositoryPath(fileSpec, roamingType, projectId), consumer) + return true + } + + override fun delete(fileSpec: String, roamingType: RoamingType): Boolean { + return false } } } @@ -218,6 +236,10 @@ class IcsApplicationLoadListener : ApplicationLoadListener { private set override fun beforeApplicationLoaded(application: Application, configPath: String) { + if (application.isUnitTestMode) { + return + } + val customPath = System.getProperty("ics.settingsRepository") val pluginSystemDir = if (customPath == null) Paths.get(configPath, "settingsRepository") else Paths.get(FileUtil.expandUserHome(customPath)) icsManager = IcsManager(pluginSystemDir) diff --git a/plugins/settings-repository/src/ReadOnlySourceManager.kt b/plugins/settings-repository/src/ReadOnlySourceManager.kt index f41094f5531c..ac131954bd1b 100644 --- a/plugins/settings-repository/src/ReadOnlySourceManager.kt +++ b/plugins/settings-repository/src/ReadOnlySourceManager.kt @@ -33,14 +33,14 @@ import org.jetbrains.settingsRepository.git.upstream import org.jetbrains.settingsRepository.git.use import java.nio.file.Path -class ReadOnlySourceManager(private val settings: IcsSettings, val rootDir: Path) { +class ReadOnlySourceManager(private val icsManager: IcsManager, val rootDir: Path) { private val repositoryList = object : AtomicClearableLazyValue>() { override fun compute(): List { - if (settings.readOnlySources.isEmpty()) { + if (icsManager.settings.readOnlySources.isEmpty()) { return emptyList() } - return settings.readOnlySources.mapSmartNotNull { source -> + return icsManager.settings.readOnlySources.mapSmartNotNull { source -> LOG.catchAndLog { if (!source.active) { return@mapSmartNotNull null @@ -64,7 +64,7 @@ class ReadOnlySourceManager(private val settings: IcsSettings, val rootDir: Path get() = repositoryList.value fun setSources(sources: List) { - settings.readOnlySources = sources + icsManager.settings.readOnlySources = sources repositoryList.drop() } diff --git a/plugins/settings-repository/src/autoSync.kt b/plugins/settings-repository/src/autoSync.kt index 5373f0ad42b7..1a9829f40bb5 100644 --- a/plugins/settings-repository/src/autoSync.kt +++ b/plugins/settings-repository/src/autoSync.kt @@ -152,7 +152,7 @@ internal class AutoSyncManager(private val icsManager: IcsManager) { if (!onAppExit && !app.isDisposeInProgress && updateResult != null && - updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult, app.messageBus)) { + updateStoragesFromStreamProvider(icsManager, app.stateStore as ComponentStoreImpl, updateResult, app.messageBus)) { // force to avoid saveAll & confirmation app.exit(true, true, true) } diff --git a/plugins/settings-repository/src/repositoryListEditor.kt b/plugins/settings-repository/src/repositoryListEditor.kt index 1b666bd65c72..2cbab16c2f1e 100644 --- a/plugins/settings-repository/src/repositoryListEditor.kt +++ b/plugins/settings-repository/src/repositoryListEditor.kt @@ -50,17 +50,18 @@ internal fun createRepositoryListEditor(): ConfigurableUi { } return object: ConfigurableUi { + private var noRepositoryRow: Row? = null + private var repositoryRow: Row? = null + override fun isModified(settings: IcsSettings) = editor.isModified override fun getComponent() = panel { - row("Repository:") { - if (editor.model.isEmpty) { - hint("Use File -> Settings Repository... to configure") - } - else { - editor.comboBox() - deleteButton() - } + noRepositoryRow = row("Repository:") { + hint("Use File -> Settings Repository... to configure") + } + repositoryRow = row("Repository:") { + editor.comboBox() + deleteButton() } } @@ -82,6 +83,9 @@ internal fun createRepositoryListEditor(): ConfigurableUi { editor.reset(list) editor.model.selectedItem = upstream + noRepositoryRow!!.visible = list.isEmpty() + repositoryRow!!.visible = list.isNotEmpty() + deleteButton.isEnabled = editor.model.selectedItem != null } } diff --git a/plugins/settings-repository/src/sync.kt b/plugins/settings-repository/src/sync.kt index 224b45dbd3e1..f12b13566acb 100644 --- a/plugins/settings-repository/src/sync.kt +++ b/plugins/settings-repository/src/sync.kt @@ -142,7 +142,7 @@ internal class SyncManager(private val icsManager: IcsManager, private val autoS if (updateResult != null) { val app = ApplicationManager.getApplication() - restartApplication = updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult!!, app.messageBus, + restartApplication = updateStoragesFromStreamProvider(icsManager, app.stateStore as ComponentStoreImpl, updateResult!!, app.messageBus, reloadAllSchemes = syncType == SyncType.OVERWRITE_LOCAL) } } @@ -158,30 +158,30 @@ internal class SyncManager(private val icsManager: IcsManager, private val autoS } return updateResult != null || isReadOnlySourcesChanged } -} -private fun updateCloudSchemes(indicator: ProgressIndicator): Boolean { - val changedRootDirs = icsManager.readOnlySourcesManager.update(indicator) ?: return false - val schemeManagersToReload = SmartList>() - icsManager.schemeManagerFactory.value.process { - val fileSpec = toRepositoryPath(it.fileSpec, it.roamingType) - if (changedRootDirs.contains(fileSpec)) { - schemeManagersToReload.add(it) - } - } - - if (schemeManagersToReload.isNotEmpty()) { - invokeAndWaitIfNeed { - for (schemeManager in schemeManagersToReload) { - schemeManager.reload() + private fun updateCloudSchemes(indicator: ProgressIndicator): Boolean { + val changedRootDirs = icsManager.readOnlySourcesManager.update(indicator) ?: return false + val schemeManagersToReload = SmartList>() + icsManager.schemeManagerFactory.value.process { + val fileSpec = toRepositoryPath(it.fileSpec, it.roamingType) + if (changedRootDirs.contains(fileSpec)) { + schemeManagersToReload.add(it) } } - } - return schemeManagersToReload.isNotEmpty() + if (schemeManagersToReload.isNotEmpty()) { + invokeAndWaitIfNeed { + for (schemeManager in schemeManagersToReload) { + schemeManager.reload() + } + } + } + + return schemeManagersToReload.isNotEmpty() + } } -internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateResult: UpdateResult, messageBus: MessageBus, reloadAllSchemes: Boolean = false): Boolean { +internal fun updateStoragesFromStreamProvider(icsManager: IcsManager, store: ComponentStoreImpl, updateResult: UpdateResult, messageBus: MessageBus, reloadAllSchemes: Boolean = false): Boolean { val (changed, deleted) = (store.storageManager as StateStorageManagerImpl).getCachedFileStorages(updateResult.changed, updateResult.deleted, ::toIdeaPath) val schemeManagersToReload = SmartList>()