@@ -42,17 +42,35 @@ import com.intellij.util.Alarm
42
42
import com.intellij.util.io.HttpRequests
43
43
import com.intellij.util.text.VersionComparatorUtil
44
44
import java.io.File
45
+ import java.io.PrintWriter
46
+ import java.io.StringWriter
45
47
import java.net.URLEncoder
46
48
import java.util.concurrent.TimeUnit
47
49
48
50
sealed class PluginUpdateStatus {
49
51
object LatestVersionInstalled : PluginUpdateStatus()
50
52
51
- class Update (val newVersion : String ,
52
- val descriptorToInstall : IdeaPluginDescriptor ,
53
+ class Update (val pluginDescriptor : IdeaPluginDescriptor ,
53
54
val hostToInstallFrom : String? ) : PluginUpdateStatus()
54
55
55
- class CheckFailed (val message : String ) : PluginUpdateStatus()
56
+ class CheckFailed (val message : String , val detail : String? = null ) : PluginUpdateStatus()
57
+
58
+ fun mergeWith (other : PluginUpdateStatus ): PluginUpdateStatus {
59
+ if (other is Update && (this is LatestVersionInstalled ||
60
+ (this is Update && VersionComparatorUtil .compare(other.pluginDescriptor.version,
61
+ pluginDescriptor.version) > 0 ))) {
62
+ return other
63
+ }
64
+ return this
65
+ }
66
+
67
+ companion object {
68
+ fun fromException (message : String , e : Exception ): PluginUpdateStatus {
69
+ val writer = StringWriter ()
70
+ e.printStackTrace(PrintWriter (writer))
71
+ return CheckFailed (message, writer.toString())
72
+ }
73
+ }
56
74
}
57
75
58
76
class KotlinPluginUpdater (val propertiesComponent : PropertiesComponent ) : Disposable {
@@ -69,8 +87,9 @@ class KotlinPluginUpdater(val propertiesComponent: PropertiesComponent) : Dispos
69
87
val lastUpdateTime = java.lang.Long .parseLong(propertiesComponent.getValue(PROPERTY_NAME , " 0" ))
70
88
if (lastUpdateTime == 0L || System .currentTimeMillis() - lastUpdateTime > TimeUnit .DAYS .toMillis(1 )) {
71
89
queueUpdateCheck { updateStatus ->
72
- if (updateStatus is PluginUpdateStatus .Update ) {
73
- notifyPluginUpdateAvailable(updateStatus)
90
+ when (updateStatus) {
91
+ is PluginUpdateStatus .Update -> notifyPluginUpdateAvailable(updateStatus)
92
+ is PluginUpdateStatus .CheckFailed -> LOG .info(" Plugin update check failed: ${updateStatus.message} , details: ${updateStatus.detail} " )
74
93
}
75
94
true
76
95
}
@@ -86,61 +105,37 @@ class KotlinPluginUpdater(val propertiesComponent: PropertiesComponent) : Dispos
86
105
}
87
106
}
88
107
108
+ fun runUpdateCheck (callback : (PluginUpdateStatus ) -> Boolean ) {
109
+ ApplicationManager .getApplication().executeOnPooledThread {
110
+ updateCheck(callback)
111
+ }
112
+ }
113
+
89
114
private fun updateCheck (callback : (PluginUpdateStatus ) -> Boolean ) {
115
+ var updateStatus: PluginUpdateStatus
90
116
try {
91
- var (mainRepoUpdateSuccess, latestVersionInRepository) = getPluginVersionFromMainRepository()
92
- var descriptorToInstall: IdeaPluginDescriptor ? = initPluginDescriptor(latestVersionInRepository)
93
- var hostToInstallFrom: String? = null
117
+ updateStatus = checkUpdatesInMainRepository()
94
118
95
119
for (host in RepositoryHelper .getPluginHosts().filterNotNull()) {
96
- val plugins = try {
97
- RepositoryHelper .loadPlugins(host, null )
98
- }
99
- catch (e: Exception ) {
100
- LOG .info(" Checking custom plugin repository $host failed" , e)
101
- continue
102
- }
103
-
104
- val kotlinPlugin = plugins.find { it.pluginId == KotlinPluginUtil .KOTLIN_PLUGIN_ID }
105
- if (kotlinPlugin != null && VersionComparatorUtil .compare(kotlinPlugin.version, latestVersionInRepository) > 0 ) {
106
- latestVersionInRepository = kotlinPlugin.version
107
- descriptorToInstall = kotlinPlugin
108
- hostToInstallFrom = host
109
- }
110
- }
111
-
112
- checkQueued = false
113
-
114
- if (mainRepoUpdateSuccess || latestVersionInRepository != null ) {
115
- recordSuccessfulUpdateCheck()
116
- if (latestVersionInRepository != null && VersionComparatorUtil .compare(latestVersionInRepository, KotlinPluginUtil .getPluginVersion()) > 0 ) {
117
- ApplicationManager .getApplication().invokeLater({
118
- callback(PluginUpdateStatus .Update (latestVersionInRepository!! , descriptorToInstall!! , hostToInstallFrom))
119
- }, ModalityState .any())
120
- }
121
- else {
122
- ApplicationManager .getApplication().invokeLater({
123
- callback(PluginUpdateStatus .LatestVersionInstalled )
124
- }, ModalityState .any())
125
- }
126
- }
127
- else {
128
- ApplicationManager .getApplication().invokeLater {
129
- if (callback(PluginUpdateStatus .CheckFailed (" Plugin not found in repository" ))) queueUpdateCheck(callback)
130
- }
120
+ val customUpdateStatus = checkUpdatesInCustomRepository(host)
121
+ updateStatus = updateStatus.mergeWith(customUpdateStatus)
131
122
}
132
123
}
133
124
catch (e: Exception ) {
134
- LOG .info(" Kotlin plugin update check failed" , e)
135
- checkQueued = false
136
- ApplicationManager .getApplication().invokeLater {
137
- if (callback(PluginUpdateStatus .CheckFailed (e.message ? : " Unknown error" ))) queueUpdateCheck(callback)
138
- }
125
+ updateStatus = PluginUpdateStatus .fromException(" Kotlin plugin update check failed" , e)
139
126
}
127
+
128
+ checkQueued = false
129
+
130
+ if (updateStatus !is PluginUpdateStatus .CheckFailed ) {
131
+ recordSuccessfulUpdateCheck()
132
+ }
133
+ ApplicationManager .getApplication().invokeLater({
134
+ callback(updateStatus)
135
+ }, ModalityState .any())
140
136
}
141
137
142
- private fun initPluginDescriptor (newVersion : String? ): IdeaPluginDescriptor ? {
143
- if (newVersion == null ) return null
138
+ private fun initPluginDescriptor (newVersion : String ): IdeaPluginDescriptor {
144
139
val originalPlugin = PluginManager .getPlugin(KotlinPluginUtil .KOTLIN_PLUGIN_ID )!!
145
140
return PluginNode (KotlinPluginUtil .KOTLIN_PLUGIN_ID ).apply {
146
141
version = newVersion
@@ -149,31 +144,48 @@ class KotlinPluginUpdater(val propertiesComponent: PropertiesComponent) : Dispos
149
144
}
150
145
}
151
146
152
- data class RepositoryCheckResult (val success : Boolean , val newVersion : String? )
153
-
154
- fun getPluginVersionFromMainRepository (): RepositoryCheckResult {
147
+ fun checkUpdatesInMainRepository (): PluginUpdateStatus {
155
148
val buildNumber = ApplicationInfo .getInstance().build.asString()
156
- val pluginVersion = KotlinPluginUtil .getPluginVersion()
149
+ val currentVersion = KotlinPluginUtil .getPluginVersion()
157
150
val os = URLEncoder .encode(SystemInfo .OS_NAME + " " + SystemInfo .OS_VERSION , CharsetToolkit .UTF8 )
158
151
val uid = UpdateChecker .getInstallationUID(propertiesComponent)
159
- val url = " https://plugins.jetbrains.com/plugins/list?pluginId=6954&build=$buildNumber &pluginVersion=$pluginVersion &os=$os &uuid=$uid "
152
+ val url = " https://plugins.jetbrains.com/plugins/list?pluginId=6954&build=$buildNumber &pluginVersion=$currentVersion &os=$os &uuid=$uid "
160
153
val responseDoc = HttpRequests .request(url).connect {
161
154
JDOMUtil .load(it.inputStream)
162
155
}
163
156
if (responseDoc.name != " plugin-repository" ) {
164
- LOG .info(" Unexpected plugin repository response: ${JDOMUtil .writeElement(responseDoc, " \n " )} " )
165
- return RepositoryCheckResult (false , null )
157
+ return PluginUpdateStatus .CheckFailed (" Unexpected plugin repository response" , JDOMUtil .writeElement(responseDoc, " \n " ))
166
158
}
167
159
if (responseDoc.children.isEmpty()) {
168
160
// No plugin version compatible with current IDEA build; don't retry updates
169
- return RepositoryCheckResult (true , null )
161
+ return PluginUpdateStatus .LatestVersionInstalled
162
+ }
163
+ val newVersion = responseDoc.getChild(" category" )?.getChild(" idea-plugin" )?.getChild(" version" )?.text
164
+ if (newVersion == null ) {
165
+ return PluginUpdateStatus .CheckFailed (" Couldn't find plugin version in repository response" , JDOMUtil .writeElement(responseDoc, " \n " ))
170
166
}
171
- val version = responseDoc.getChild(" category" )?.getChild(" idea-plugin" )?.getChild(" version" )?.text
172
- if (version == null ) {
173
- LOG .info(" Couldn't find plugin version in repository response: ${JDOMUtil .writeElement(responseDoc, " \n " )} " )
174
- return RepositoryCheckResult (false , null )
167
+ val pluginDescriptor = initPluginDescriptor(newVersion)
168
+ return updateIfNotLatest(pluginDescriptor, null )
169
+ }
170
+
171
+ private fun checkUpdatesInCustomRepository (host : String ): PluginUpdateStatus {
172
+ val plugins = try {
173
+ RepositoryHelper .loadPlugins(host, null )
175
174
}
176
- return RepositoryCheckResult (true , version)
175
+ catch (e: Exception ) {
176
+ return PluginUpdateStatus .fromException(" Checking custom plugin repository $host failed" , e)
177
+ }
178
+
179
+ val kotlinPlugin = plugins.find { it.pluginId == KotlinPluginUtil .KOTLIN_PLUGIN_ID } ? : return PluginUpdateStatus .LatestVersionInstalled
180
+ return updateIfNotLatest(kotlinPlugin, host)
181
+ }
182
+
183
+ private fun updateIfNotLatest (kotlinPlugin : IdeaPluginDescriptor , host : String? ): PluginUpdateStatus {
184
+ if (VersionComparatorUtil .compare(kotlinPlugin.version, KotlinPluginUtil .getPluginVersion()) <= 0 ) {
185
+ return PluginUpdateStatus .LatestVersionInstalled
186
+ }
187
+
188
+ return PluginUpdateStatus .Update (kotlinPlugin, host)
177
189
}
178
190
179
191
private fun recordSuccessfulUpdateCheck () {
@@ -184,7 +196,7 @@ class KotlinPluginUpdater(val propertiesComponent: PropertiesComponent) : Dispos
184
196
private fun notifyPluginUpdateAvailable (update : PluginUpdateStatus .Update ) {
185
197
val notification = notificationGroup.createNotification(
186
198
" Kotlin" ,
187
- " A new version ${update.newVersion } of the Kotlin plugin is available. <b><a href=\" #\" >Install</a></b>" ,
199
+ " A new version ${update.pluginDescriptor.version } of the Kotlin plugin is available. <b><a href=\" #\" >Install</a></b>" ,
188
200
NotificationType .INFORMATION ) { notification, event ->
189
201
notification.expire()
190
202
installPluginUpdate(update) {
@@ -197,7 +209,7 @@ class KotlinPluginUpdater(val propertiesComponent: PropertiesComponent) : Dispos
197
209
198
210
fun installPluginUpdate (update : PluginUpdateStatus .Update ,
199
211
cancelCallback : () -> Unit = {}) {
200
- val descriptor = update.descriptorToInstall
212
+ val descriptor = update.pluginDescriptor
201
213
val pluginDownloader = PluginDownloader .createDownloader(descriptor, update.hostToInstallFrom, null )
202
214
ProgressManager .getInstance().run (object : Task .Backgroundable (null , " Downloading plugins" , true ) {
203
215
override fun run (indicator : ProgressIndicator ) {
0 commit comments