From e2e90900a2a5f30cb0e6bbf12079624c11b9051f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 11 Feb 2025 15:34:14 +0100 Subject: [PATCH] fix ICS sync on app exit GitOrigin-RevId: 38fb384ca65c7b526ddc7a85fc7c4555c0e624d1 --- plugins/settings-repository/src/IcsBundle.kt | 14 +++-- plugins/settings-repository/src/autoSync.kt | 57 +++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/plugins/settings-repository/src/IcsBundle.kt b/plugins/settings-repository/src/IcsBundle.kt index ac1fd330a59f..22cc6dbb0746 100644 --- a/plugins/settings-repository/src/IcsBundle.kt +++ b/plugins/settings-repository/src/IcsBundle.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.settingsRepository import com.intellij.DynamicBundle @@ -7,17 +7,15 @@ import org.jetbrains.annotations.PropertyKey internal const val BUNDLE = "messages.IcsBundle" -object IcsBundle : DynamicBundle(BUNDLE) { +internal object IcsBundle { + private val bundle = DynamicBundle(IcsBundle::class.java, BUNDLE) + @Nls @JvmStatic - fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params) - - @JvmStatic - fun messagePointer(@PropertyKey(resourceBundle = BUNDLE) key: String, - vararg params: Any): java.util.function.Supplier = getLazyMessage(key, *params) + fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = bundle.getMessage(key, *params) } @Nls -fun icsMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String { +internal fun icsMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String { return IcsBundle.message(key, *params) } diff --git a/plugins/settings-repository/src/autoSync.kt b/plugins/settings-repository/src/autoSync.kt index cf28746edb2e..5232f82bcdac 100644 --- a/plugins/settings-repository/src/autoSync.kt +++ b/plugins/settings-repository/src/autoSync.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.settingsRepository import com.intellij.configurationStore.ComponentStoreImpl @@ -8,9 +8,11 @@ import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement import com.intellij.openapi.components.ComponentManagerEx import com.intellij.openapi.components.impl.stores.stateStore -import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.runBlockingMaybeCancellable +import com.intellij.platform.ide.progress.ModalTaskOwner +import com.intellij.platform.ide.progress.runWithModalProgressBlocking import com.intellij.platform.util.progress.reportRawProgress +import com.intellij.util.ui.EDT import kotlinx.coroutines.* internal class AutoSyncManager(private val icsManager: IcsManager) { @@ -45,27 +47,15 @@ internal class AutoSyncManager(private val icsManager: IcsManager) { if (onAppExit) { // called on final confirmed exit - no need to restore enabled state enabled = false - catchAndLog { - runBlockingMaybeCancellable { - icsManager.runInAutoCommitDisabledMode { - val repositoryManager = icsManager.repositoryManager - val hasUpstream = repositoryManager.hasUpstream() - if (hasUpstream && !repositoryManager.canCommit()) { - LOG.warn("Auto sync skipped: repository is not committable") - return@runInAutoCommitDisabledMode - } - - // on app exit fetch and push only if there are commits to push - // if no upstream - just update cloud schemes - if (hasUpstream && !repositoryManager.commit() && repositoryManager.getAheadCommitsCount() == 0 && icsManager.readOnlySourcesManager.repositories.isEmpty()) { - return@runInAutoCommitDisabledMode - } - - // use explicit progress task to sync on app exit to make it clear why app is not exited immediately - icsManager.syncManager.sync(SyncType.MERGE, onAppExit = true) - } + if (EDT.isCurrentThreadEdt()) { + @Suppress("DialogTitleCapitalization") + runWithModalProgressBlocking(ModalTaskOwner.guess(), IcsBundle.message("task.sync.title")) { + doSyncOnAppExit() } } + runBlockingMaybeCancellable { + doSyncOnAppExit() + } return } else if (ApplicationManager.getApplication().isDisposed) { @@ -82,6 +72,26 @@ internal class AutoSyncManager(private val icsManager: IcsManager) { } } + private suspend fun doSyncOnAppExit() { + icsManager.runInAutoCommitDisabledMode { + val repositoryManager = icsManager.repositoryManager + val hasUpstream = repositoryManager.hasUpstream() + if (hasUpstream && !repositoryManager.canCommit()) { + LOG.warn("Auto sync skipped: repository is not committable") + return@runInAutoCommitDisabledMode + } + + // on app exit fetch and push only if there are commits to push + // if no upstream - just update cloud schemes + if (hasUpstream && !repositoryManager.commit() && repositoryManager.getAheadCommitsCount() == 0 && icsManager.readOnlySourcesManager.repositories.isEmpty()) { + return@runInAutoCommitDisabledMode + } + + // use an explicit progress task to sync on app exit to make it clear why the app is not exited immediately + icsManager.syncManager.sync(SyncType.MERGE, onAppExit = true) + } + } + private suspend fun doSync() { val app = ApplicationManager.getApplication() val repositoryManager = icsManager.repositoryManager @@ -122,9 +132,8 @@ internal inline fun catchAndLog(asWarning: Boolean = false, runnable: () -> Unit try { runnable() } - catch (_: ProcessCanceledException) { - } - catch (_: CancellationException) { + catch (e: CancellationException) { + throw e } catch (e: Throwable) { if (asWarning || e is AuthenticationException || e is NoRemoteRepositoryException) {