settings-sync: allow downloading the latest settings snapshot from the server

GitOrigin-RevId: 3bce05b40b714e02ad21af4f0dd6d9401eef8118
This commit is contained in:
Kirill Likhodedov
2022-01-03 16:46:17 +00:00
committed by intellij-monorepo-bot
parent f60d448dba
commit e001ff24b5
5 changed files with 84 additions and 9 deletions
@@ -29,6 +29,7 @@
<group id="SettingsSync">
<action class="com.intellij.settingsSync.ManualUpdateAction" id="settingsSync.manualUpdate" icon="AllIcons.Chooser.Bottom"/>
<action class="com.intellij.settingsSync.ManualPushAction" id="settingsSync.manualPush" icon="AllIcons.Chooser.Top" />
<action class="com.intellij.settingsSync.DownloadSnapshotAction" id="settingsSync.downloadSnapshot" icon="AllIcons.Actions.Download"/>
<add-to-group group-id="NavBarToolBar" anchor="last"/>
<add-to-group group-id="MainToolBar" anchor="last"/>
@@ -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
sync.status.login.message=Login to enable settings sync
@@ -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<String, String>()
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<String, String>()
private val lock = ReentrantLock()
override fun get(path: String): String? {
return contextVersionMap[path]
}
override fun store(path: String, value: String) {
contextVersionMap[path] = path
}
@@ -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<SettingsSyncFacade>().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<SettingsSyncFacade>().getRemoteCommunicator() is CloudConfigServerCommunicator
}
}
@@ -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)
}