User: joe Date: 12 Nov 26 23:38 Revision: c83e78f9365bc2a0a2844ca45bf752f4f07f9cc5 Summary: Revert "Replace code using internal API in PluginUpdater with the PluginUpdateCheckService API introduced in 2026.1" This reverts commit f731810dcfe8eef5a723e818c0380d756820444d. TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10737&personal=false Index: src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt =================================================================== --- src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt (revision ff47a747c3bb3a57e6d3c913fc93ec9783414c3d) +++ src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt (revision c83e78f9365bc2a0a2844ca45bf752f4f07f9cc5) @@ -22,8 +22,6 @@ import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.ui.DialogWrapper -import com.intellij.openapi.updateSettings.PluginUpdateInfo -import com.intellij.openapi.updateSettings.impl.PluginDownloader import com.intellij.openapi.updateSettings.impl.UpdateSettings import com.intellij.ui.AnimatedIcon import com.intellij.ui.dsl.builder.Cell @@ -50,29 +48,24 @@ saveSettings() updateCheckInProgressIcon.component.isVisible = true resetUpdateStatus() - PluginUpdater.runUpdateCheck { result -> + PluginUpdater.runUpdateCheck { pluginUpdateStatus -> updateCheckInProgressIcon.component.isVisible = false - updateStatusLabel.component.text = result.fold( - { info -> - when (info) { - is PluginUpdateInfo.NoUpdate -> + updateStatusLabel.component.text = when (pluginUpdateStatus) { + is PluginUpdateStatus.LatestVersionInstalled -> - "You have the latest version of the plugin (${PluginUtil.pluginVersion}) installed." + "You have the latest version of the plugin (${PluginUtil.pluginVersion}) installed." - is PluginUpdateInfo.UpdateAvailable -> { - update = info.update + is PluginUpdateStatus.Update -> { + update = pluginUpdateStatus - installButton.component.isVisible = true + installButton.component.isVisible = true - "A new version (${info.update.pluginVersion}) is available" + "A new version (${pluginUpdateStatus.pluginDescriptor.version}) is available" - } + } - is PluginUpdateInfo.CheckFailed -> - "Update check failed: " + info.errors.entries.joinToString("; ") { (host, e) -> - "${host ?: "Marketplace"}: ${e.message}" + else -> // CheckFailed + "Update check failed: " + (pluginUpdateStatus as PluginUpdateStatus.CheckFailed).message - } + } + + false - } + } - }, - { e -> "Update check failed: ${e.message}" }, - ) - } + } - } updateCheckInProgressIcon = icon(AnimatedIcon.Default.INSTANCE) installButton = button("Install Update") { update?.let { update -> @@ -89,7 +82,7 @@ updateStatusLabel = label("") } } - private var update: PluginDownloader? = null + private var update: PluginUpdateStatus.Update? = null private var initialSelectedChannel: Int = 0 init { Index: src/main/kotlin/update/PluginUpdateStatus.kt =================================================================== --- src/main/kotlin/update/PluginUpdateStatus.kt (revision c83e78f9365bc2a0a2844ca45bf752f4f07f9cc5) +++ src/main/kotlin/update/PluginUpdateStatus.kt (revision c83e78f9365bc2a0a2844ca45bf752f4f07f9cc5) @@ -0,0 +1,49 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2025 minecraft-dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, version 3.0 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.demonwav.mcdev.update + +import com.intellij.ide.plugins.IdeaPluginDescriptor +import com.intellij.util.text.VersionComparatorUtil + +sealed class PluginUpdateStatus : Comparable { + + protected abstract fun getVersionString(): String? + + fun mergeWith(other: PluginUpdateStatus): PluginUpdateStatus = maxOf(this, other) + + override fun compareTo(other: PluginUpdateStatus): Int { + val thisVersion = this.getVersionString() ?: return 1 + val otherVersion = other.getVersionString() ?: return -1 + return VersionComparatorUtil.compare(thisVersion, otherVersion) + } + + object LatestVersionInstalled : PluginUpdateStatus() { + override fun getVersionString(): String = PluginUtil.pluginVersion + } + + class Update(val pluginDescriptor: IdeaPluginDescriptor, val hostToInstallFrom: String?) : PluginUpdateStatus() { + override fun getVersionString(): String? = this.pluginDescriptor.version + } + + class CheckFailed(val message: String) : PluginUpdateStatus() { + override fun getVersionString(): String? = null + } +} Index: src/main/kotlin/update/PluginUpdater.kt =================================================================== --- src/main/kotlin/update/PluginUpdater.kt (revision ff47a747c3bb3a57e6d3c913fc93ec9783414c3d) +++ src/main/kotlin/update/PluginUpdater.kt (revision c83e78f9365bc2a0a2844ca45bf752f4f07f9cc5) @@ -21,27 +21,113 @@ package com.demonwav.mcdev.update import com.demonwav.mcdev.util.McdevReflection +import com.demonwav.mcdev.util.forEachNotNull import com.demonwav.mcdev.util.invokeLater +import com.intellij.ide.plugins.IdeaPluginDescriptor +import com.intellij.ide.plugins.PluginManagerCore import com.intellij.ide.plugins.PluginManagerMain +import com.intellij.ide.plugins.PluginNode +import com.intellij.ide.plugins.RepositoryHelper +import com.intellij.openapi.application.ApplicationInfo import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ModalityState import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task -import com.intellij.openapi.updateSettings.PluginUpdateCheckService -import com.intellij.openapi.updateSettings.PluginUpdateInfo import com.intellij.openapi.updateSettings.impl.PluginDownloader +import com.intellij.openapi.util.JDOMUtil +import com.intellij.openapi.util.SystemInfo +import com.intellij.util.io.HttpRequests import java.io.IOException +import java.net.URLEncoder +import org.jdom.Element +import org.jdom.JDOMException object PluginUpdater { - fun runUpdateCheck(callback: (Result) -> Unit) { - ApplicationManager.getApplication().executeOnPooledThread { - val result = runCatching { PluginUpdateCheckService.getInstance().getPluginUpdate(PluginUtil.PLUGIN_ID) } - ApplicationManager.getApplication().invokeLater({ callback(result) }, ModalityState.any()) + fun runUpdateCheck(callback: (PluginUpdateStatus) -> Boolean) { + ApplicationManager.getApplication().executeOnPooledThread { updateCheck(callback) } - } + } + + private fun updateCheck(callback: (PluginUpdateStatus) -> Boolean) { + var updateStatus: PluginUpdateStatus + try { + updateStatus = checkUpdatesInMainRepo() + + RepositoryHelper.getPluginHosts() + .forEachNotNull { updateStatus = updateStatus.mergeWith(checkUpdatesInCustomRepo(it)) } + + val finalUpdate = updateStatus + ApplicationManager.getApplication().invokeLater({ callback(finalUpdate) }, ModalityState.any()) + } catch (_: Exception) { + PluginUpdateStatus.CheckFailed("Minecraft Development plugin update check failed") - } + } + } - fun installPluginUpdate(downloader: PluginDownloader) { + private fun checkUpdatesInMainRepo(): PluginUpdateStatus { + val buildNumber = ApplicationInfo.getInstance().build.asString() + val currentVersion = PluginUtil.pluginVersion + val os = URLEncoder.encode(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION, Charsets.UTF_8) + val url = + "https://plugins.jetbrains.com/plugins/list?pluginId=8327&build=" + + "$buildNumber&pluginVersion=$currentVersion&os=$os" + + val responseDoc = HttpRequests.request(url).connect { request -> + try { + return@connect JDOMUtil.load(request.inputStream) + } catch (e: JDOMException) { + e.printStackTrace() + } + + null + } ?: return PluginUpdateStatus.CheckFailed("Unexpected plugin repository response") + + if (responseDoc.name != "plugin-repository") { + return PluginUpdateStatus.CheckFailed("Unexpected plugin repository response") + } + if (responseDoc.children.isEmpty()) { + return PluginUpdateStatus.LatestVersionInstalled + } + + val newVersion = responseDoc.getChild("category")?.getChild("idea-plugin")?.getChild("version")?.text + ?: return PluginUpdateStatus.CheckFailed("Couldn't find plugin version in repository response") + + val plugin = PluginManagerCore.getPlugin(PluginUtil.PLUGIN_ID)!! + val pluginNode = PluginNode(PluginUtil.PLUGIN_ID) + pluginNode.version = newVersion + pluginNode.name = plugin.name + pluginNode.description = plugin.description + + if (pluginNode.version == PluginUtil.pluginVersion) { + return PluginUpdateStatus.LatestVersionInstalled + } + + return PluginUpdateStatus.Update(pluginNode, null) + } + + private fun checkUpdatesInCustomRepo(host: String): PluginUpdateStatus { + val plugins = try { + RepositoryHelper.loadPluginModels(host, null, null) + .map { it.getDescriptor() } + } catch (_: IOException) { + return PluginUpdateStatus.CheckFailed("Checking custom plugin repository $host failed") + } + + val minecraftPlugin = plugins.firstOrNull { plugin -> plugin.pluginId == PluginUtil.PLUGIN_ID } + ?: return PluginUpdateStatus.LatestVersionInstalled + + return updateIfNotLatest(minecraftPlugin, host) + } + + private fun updateIfNotLatest(plugin: IdeaPluginDescriptor, host: String): PluginUpdateStatus { + if (plugin.version == PluginUtil.pluginVersion) { + return PluginUpdateStatus.LatestVersionInstalled + } + return PluginUpdateStatus.Update(plugin, host) + } + + fun installPluginUpdate(update: PluginUpdateStatus.Update) { + val plugin = update.pluginDescriptor + val downloader = PluginDownloader.createDownloader(plugin, update.hostToInstallFrom, null) ProgressManager.getInstance().run( object : Task.Backgroundable(null, "Downloading plugin", true) { override fun run(indicator: ProgressIndicator) {