[platform] on checking for updates, suggests the same baseline build (always)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Fri, 11 Nov 2016 19:58:10 +0000 (20:58 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Fri, 11 Nov 2016 19:58:38 +0000 (20:58 +0100)
The code which selected the desired build was failing in cases when builds were distributed across different channels. The commit makes the build selection independent of channel layout.

platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateStrategy.kt
platform/platform-tests/testSrc/com/intellij/ide/updates/UpdateStrategyTest.kt

index 4e07c91f15d78c21ac49ac3698a280d5384e5c9e..52b15f462ac3c123bf3159fca3210539ca270f31 100644 (file)
@@ -17,12 +17,15 @@ package com.intellij.openapi.updateSettings.impl
 
 import com.intellij.openapi.updateSettings.UpdateStrategyCustomization
 import com.intellij.openapi.util.BuildNumber
+import java.util.*
 
 class UpdateStrategy(private val currentBuild: BuildNumber, private val updates: UpdatesInfo, private val settings: UserUpdateSettings) {
   enum class State {
     LOADED, CONNECTION_ERROR, NOTHING_LOADED
   }
 
+  private val lineage = currentBuild.baselineVersion
+
   fun checkForUpdates(): CheckForUpdateResult {
     val product = updates[currentBuild.productCode]
     if (product == null || product.channels.isEmpty()) {
@@ -33,12 +36,10 @@ class UpdateStrategy(private val currentBuild: BuildNumber, private val updates:
     val ignoredBuilds = settings.ignoredBuildNumbers.toSet()
 
     val result = product.channels.asSequence()
-        .filter { ch -> ch.status >= selectedChannel }  // filter out inapplicable channels
-        .sortedBy { ch -> ch.status }  // sort by stability, asc
-        .map { ch -> ch.builds.asSequence().filter { build -> isApplicable(build, ignoredBuilds) } to ch }  // filter out inapplicable builds
-        .map { p -> maxBuild(p.first) to p.second }  // max build in a channel, preferring same baseline
-        .filter { p -> p.first != null }
-        .maxBy { p -> p.first!!.number }
+      .filter { ch -> ch.status >= selectedChannel }                                      // filters out inapplicable channels
+      .flatMap { ch -> ch.builds.asSequence().map { build -> build to ch } }              // maps into a sequence of <build, channel> pairs
+      .filter { p -> isApplicable(p.first, ignoredBuilds) }                               // filters out inapplicable builds
+      .maxWith(Comparator { p1, p2 -> compareBuilds(p1.first.number, p2.first.number) })  // a build with the max number, preferring the same baseline
 
     return CheckForUpdateResult(result?.first, result?.second)
   }
@@ -48,8 +49,10 @@ class UpdateStrategy(private val currentBuild: BuildNumber, private val updates:
       candidate.number.asStringWithoutProductCode() !in ignoredBuilds &&
       candidate.target?.inRange(currentBuild) ?: true
 
-  private fun maxBuild(builds: Sequence<BuildInfo>) =
-      builds.filter { it.number.baselineVersion == currentBuild.baselineVersion }.maxBy { it.number } ?: builds.maxBy { it.number }
+  private fun compareBuilds(n1: BuildNumber, n2: BuildNumber) =
+      if (n1.baselineVersion == lineage && n2.baselineVersion != lineage) 1
+      else if (n2.baselineVersion == lineage && n1.baselineVersion != lineage) -1
+      else n1.compareTo(n2)
 
   //<editor-fold desc="Deprecated stuff.">
 
index d545946a496ba9885c1dae79ef86a076debc4a2e..a3c7e4764dde9ecc3fdecf3b1eed79b37d417043 100644 (file)
@@ -137,8 +137,12 @@ class UpdateStrategyTest {
     assertEquals("bug fix", check("IU-163.50", ChannelStatus.RELEASE, channels).newBuild?.message)
   }
 
-  @Test fun `updates from the same baseline are preferred`() {
-    val result = check("IU-143.2287", ChannelStatus.RELEASE, """
+  @Test fun `updates from the same baseline are preferred (unified channels)`() {
+    val result = check("IU-143.2287", ChannelStatus.EAP, """
+      <channel id="IDEA_EAP" status="eap" licensing="eap">
+        <build number="143.2330" version="15.0.5 EAP"/>
+        <build number="145.600" version="2016.1.2 EAP"/>
+      </channel>
       <channel id="IDEA_Release" status="release" licensing="release">
         <build number="143.2332" version="15.0.5"/>
         <build number="145.597" version="2016.1.1"/>
@@ -146,6 +150,23 @@ class UpdateStrategyTest {
     assertBuild("143.2332", result.newBuild)
   }
 
+  @Test fun `updates from the same baseline are preferred (per-release channels)`() {
+    val result = check("IU-143.2287", ChannelStatus.EAP, """
+      <channel id="IDEA_143_EAP" status="eap" licensing="eap">
+        <build number="143.2330" version="15.0.5 EAP"/>
+      </channel>
+      <channel id="IDEA_143_Release" status="release" licensing="release">
+        <build number="143.2332" version="15.0.5"/>
+      </channel>
+      <channel id="IDEA_145_EAP" status="eap" licensing="eap">
+        <build number="145.600" version="2016.1.2 EAP"/>
+      </channel>
+      <channel id="IDEA_Release_145" status="release" licensing="release">
+        <build number="145.597" version="2016.1.1"/>
+      </channel>""")
+    assertBuild("143.2332", result.newBuild)
+  }
+
   @Test fun `cross-baseline updates are perfectly legal`() {
     val result = check("IU-143.2332", ChannelStatus.EAP, """
       <channel id="IDEA_Release" status="release" licensing="release">