diff --git a/plugins/settings-sync/resources/META-INF/plugin.xml b/plugins/settings-sync/resources/META-INF/plugin.xml index 35ed4be970f1..2a5601e572fb 100644 --- a/plugins/settings-sync/resources/META-INF/plugin.xml +++ b/plugins/settings-sync/resources/META-INF/plugin.xml @@ -29,6 +29,7 @@ + diff --git a/plugins/settings-sync/resources/messages/SettingsSyncBundle.properties b/plugins/settings-sync/resources/messages/SettingsSyncBundle.properties index 042cb52608d3..267596a706c4 100644 --- a/plugins/settings-sync/resources/messages/SettingsSyncBundle.properties +++ b/plugins/settings-sync/resources/messages/SettingsSyncBundle.properties @@ -7,6 +7,10 @@ notification.title.update.error=Couldn't get settings from server notification.title.update.no.such.file=No settings file on the server progress.title.updating.settings.from.server=Updating settings from server... notification.title.apply.error=Couldn't apply settings +progress.title.downloading.settings.from.server=Downloading settings from server... +notification.content.downloaded.latest.settings.successfully=Downloaded the latest settings as a zip file +notification.title.download.zip.file.failed=Failed to download zip file +notification.content.check.log.file.for.errors=Check the log file for errors title.settings.sync=Settings Sync configurable.what.to.sync.label=Configure what to sync: @@ -61,4 +65,4 @@ settings.sync.info.message=Sync UI, Code and System settings, Keymaps, Plugins, sync.status=Sync sync.status.enabled=enabled. sync.status.disabled=disabled. -sync.status.login.message=Login to enable settings sync \ No newline at end of file +sync.status.login.message=Login to enable settings sync diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/CloudConfigServerCommunicator.kt b/plugins/settings-sync/src/com/intellij/settingsSync/CloudConfigServerCommunicator.kt index dac192f7ec86..492ce0a8b61a 100644 --- a/plugins/settings-sync/src/com/intellij/settingsSync/CloudConfigServerCommunicator.kt +++ b/plugins/settings-sync/src/com/intellij/settingsSync/CloudConfigServerCommunicator.kt @@ -11,8 +11,10 @@ import com.jetbrains.cloudconfig.ETagStorage import com.jetbrains.cloudconfig.HeaderStorage import com.jetbrains.cloudconfig.auth.JbaTokenAuthProvider import com.jetbrains.cloudconfig.exception.InvalidVersionIdException +import java.io.File import java.io.IOException import java.io.InputStream +import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock @@ -156,15 +158,34 @@ private const val TIMEOUT = 10000 } } - private inner class VersionContext : HeaderStorage { - private val contextVersionMap = mutableMapOf() - private val lock = ReentrantLock() + fun downloadSnapshot(): File? { + val stream = receiveSnapshotFile() + if (stream == null) { + LOG.info("$SETTINGS_SYNC_SNAPSHOT_ZIP not found on the server") + return null + } - override fun get(path: String): String? { - return contextVersionMap[path] + try { + val currentDate = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(Date()) + val tempFile = FileUtil.createTempFile("settings.sync.snapshot.$currentDate.zip", null) + FileUtil.writeToFile(tempFile, stream.readAllBytes()) + return tempFile + } + catch (e: Throwable) { + LOG.error(e) + return null + } } - override fun store(path: String, value: String) { + private inner class VersionContext : HeaderStorage { + private val contextVersionMap = mutableMapOf() + private val lock = ReentrantLock() + + override fun get(path: String): String? { + return contextVersionMap[path] + } + + override fun store(path: String, value: String) { contextVersionMap[path] = path } diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/DownloadSnapshotAction.kt b/plugins/settings-sync/src/com/intellij/settingsSync/DownloadSnapshotAction.kt new file mode 100644 index 000000000000..d53d3bb51c0a --- /dev/null +++ b/plugins/settings-sync/src/com/intellij/settingsSync/DownloadSnapshotAction.kt @@ -0,0 +1,46 @@ +package com.intellij.settingsSync + +import com.intellij.ide.actions.RevealFileAction +import com.intellij.ide.actions.ShowLogAction +import com.intellij.notification.NotificationAction +import com.intellij.notification.NotificationGroupManager +import com.intellij.notification.NotificationType +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.components.service +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.Task +import com.intellij.openapi.project.DumbAwareAction + +class DownloadSnapshotAction : DumbAwareAction() { + override fun actionPerformed(e: AnActionEvent) { + val remoteCommunicator = service().getRemoteCommunicator() as CloudConfigServerCommunicator + object: Task.Backgroundable(e.project, SettingsSyncBundle.message("progress.title.downloading.settings.from.server"), false) { + override fun run(indicator: ProgressIndicator) { + val zipFile = remoteCommunicator.downloadSnapshot() + if (zipFile != null) { + @Suppress("DialogTitleCapitalization") + NotificationGroupManager.getInstance().getNotificationGroup(NOTIFICATION_GROUP) + .createNotification("", SettingsSyncBundle.message("notification.content.downloaded.latest.settings.successfully"), + NotificationType.INFORMATION) + .addAction(NotificationAction.createSimpleExpiring(RevealFileAction.getActionName()) { + RevealFileAction.openFile(zipFile) + }) + .notify(e.project) + + } + else { + NotificationGroupManager.getInstance().getNotificationGroup(NOTIFICATION_GROUP) + .createNotification(SettingsSyncBundle.message("notification.title.download.zip.file.failed"), + SettingsSyncBundle.message("notification.content.check.log.file.for.errors"), NotificationType.ERROR) + .addAction(ShowLogAction.notificationAction()) + .notify(e.project) + } + } + }.queue() + } + + override fun update(e: AnActionEvent) { + e.presentation.isEnabledAndVisible = isSettingsSyncEnabled() && + service().getRemoteCommunicator() is CloudConfigServerCommunicator + } +} \ No newline at end of file diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncMain.kt b/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncMain.kt index 83851063d07e..fdab7cc97785 100644 --- a/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncMain.kt +++ b/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncMain.kt @@ -27,6 +27,8 @@ internal class SettingsSyncFacade { ApplicationManager.getApplication().messageBus.syncPublisher(SETTINGS_CHANGED_TOPIC).settingChanged(SyncSettingsEvent.PushRequest()) } + internal fun getRemoteCommunicator(): SettingsSyncRemoteCommunicator = getMain().controls.remoteCommunicator + private fun getMain(): SettingsSyncMain { return ApplicationLoadListener.EP_NAME.findExtensionOrFail(SettingsSyncMain::class.java) } @@ -72,10 +74,11 @@ internal class SettingsSyncMain : ApplicationLoadListener { componentStore.storageManager.addStreamProvider(streamProvider) - return SettingsSyncControls(updateChecker, bridge) + return SettingsSyncControls(updateChecker, bridge, remoteCommunicator) } } internal class SettingsSyncControls(val updateChecker: SettingsSyncUpdateChecker, - val bridge: SettingsSyncBridge) + val bridge: SettingsSyncBridge, + val remoteCommunicator: SettingsSyncRemoteCommunicator) } \ No newline at end of file