diff --git a/modules/core/shared/src/main/scala/scaladex/core/model/SemanticVersion.scala b/modules/core/shared/src/main/scala/scaladex/core/model/SemanticVersion.scala index 4fb0a1602..b261a6a92 100644 --- a/modules/core/shared/src/main/scala/scaladex/core/model/SemanticVersion.scala +++ b/modules/core/shared/src/main/scala/scaladex/core/model/SemanticVersion.scala @@ -103,6 +103,14 @@ object SemanticVersion { ) } + val PreferRelease: Ordering[SemanticVersion] = Ordering.by(_.isRelease) + + /** + * Often we will prefer the latest release, but if there is no full release, we will accept the most recent + * pre-release. + */ + val PreferReleasesThenHighest: Ordering[SemanticVersion] = PreferRelease.orElse(ordering) + private def MajorP[A: P]: P[Int] = Number // http://semver.org/#spec-item-10 diff --git a/modules/core/shared/src/test/scala/scaladex/core/model/SemanticVersionTests.scala b/modules/core/shared/src/test/scala/scaladex/core/model/SemanticVersionTests.scala index 9abba45d1..dbd8880fb 100644 --- a/modules/core/shared/src/test/scala/scaladex/core/model/SemanticVersionTests.scala +++ b/modules/core/shared/src/test/scala/scaladex/core/model/SemanticVersionTests.scala @@ -3,6 +3,8 @@ package scaladex.core.model import org.scalatest.funspec.AsyncFunSpec import org.scalatest.matchers.should.Matchers import org.scalatest.prop.TableDrivenPropertyChecks +import scaladex.core.model.SemanticVersion.PreferReleasesThenHighest +import scaladex.core.test.Values._ class SemanticVersionTests extends AsyncFunSpec with Matchers with TableDrivenPropertyChecks { it("should parse any version") { @@ -39,6 +41,12 @@ class SemanticVersionTests extends AsyncFunSpec with Matchers with TableDrivenPr forAll(inputs)((lower, higher) => lower shouldBe <(higher)) } + it("should allow us to prefer releases over pre-releases") { + val versions = Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`) + versions.max shouldBe `7.2.0-PREVIEW.1` + versions.max(PreferReleasesThenHighest) shouldBe `7.1.0` + } + it("should encode and decode any version") { val inputs = Table[SemanticVersion]( "semanticVersion", diff --git a/modules/core/shared/src/test/scala/scaladex/core/test/Values.scala b/modules/core/shared/src/test/scala/scaladex/core/test/Values.scala index eb8d18d44..08163b2cd 100644 --- a/modules/core/shared/src/test/scala/scaladex/core/test/Values.scala +++ b/modules/core/shared/src/test/scala/scaladex/core/test/Values.scala @@ -36,8 +36,8 @@ object Values { val `2.7.0` = PatchVersion(2, 7, 0) val `7.0.0` = PatchVersion(7, 0, 0) val `7.1.0` = PatchVersion(7, 1, 0) - val `7.2.0-PREVIEW1` = SemanticVersion.parse("7.2.0-PREVIEW.1").get - val `7.2.0-PREVIEW2` = SemanticVersion.parse("7.2.0-PREVIEW.2").get + val `7.2.0-PREVIEW.1` = SemanticVersion.parse("7.2.0-PREVIEW.1").get + val `7.2.0-PREVIEW.2` = SemanticVersion.parse("7.2.0-PREVIEW.2").get val `7.2.0` = PatchVersion(7, 2, 0) val `7.3.0` = PatchVersion(7, 3, 0) diff --git a/modules/server/src/main/scala/scaladex/server/route/Badges.scala b/modules/server/src/main/scala/scaladex/server/route/Badges.scala index a144cb046..b13a47382 100644 --- a/modules/server/src/main/scala/scaladex/server/route/Badges.scala +++ b/modules/server/src/main/scala/scaladex/server/route/Badges.scala @@ -21,6 +21,7 @@ import scaladex.core.model.Scala import scaladex.core.model.ScalaJs import scaladex.core.model.ScalaNative import scaladex.core.model.SemanticVersion +import scaladex.core.model.SemanticVersion.PreferReleasesThenHighest import scaladex.core.service.WebDatabase class Badges(database: WebDatabase)(implicit executionContext: ExecutionContext) { @@ -173,7 +174,7 @@ object Badges { private[route] def summaryOfLatestVersions(versionsByScalaVersions: Map[Scala, Seq[SemanticVersion]]): String = versionsByScalaVersions.view - .mapValues(_.max) + .mapValues(_.max(PreferReleasesThenHighest)) .groupMap { case (_, latestVersion) => latestVersion } { case (scalaVersion, _) => scalaVersion } .toSeq .sortBy(_._1)(SemanticVersion.ordering.reverse) diff --git a/modules/server/src/test/scala/scaladex/server/route/BadgesTests.scala b/modules/server/src/test/scala/scaladex/server/route/BadgesTests.scala index 764188a0e..dd3921aa4 100644 --- a/modules/server/src/test/scala/scaladex/server/route/BadgesTests.scala +++ b/modules/server/src/test/scala/scaladex/server/route/BadgesTests.scala @@ -11,7 +11,7 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.funspec.AnyFunSpec import org.scalatest.matchers.should.Matchers import scaladex.core.model.Scala._ -import scaladex.core.test.Values.{`7.2.0`, _} +import scaladex.core.test.Values._ import scaladex.core.util.ScalaExtensions._ import scaladex.server.route.Badges.summaryOfLatestVersions @@ -78,11 +78,13 @@ class BadgesUnitTests extends AnyFunSpec with Matchers { } it("should prefer releases to pre-releases if both are available") { - summaryOfLatestVersions(Map(`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW1`))) shouldBe "7.1.0 (Scala 2.13)" + summaryOfLatestVersions(Map(`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`))) shouldBe "7.1.0 (Scala 2.13)" } it("should display latest pre-release if no full release is available") { - summaryOfLatestVersions(Map(`2.13` -> Seq(`7.2.0-PREVIEW1`, `7.2.0-PREVIEW2`))) shouldBe s"${`7.2.0-PREVIEW2`} (Scala 2.13)" + summaryOfLatestVersions( + Map(`2.13` -> Seq(`7.2.0-PREVIEW.1`, `7.2.0-PREVIEW.2`)) + ) shouldBe s"${`7.2.0-PREVIEW.2`} (Scala 2.13)" } }