From a4444b0d94193f031ca7eafe219d5e4e8a005d40 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 2 Apr 2020 09:42:32 +0200 Subject: [PATCH 01/10] filter out invalid sbt and scala.js versions --- .../SemanticVersion.scala | 76 ++++++------------- .../release/ScalaTarget.scala | 9 ++- .../DataRepository.scala | 27 ++++--- 3 files changed, 49 insertions(+), 63 deletions(-) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index 787c40da1..02f5c5128 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -24,20 +24,21 @@ case class OtherPreRelease(o: String) extends PreRelease { */ case class SemanticVersion( major: Long, - minor: Long = 0, + minor: Option[Long] = None, patch: Option[Long] = None, patch2: Option[Long] = None, preRelease: Option[PreRelease] = None, metadata: Option[String] = None ) extends Ordered[SemanticVersion] { - def isSemantic = { + def isSemantic: Boolean = { patch.isDefined && - !patch2.isDefined && - preRelease.map(_.isSemantic).getOrElse(true) + patch2.isEmpty && + preRelease.forall(_.isSemantic) } override def toString: String = { + val minorPart = minor.map(m => s".$m").getOrElse("") val patchPart = patch.map("." + _).getOrElse("") val patch2Part = patch2.map("." + _).getOrElse("") @@ -52,7 +53,7 @@ case class SemanticVersion( val metadataPart = metadata.map("+" + _).getOrElse("") - major + "." + minor + patchPart + patch2Part + preReleasePart + metadataPart + major + minorPart + patchPart + patch2Part + preReleasePart + metadataPart } def binary: SemanticVersion = @@ -61,57 +62,29 @@ case class SemanticVersion( def forceBinary: SemanticVersion = SemanticVersion(major, minor) - private final val LT = -1 - private final val GT = 1 - private final val EQ = 0 - - private final val lcmp = implicitly[Ordering[Long]] - private final val scmp = implicitly[Ordering[String]] - private final val cmp = - implicitly[Ordering[(Long, Long, Option[Long], Option[Long])]] - - override def compare(that: SemanticVersion): Int = { - val v1 = this - val v2 = that - - def tupled(v: SemanticVersion) = (v.major, v.minor, v.patch, v.patch2) - val tv1 = tupled(v1) - val tv2 = tupled(v2) - - def preCmp(pr1: Option[PreRelease], pr2: Option[PreRelease]): Int = { - // format: off - (pr1, pr2) match { - case (None, None) => EQ - case (None, Some(_)) => GT - case (Some(_), None) => LT - case (Some(ReleaseCandidate(rc1)), Some(ReleaseCandidate(rc2))) => lcmp.compare(rc1, rc2) - case (Some(ReleaseCandidate(_)) , Some(Milestone(_))) => GT - case (Some(Milestone(_)) , Some(ReleaseCandidate(_))) => LT - case (Some(Milestone(m1)) , Some(Milestone(m2))) => lcmp.compare(m1, m2) - case (Some(OtherPreRelease(pr1)) , Some(OtherPreRelease(pr2))) => scmp.compare(pr1, pr2) - case (Some(OtherPreRelease(_)) , Some(Milestone(_))) => LT - case (Some(OtherPreRelease(_)) , Some(ReleaseCandidate(_))) => LT - case (Some(_) , Some(OtherPreRelease(_))) => GT - case _ => EQ - } - // format: on - } - - // Milestone < Release Candidate < Released - if (cmp.equiv(tv1, tv2)) preCmp(v1.preRelease, v2.preRelease) - else cmp.compare(tv1, tv2) + override def compare(that: SemanticVersion): PageIndex = { + SemanticVersion.ordering.compare(this, that) } } object SemanticVersion extends Parsers { - import fastparse._ - import fastparse.NoWhitespace._ + private implicit val preReleaseOrdering: Ordering[PreRelease] = Ordering.by { + case ReleaseCandidate(rc) => (Some(rc), None, None) + case Milestone(m) => (None, Some(m), None) + case OtherPreRelease(pr) => (None, None, Some(pr)) + } - implicit def ordering = new Ordering[SemanticVersion] { - def compare(v1: SemanticVersion, v2: SemanticVersion): Int = - v1.compare(v2) + implicit val ordering: Ordering[SemanticVersion] = Ordering.by { + x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) } + def apply(major: Long, minor: Long): SemanticVersion = { + SemanticVersion(major, Some(minor)) + } + + import fastparse._ + import fastparse.NoWhitespace._ + private def Number[_: P] = Digit.rep(1).!.map(_.toLong) private def Major[_: P] = Number @@ -127,12 +100,11 @@ object SemanticVersion extends Parsers { // http://semver.org/#spec-item-10 private def MetaData[_: P] = "+" ~ AnyChar.rep.! - private def MinorP[_: P] = - ("." ~ Number).?.map(_.getOrElse(0L)) // not really valid SemVer + private def MinorP[_: P] = ("." ~ Number).? // not really valid SemVer private def PatchP[_: P] = ("." ~ Number).? // not really valid SemVer private def Patch2P[_: P] = ("." ~ Number).? // not really valid SemVer - def Parser[_: P] = { + def Parser[_: P]: P[SemanticVersion] = { ("v".? ~ Major ~ MinorP ~ PatchP ~ Patch2P ~ PreRelease.? ~ MetaData.?) .map { case (major, minor, patch, patch2, preRelease, metadata) => diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index c4d8d9602..03f796df4 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -146,8 +146,13 @@ object ScalaTarget { val scalaVersion = target.map(_.scalaVersion.forceBinary.toString) - val scalaJsVersion = - target.flatMap(_.scalaJsVersion.map(_.forceBinary.toString)) + val scalaJsVersion = for { + target <- target + scalaJsVersion <- target.scalaJsVersion + } yield scalaJsVersion match { + case SemanticVersion(0, minor, _, _, _, _) => SemanticVersion(0, minor).toString + case _ => SemanticVersion(scalaJsVersion.major).toString + } val scalaNativeVersion = target.flatMap(_.scalaNativeVersion.map(_.forceBinary.toString)) diff --git a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala index 67b0413cc..efb4afec4 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala @@ -225,20 +225,16 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getScalaVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("scalaVersion", - filteredSearchQuery(params), - filterScalaVersion) + versionAggregations("scalaVersion", filteredSearchQuery(params), filterScalaVersion) .map(addLabelsIfMissing(params.scalaVersions.toSet)) } def getAllScalaJsVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaJsVersion", notDeprecatedQuery, _ => true) + versionAggregations("scalaJsVersion", notDeprecatedQuery, filterScalaJsVersion) } def getScalaJsVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("scalaJsVersion", - filteredSearchQuery(params), - _ => true) + versionAggregations("scalaJsVersion", filteredSearchQuery(params), filterScalaJsVersion) .map(addLabelsIfMissing(params.scalaJsVersions.toSet)) } @@ -256,11 +252,11 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getAllSbtVersions(): Future[List[(String, Long)]] = { - versionAggregations("sbtVersion", notDeprecatedQuery, _ => true) + versionAggregations("sbtVersion", notDeprecatedQuery, filterSbtVersion) } def getSbtVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("sbtVersion", filteredSearchQuery(params), _ => true) + versionAggregations("sbtVersion", filteredSearchQuery(params), filterSbtVersion) .map(addLabelsIfMissing(params.sbtVersions.toSet)) } @@ -575,6 +571,19 @@ object DataRepository { minScalaVersion <= version && version <= maxScalaVersion } + private def minSbtVersion = SemanticVersion(0, 11) + private def maxSbtVersion = SemanticVersion(1, 3) + + private def filterSbtVersion(version: SemanticVersion): Boolean = { + minSbtVersion <= version && version <= maxSbtVersion + } + + private def minScalaJsVersion = SemanticVersion(0, 6) + + private def filterScalaJsVersion(version: SemanticVersion): Boolean = { + minScalaJsVersion <= version + } + private def labelizeTargetType(targetType: String): String = { if (targetType == "JVM") "Scala (Jvm)" else targetType.take(1).map(_.toUpper) + targetType.drop(1).map(_.toLower) From 18a3be5b5df6e8adec7b3cf2c5079e8b4e77160c Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 2 Apr 2020 16:03:24 +0200 Subject: [PATCH 02/10] refactor ScalaTarget --- .../central/CentralMissing.scala | 43 ++-- .../elastic/package.scala | 6 +- .../project/ArtifactMetaExtractor.scala | 15 +- .../project/ProjectConvert.scala | 76 ++++--- .../ch.epfl.scala.index.model/Artifact.scala | 60 +---- .../ch.epfl.scala.index.model/Parsers.scala | 7 + .../ch.epfl.scala.index.model/Release.scala | 38 +--- .../SemanticVersion.scala | 34 ++- .../release/DefaultRelease.scala | 35 ++- .../release/ScalaTarget.scala | 208 +++++++----------- .../ArtifactTests.scala | 70 +++--- .../ScalaTargetOrdering.scala | 43 ---- .../SemanticVersionTests.scala | 103 ++++----- .../release/DefaultReleaseTests.scala | 44 ++-- .../release/MillInstallTests.scala | 8 +- .../release/SbtInstallTests.scala | 22 +- .../release/ScalaTargetOrdering.scala | 43 ++++ .../DataRepository.scala | 47 ++-- .../routes/ProjectPages.scala | 33 +-- .../routes/api/SearchApi.scala | 16 +- .../RelevanceTest.scala | 24 +- 21 files changed, 444 insertions(+), 531 deletions(-) delete mode 100644 model/src/test/scala/ch.epfl.scala.index.model/ScalaTargetOrdering.scala create mode 100644 model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala diff --git a/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala b/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala index 55e2286a0..e781afa87 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala @@ -2,47 +2,44 @@ package ch.epfl.scala.index package data import ch.epfl.scala.index.model.Release -import ch.epfl.scala.index.model.release.ScalaTarget +import ch.epfl.scala.index.model.release.{ + SbtPlugin, + ScalaJs, + ScalaJvm, + ScalaNative, + ScalaTarget +} import ch.epfl.scala.index.model.SemanticVersion import ch.epfl.scala.index.data.github.GithubDownload -import ch.epfl.scala.index.data.project.{ProjectConvert, ArtifactMetaExtractor} +import ch.epfl.scala.index.data.project.{ArtifactMetaExtractor, ProjectConvert} import ch.epfl.scala.index.data.maven.PomsReader import ch.epfl.scala.index.model.misc.Sha1 import scala.util.{Failure, Success} -import scala.concurrent.{Future, Promise, Await} +import scala.concurrent.{Await, Future, Promise} import scala.concurrent.duration._ import scala.util.Try - import akka.NotUsed import akka.actor.ActorSystem - import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.http.scaladsl.model.ContentTypes._ import akka.http.scaladsl.model.headers._ - import akka.http.scaladsl.model.Uri.Query import akka.http.scaladsl.unmarshalling._ - import akka.stream.Materializer import akka.stream.ThrottleMode import akka.stream.scaladsl._ - import akka.stream.{OverflowStrategy, QueueOfferResult} - import de.heikoseeberger.akkahttpjson4s.Json4sSupport._ import org.joda.time.DateTime import org.json4s._ import org.json4s.native.JsonMethods._ - import org.slf4j.LoggerFactory import scala.collection.immutable.Seq - import java.nio.file.Files import java.nio.charset.StandardCharsets - import java.lang.reflect.InvocationTargetException object CentralMissing { @@ -273,17 +270,17 @@ class CentralMissing(paths: DataPaths)(implicit val materializer: Materializer, val native03 = SemanticVersion("0.3").get val allTargets = List( - ScalaTarget.scala(scala213), - ScalaTarget.scala(scala212), - ScalaTarget.scala(scala211), - ScalaTarget.scala(scala210), - ScalaTarget.sbt(scala210, sbt013), - ScalaTarget.sbt(scala212, sbt10), - ScalaTarget.scalaJs(scala213, scalaJs06), - ScalaTarget.scalaJs(scala212, scalaJs06), - ScalaTarget.scalaJs(scala211, scalaJs06), - ScalaTarget.scalaJs(scala210, scalaJs06), - ScalaTarget.scalaNative(scala211, native03) + ScalaJvm(scala213), + ScalaJvm(scala212), + ScalaJvm(scala211), + ScalaJvm(scala210), + SbtPlugin(scala210, sbt013), + SbtPlugin(scala212, sbt10), + ScalaJs(scala213, scalaJs06), + ScalaJs(scala212, scalaJs06), + ScalaJs(scala211, scalaJs06), + ScalaJs(scala210, scalaJs06), + ScalaNative(scala211, native03) ) val releasesDownloads = diff --git a/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala b/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala index d8482077b..b3a7ac33c 100755 --- a/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala @@ -27,7 +27,11 @@ trait ProjectProtocol { classOf[Milestone], classOf[ReleaseCandidate], classOf[OtherPreRelease], - classOf[BintrayResolver] + classOf[BintrayResolver], + classOf[ScalaJvm], + classOf[ScalaJs], + classOf[ScalaNative], + classOf[SbtPlugin] ) ) ) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala index 653564180..d45baa96d 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala @@ -3,10 +3,9 @@ package data package project import cleanup._ -import model.release.ScalaTarget +import model.release.{SbtPlugin, ScalaJvm, ScalaTarget} import model.{Artifact, SemanticVersion} import maven.{ReleaseModel, SbtPluginTarget} - import org.slf4j.LoggerFactory case class ArtifactMeta( @@ -43,8 +42,8 @@ class ArtifactMetaExtractor(paths: DataPaths) { // This is a usual Scala library (whose artifact name is suffixed by the Scala binary version) // For example: akka-actors_2.12 case None => { - Artifact(pom.artifactId).map { - case (artifactName, target) => + Artifact.parse(pom.artifactId).map { + case Artifact(artifactName, target) => ArtifactMeta( artifactName = artifactName, scalaTarget = Some(target), @@ -63,8 +62,7 @@ class ArtifactMetaExtractor(paths: DataPaths) { Some( ArtifactMeta( artifactName = pom.artifactId, - scalaTarget = - Some(ScalaTarget.sbt(scalaVersion, sbtVersion)), + scalaTarget = Some(SbtPlugin(scalaVersion, sbtVersion)), isNonStandard = false ) ) @@ -91,8 +89,7 @@ class ArtifactMetaExtractor(paths: DataPaths) { // we assume binary compatibility ArtifactMeta( artifactName = pom.artifactId, - scalaTarget = - Some(ScalaTarget.scala(version.copy(patch = None))), + scalaTarget = Some(ScalaJvm(version.copy(patch = None))), isNonStandard = true ) ) @@ -115,7 +112,7 @@ class ArtifactMetaExtractor(paths: DataPaths) { version => ArtifactMeta( artifactName = pom.artifactId, - scalaTarget = Some(ScalaTarget.scala(version)), + scalaTarget = Some(ScalaJvm(version)), isNonStandard = true ) ) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala index 072ade72b..66430d810 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala @@ -2,21 +2,17 @@ package ch.epfl.scala.index package data package project -import cleanup._ -import model._ -import model.misc._ -import model.release._ -import maven.{ReleaseModel, SbtPluginTarget} -import bintray._ -import github._ - -import ch.epfl.scala.index.data.LocalRepository.BintraySbtPlugins +import ch.epfl.scala.index.data.bintray._ +import ch.epfl.scala.index.data.cleanup._ +import ch.epfl.scala.index.data.elastic.SaveLiveData +import ch.epfl.scala.index.data.github._ +import ch.epfl.scala.index.data.maven.ReleaseModel import ch.epfl.scala.index.data.project.ProjectConvert.ProjectSeed - -import elastic.SaveLiveData +import ch.epfl.scala.index.model._ +import ch.epfl.scala.index.model.misc._ +import ch.epfl.scala.index.model.release._ import com.github.nscala_time.time.Imports._ import org.joda.time.DateTime - import org.slf4j.LoggerFactory class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) @@ -94,7 +90,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) val projectReference = Project.Reference(organization, repository) val cachedReleasesForProject = - cachedReleases.get(projectReference).getOrElse(Set()) + cachedReleases.getOrElse(projectReference, Set()) val releases = vs.map { case (_, @@ -106,12 +102,20 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) version, isNonStandardLib) => val (targetType, - fullScalaVersion, scalaVersion, scalaJsVersion, scalaNativeVersion, - sbtVersion) = - ScalaTarget.split(target) + sbtVersion) = target match { + case Some(ScalaJvm(version)) => + (Jvm, Some(version), None, None, None) + case Some(ScalaJs(version, jsVersion)) => + (Js, Some(version), Some(jsVersion), None, None) + case Some(ScalaNative(version, nativeVersion)) => + (Native, Some(version), None, Some(nativeVersion), None) + case Some(SbtPlugin(version, sbtVersion)) => + (Sbt, Some(version), None, None, Some(sbtVersion)) + case None => (Java, None, None, None, None) + } Release( maven = pomToMavenReference(pom), @@ -134,18 +138,24 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) javaDependencies = Seq(), reverseDependencies = Seq(), internalDependencies = Seq(), - targetType = targetType.getOrElse(Java).toString, + targetType = targetType.toString, // for artifact publish with binary, full will return binary // ex cats_2.11 => 2.11 - fullScalaVersion = fullScalaVersion, - scalaVersion = scalaVersion, - scalaJsVersion = scalaJsVersion, - scalaNativeVersion = scalaNativeVersion, - sbtVersion = sbtVersion + fullScalaVersion = scalaVersion.map(_.toString), + scalaVersion = scalaVersion.map(_.forceBinary.toString), + scalaJsVersion = scalaJsVersion.map { + case SemanticVersion(0, minor, _, _, _, _) => + SemanticVersion(0, minor).toString + case SemanticVersion(major, _, _, _, _, _) => + SemanticVersion(major).toString + }, + scalaNativeVersion = + scalaNativeVersion.map(_.forceBinary.toString), + sbtVersion = sbtVersion.map(_.forceBinary.toString) ) }.toSet ++ cachedReleasesForProject - val releaseCount = releases.map(_.reference.version).toSet.size + val releaseCount = releases.map(_.reference.version).size val (max, min) = maxMinRelease(releases) @@ -153,8 +163,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) if (stored) storedProjects .get(Project.Reference(organization, repository)) - .map(_.defaultStableVersion) - .getOrElse(true) + .forall(_.defaultStableVersion) else true val releaseOptions = DefaultRelease( @@ -214,7 +223,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) // Scala Library is a reverse dependency of almost all projects anyway case (Some(dependencyReference), _) - if (reverse && dependencyReference.isScalaLib) => + if reverse && dependencyReference.isScalaLib => cache0 /* We have both, scala -> scala reference */ @@ -312,12 +321,12 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) val project = seed.toProject( - targetType = releases.map(_.targetType).toSet, - fullScalaVersion = releases.flatMap(_.fullScalaVersion).toSet, - scalaVersion = releases.flatMap(_.scalaVersion).toSet, - scalaJsVersion = releases.flatMap(_.scalaJsVersion).toSet, - scalaNativeVersion = releases.flatMap(_.scalaNativeVersion).toSet, - sbtVersion = releases.flatMap(_.sbtVersion).toSet, + targetType = releases.map(_.targetType), + fullScalaVersion = releases.flatMap(_.fullScalaVersion), + scalaVersion = releases.flatMap(_.scalaVersion), + scalaJsVersion = releases.flatMap(_.scalaJsVersion), + scalaNativeVersion = releases.flatMap(_.scalaNativeVersion), + sbtVersion = releases.flatMap(_.sbtVersion), dependencies = dependencies(releasesWithDependencies), dependentCount = releasesWithDependencies.view .flatMap(_.reverseDependencies.map(_.reference)) @@ -356,7 +365,8 @@ object ProjectConvert { updated: Option[String] ) { - def reference = Project.Reference(organization, repository) + def reference: Project.Reference = + Project.Reference(organization, repository) def toProject(targetType: Set[String], fullScalaVersion: Set[String], diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala b/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala index 815dda651..682ed553b 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala @@ -1,64 +1,24 @@ package ch.epfl.scala.index.model +import ch.epfl.scala.index.model.release.ScalaTarget.scalaTargetParser import fastparse._ - import release.ScalaTarget +case class Artifact(name: String, target: ScalaTarget) + object Artifact extends Parsers { import fastparse.NoWhitespace._ - private def ScalaPart[_: P] = "_" ~ SemanticVersion.Parser - - private def ScalaJs[_: P]: P[ScalaTarget] = - ("_sjs" ~ SemanticVersion.Parser ~ ScalaPart).map { - case (scalaJsVersion, scalaVersion) => - ScalaTarget.scalaJs(scalaVersion, scalaJsVersion) - } - - private def ScalaNative[_: P]: P[ScalaTarget] = - ("_native" ~ SemanticVersion.Parser ~ ScalaPart).map { - case (scalaNativeVersion, scalaVersion) => - ScalaTarget.scalaNative(scalaVersion, scalaNativeVersion) - } - - private def Sbt[_: P]: P[ScalaTarget] = - (ScalaPart ~ "_" ~ SemanticVersion.Parser).map { - case (scalaVersion, sbtVersion) => - ScalaTarget.sbt(scalaVersion, sbtVersion) - } - - private def Scala[_: P]: P[ScalaTarget] = ScalaPart.map(ScalaTarget.scala) - - private def ScalaTargetParser[_: P] = - ScalaJs | ScalaNative | Sbt | Scala - - private def ArtifactNameParser[_: P] = { + private def artifactNameParser[_: P] = { Start ~ - (Alpha | Digit | "-".! | ".".! | (!(ScalaTargetParser ~ End) ~ "_")).rep.! ~ // must end with scala target - ScalaTargetParser ~ + (Alpha | Digit | "-".! | ".".! | (!(scalaTargetParser ~ End) ~ "_")).rep.! ~ // must end with scala target + scalaTargetParser ~ End + }.map { + case (name, target) => Artifact(name, target) } - def apply(artifactId: String): Option[(String, ScalaTarget)] = { - fastparse.parse(artifactId, x => ArtifactNameParser(x)) match { - case Parsed.Success(v, _) => Some(v) - case _ => None - } + def parse(artifactId: String): Option[Artifact] = { + tryParse(artifactId, x => artifactNameParser(x)) } } - -/** - * We distinguish between 3 kinds of artifacts: - * - conventional Scala library (whose artifact names are suffixed by the targeted Scala version -- e.g. "_2.11") - * - unconventional Scala library (whose artifact names are ''not'' suffixed by the targeted Scala version) - * - sbt plugins - */ -sealed trait ArtifactKind - -object ArtifactKind { - - case object ConventionalScalaLib extends ArtifactKind - case object UnconventionalScalaLib extends ArtifactKind - case object SbtPlugin extends ArtifactKind - -} diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala b/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala index d5a79ba80..78da50e7d 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala @@ -6,4 +6,11 @@ trait Parsers { protected def Alpha[_: P] = CharPred(c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')).! protected def Digit[_: P] = CharIn("0123456789").! + + def tryParse[T](input: ParserInputSource, parser: P[_] => P[T]): Option[T] = { + fastparse.parse(input, parser) match { + case Parsed.Success(v, _) => Some(v) + case _ => None + } + } } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala index 90e6ea3e6..3172fefc7 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala @@ -49,33 +49,19 @@ case class Release( * @return */ def sbtInstall: String = { - val isSbtPlugin = reference.target.flatMap(_.sbtVersion).isDefined - - val install = - if (!isSbtPlugin) { - val isScalaJs = - reference.target.flatMap(_.scalaJsVersion).isDefined - - val isScalaNative = - reference.target.flatMap(_.scalaNativeVersion).isDefined - - val isCrossFull = - reference.target.flatMap(_.scalaVersion.patch).isDefined - - val isPreRelease = - reference.target.flatMap(_.scalaVersion.preRelease).isDefined - - val (artifactOperator, crossSuffix) = - if (isNonStandardLib) ("%", "") - else if (isScalaJs || isScalaNative) ("%%%", "") - else if (isCrossFull & !isPreRelease) - ("%", " cross CrossVersion.full") - else ("%%", "") - - s"""libraryDependencies += "${maven.groupId}" $artifactOperator "${reference.artifact}" % "${reference.version}"$crossSuffix""" - } else { + val install = reference.target match { + case Some(SbtPlugin(_, _)) => s"""addSbtPlugin("${maven.groupId}" % "${reference.artifact}" % "${reference.version}")""" - } + case _ if isNonStandardLib => + s"""libraryDependencies += "${maven.groupId}" % "${reference.artifact}" % "${reference.version}"""" + case Some(ScalaJs(_, _) | ScalaNative(_, _)) => + s"""libraryDependencies += "${maven.groupId}" %%% "${reference.artifact}" % "${reference.version}"""" + case Some(ScalaJvm(version)) + if version.patch.isDefined && version.preRelease.isEmpty => + s"""libraryDependencies += "${maven.groupId}" % "${reference.artifact}" % "${reference.version}" cross CrossVersion.full""" + case _ => + s"""libraryDependencies += "${maven.groupId}" %% "${reference.artifact}" % "${reference.version}"""" + } List( Some(install), diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index 02f5c5128..68fb9c05d 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -68,20 +68,40 @@ case class SemanticVersion( } object SemanticVersion extends Parsers { - private implicit val preReleaseOrdering: Ordering[PreRelease] = Ordering.by { - case ReleaseCandidate(rc) => (Some(rc), None, None) - case Milestone(m) => (None, Some(m), None) - case OtherPreRelease(pr) => (None, None, Some(pr)) - } + private implicit val preReleaseOrdering: Ordering[Option[PreRelease]] = + Ordering.by { + case None => (3, None, None) + case Some(ReleaseCandidate(rc)) => (2, Some(rc), None) + case Some(Milestone(m)) => (1, Some(m), None) + case Some(OtherPreRelease(pr)) => (0, None, Some(pr)) + } - implicit val ordering: Ordering[SemanticVersion] = Ordering.by { - x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) + implicit def ordering: Ordering[SemanticVersion] = Ordering.by { x => + (x.major, x.minor, x.patch, x.patch2, x.preRelease) } def apply(major: Long, minor: Long): SemanticVersion = { SemanticVersion(major, Some(minor)) } + def apply(major: Long, minor: Long, patch: Long): SemanticVersion = { + SemanticVersion(major, Some(minor), Some(patch)) + } + + def apply(major: Long, + minor: Long, + patch: Long, + patch2: Long): SemanticVersion = { + SemanticVersion(major, Some(minor), Some(patch), Some(patch2)) + } + + def apply(major: Long, + minor: Long, + patch: Long, + preRelease: PreRelease): SemanticVersion = { + SemanticVersion(major, Some(minor), Some(patch), None, Some(preRelease)) + } + import fastparse._ import fastparse.NoWhitespace._ diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala index af2f606cb..599965edd 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala @@ -15,7 +15,7 @@ object ReleaseSelection { selected: Option[String]): ReleaseSelection = { new ReleaseSelection( - target.flatMap(ScalaTarget.decode), + target.flatMap(ScalaTarget.parse), artifactName, version.flatMap(SemanticVersion.parse), selected @@ -42,15 +42,15 @@ object DefaultRelease { defaultStableVersion: Boolean): Option[ReleaseOptions] = { def filterTarget(release: Release): Boolean = - selection.target - .map(target => Some(target) == release.reference.target) - .getOrElse(true) + selection.target.forall( + target => release.reference.target.contains(target) + ) def filterArtifact(release: Release): Boolean = - selection.artifact.map(_ == release.reference.artifact).getOrElse(true) + selection.artifact.forall(_ == release.reference.artifact) def filterVersion(release: Release): Boolean = - selection.version.map(_ == release.reference.version).getOrElse(true) + selection.version.forall(_ == release.reference.version) def filterAll = releases.filter( @@ -71,14 +71,15 @@ object DefaultRelease { } // descending ordering for versions - implicit def ordering = implicitly[Ordering[SemanticVersion]].reverse + implicit def ordering: Ordering[SemanticVersion] = + SemanticVersion.ordering.reverse val releasesSorted = selectedReleases.toList.sortBy { release => import release.reference._ ( // artifact // match default artifact (ex: akka-actors is the default for akka/akka) - defaultArtifact != Some(artifact), // false < true + !defaultArtifact.contains(artifact), // false < true // match project repository (ex: shapeless) projectRepository == artifact, // alphabetically @@ -88,10 +89,10 @@ object DefaultRelease { version, // target // stable jvm targets first - target.flatMap(_.scalaJsVersion).isDefined, + target.exists(_.targetType == Js), target.flatMap(_.scalaVersion.preRelease).isDefined, target.map(_.scalaVersion), - target.flatMap(_.scalaJsVersion) + target.collect { case ScalaJs(_, scalaJsVersion) => scalaJsVersion } ) } @@ -102,11 +103,21 @@ object DefaultRelease { .flatten .sortBy( target => - (target.targetType, target.scalaVersion, target.scalaJsVersion) + ( + target.targetType, + target.scalaVersion, + target match { + case ScalaJs(_, scalaJsVersion) => Some(scalaJsVersion) + case _ => None + } + ) ) val artifacts = releases.map(_.reference.artifact).toList.sorted - val versions = releases.map(_.reference.version).toList.sorted + val versions = releases + .map(_.reference.version) + .toList + .sorted(SemanticVersion.ordering.reverse) ReleaseOptions( artifacts, diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index 03f796df4..ccea2088c 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -2,18 +2,12 @@ package ch.epfl.scala.index.model package release object ScalaTargetType { - implicit val ordering: Ordering[ScalaTargetType] = { - def toInt(v: ScalaTargetType): Int = { - v match { - case Jvm => 5 - case Js => 4 - case Native => 3 - case Sbt => 2 - case Java => 1 - } - } - - Ordering.by(toInt) + implicit val ordering: Ordering[ScalaTargetType] = Ordering.by { + case Jvm => 5 + case Js => 4 + case Native => 3 + case Sbt => 2 + case Java => 1 } } @@ -32,139 +26,87 @@ in other words if we see cats_2.11 we will not infer the full scala version from it's dependency on scala-library for example. */ -case class ScalaTarget( - scalaVersion: SemanticVersion, - scalaJsVersion: Option[SemanticVersion], - scalaNativeVersion: Option[SemanticVersion], - sbtVersion: Option[SemanticVersion] -) extends Ordered[ScalaTarget] { - - def render = { - (scalaJsVersion, scalaNativeVersion, sbtVersion) match { - case (Some(jsVersion), _, _) => - s"scala-js ${jsVersion.toString} (scala ${scalaVersion.toString})" - - case (_, Some(nativeVersion), _) => - s"scala-native ${nativeVersion.toString} (scala ${scalaVersion.toString})" - - case (_, _, Some(sbtVersion)) => - s"sbt ${sbtVersion.toString} (scala ${scalaVersion.toString})" - - case _ => - s"scala ${scalaVersion.toString}" - } - } - - def targetType: ScalaTargetType = { - (scalaJsVersion, scalaNativeVersion, sbtVersion) match { - case (Some(_), _, _) => Js - case (_, Some(_), _) => Native - case (_, _, Some(_)) => Sbt - case _ => Jvm - } - } +sealed trait ScalaTarget extends Ordered[ScalaTarget] { + def scalaVersion: SemanticVersion + def render: String + def encode: String + def targetType: ScalaTargetType - def encode: String = { - (scalaJsVersion, scalaNativeVersion, sbtVersion) match { - case (Some(scalaJsVersion), _, _) => - s"_sjs${scalaJsVersion}_${scalaVersion}" + override def compare(that: ScalaTarget): Int = + ScalaTarget.ordering.compare(this, that) +} - case (_, Some(scalaNativeVersion), _) => - s"_native${scalaNativeVersion}_${scalaVersion}" +case class ScalaJvm(scalaVersion: SemanticVersion) extends ScalaTarget { + val scalaJsVersion: Option[SemanticVersion] = None + val render = s"scala $scalaVersion" + val encode = s"_$scalaVersion" + val targetType: ScalaTargetType = Jvm +} +case class ScalaJs(scalaVersion: SemanticVersion, + scalaJsVersion: SemanticVersion) + extends ScalaTarget { + val render = s"scala-js $scalaJsVersion ($scalaVersion)" + val encode = s"_sjs${scalaJsVersion}_$scalaVersion" + val targetType: ScalaTargetType = Js +} +case class ScalaNative(scalaVersion: SemanticVersion, + scalaNativeVersion: SemanticVersion) + extends ScalaTarget { + val scalaJsVersion: Option[SemanticVersion] = None + val render = s"scala-native $scalaNativeVersion ($scalaNativeVersion)" + val encode = s"_native${scalaNativeVersion}_$scalaVersion" + val targetType: ScalaTargetType = Native +} - case (_, _, Some(sbtVersion)) => - s"_${scalaVersion}_${sbtVersion}" +case class SbtPlugin(scalaVersion: SemanticVersion, sbtVersion: SemanticVersion) + extends ScalaTarget { + val scalaJsVersion: Option[SemanticVersion] = None + val render = s"sbt $sbtVersion ($scalaVersion)" + val encode = s"_${scalaVersion}_$sbtVersion" + val targetType: ScalaTargetType = Sbt +} - case _ => - s"_${scalaVersion}" +object ScalaTarget extends Parsers { + // Scala > Js > Native > Sbt + implicit val ordering: Ordering[ScalaTarget] = + Ordering.by[ScalaTarget, + (ScalaTargetType, SemanticVersion, Option[SemanticVersion])] { + case ScalaJvm(version) => (Jvm, version, None) + case ScalaJs(version, jsVersion) => (Js, version, Some(jsVersion)) + case ScalaNative(version, nativeVersion) => + (Native, version, Some(nativeVersion)) + case SbtPlugin(version, sbtVersion) => (Sbt, version, Some(sbtVersion)) } - } - - private final val LT = -1 - private final val GT = 1 - private final val EQ = 0 - - // Scala > Js > Native - override def compare(that: ScalaTarget): Int = - ScalaTarget.ordering.compare(this, that) -} + def parse(code: String): Option[ScalaTarget] = { + tryParse(code, x => scalaTargetParser(x)) + } -object ScalaTarget { + import fastparse.NoWhitespace._ + import fastparse._ - implicit val ordering: Ordering[ScalaTarget] = Ordering.by { target => - ( - target.targetType, - target.scalaVersion, - target.scalaJsVersion, - target.scalaNativeVersion, - target.sbtVersion - ) - } + private def scalaPart[_: P] = "_" ~ SemanticVersion.Parser - def decode(code: String): Option[ScalaTarget] = { - Artifact(code).map(_._2) - } + private def scalaJs[_: P]: P[ScalaTarget] = + ("_sjs" ~ SemanticVersion.Parser ~ scalaPart).map { + case (scalaJsVersion, scalaVersion) => + ScalaJs(scalaVersion, scalaJsVersion) + } - def scala(scalaVersion: SemanticVersion) = - ScalaTarget(scalaVersion = scalaVersion, - scalaJsVersion = None, - scalaNativeVersion = None, - sbtVersion = None) - - def scalaJs(scalaVersion: SemanticVersion, scalaJsVersion: SemanticVersion) = - ScalaTarget(scalaVersion = scalaVersion, - scalaJsVersion = Some(scalaJsVersion), - scalaNativeVersion = None, - sbtVersion = None) - - def scalaNative(scalaVersion: SemanticVersion, - scalaNativeVersion: SemanticVersion) = - ScalaTarget(scalaVersion = scalaVersion, - scalaJsVersion = None, - scalaNativeVersion = Some(scalaNativeVersion), - sbtVersion = None) - - def sbt(scalaVersion: SemanticVersion, sbtVersion: SemanticVersion) = - ScalaTarget(scalaVersion = scalaVersion, - scalaJsVersion = None, - scalaNativeVersion = None, - sbtVersion = Some(sbtVersion)) - - def split(target: Option[ScalaTarget]): (Option[ScalaTargetType], - Option[String], - Option[String], - Option[String], - Option[String], - Option[String]) = { - val targetType = - target.map(_.targetType) - - val fullScalaVersion = - target.map(_.scalaVersion.toString) - - val scalaVersion = - target.map(_.scalaVersion.forceBinary.toString) - - val scalaJsVersion = for { - target <- target - scalaJsVersion <- target.scalaJsVersion - } yield scalaJsVersion match { - case SemanticVersion(0, minor, _, _, _, _) => SemanticVersion(0, minor).toString - case _ => SemanticVersion(scalaJsVersion.major).toString + private def scalaNative[_: P]: P[ScalaTarget] = + ("_native" ~ SemanticVersion.Parser ~ scalaPart).map { + case (scalaNativeVersion, scalaVersion) => + ScalaNative(scalaVersion, scalaNativeVersion) } - val scalaNativeVersion = - target.flatMap(_.scalaNativeVersion.map(_.forceBinary.toString)) + private def sbt[_: P]: P[ScalaTarget] = + (scalaPart ~ "_" ~ SemanticVersion.Parser).map { + case (scalaVersion, sbtVersion) => + SbtPlugin(scalaVersion, sbtVersion) + } - val sbtVersion = - target.flatMap(_.sbtVersion.map(_.forceBinary.toString)) + private def scala[_: P]: P[ScalaTarget] = scalaPart.map(ScalaJvm) - (targetType, - fullScalaVersion, - scalaVersion, - scalaJsVersion, - scalaNativeVersion, - sbtVersion) - } + def scalaTargetParser[_: P]: P[ScalaTarget] = + scalaJs | scalaNative | sbt | scala } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala index 20be980bd..31d002eae 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala @@ -4,76 +4,62 @@ import release._ import org.scalatest._ -class ArtifactTests extends FunSpec { +class ArtifactTests extends FunSpec with Matchers { describe("parsing artifacts") { it("parses scalajs") { - assert( - Artifact("cats-core_sjs0.6_2.11") == Some( - ( - "cats-core", - ScalaTarget.scalaJs( - scalaVersion = SemanticVersion("2.11").get, - scalaJsVersion = SemanticVersion("0.6").get - ) + Artifact.parse("cats-core_sjs0.6_2.11") should contain( + Artifact( + "cats-core", + ScalaJs( + scalaVersion = SemanticVersion(2, 11), + scalaJsVersion = SemanticVersion(0, 6) ) ) ) } it("parses scala-native") { - assert( - Artifact("cats-core_native0.1_2.11") == Some( - ( - "cats-core", - ScalaTarget.scalaNative( - scalaVersion = SemanticVersion("2.11").get, - scalaNativeVersion = SemanticVersion("0.1").get - ) + Artifact.parse("cats-core_native0.1_2.11") should contain( + Artifact( + "cats-core", + ScalaNative( + scalaVersion = SemanticVersion(2, 11), + scalaNativeVersion = SemanticVersion(0, 1) ) ) ) } it("parses scala rc") { - assert( - Artifact("akka-remote-tests_2.11.0-RC4") == Some( - ( - "akka-remote-tests", - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.11.0-RC4").get - ) - ) + Artifact.parse("akka-remote-tests_2.11.0-RC4") should contain( + Artifact( + "akka-remote-tests", + ScalaJvm(SemanticVersion(2, 11, 0, ReleaseCandidate(4))) ) ) } it("parses sbt") { - assert( - Artifact("sbt-microsites_2.12_1.0") == Some( - ( - "sbt-microsites", - ScalaTarget.sbt( - scalaVersion = SemanticVersion("2.12").get, - sbtVersion = SemanticVersion("1.0").get - ) + Artifact.parse("sbt-microsites_2.12_1.0") should contain( + Artifact( + "sbt-microsites", + SbtPlugin( + scalaVersion = SemanticVersion(2, 12), + sbtVersion = SemanticVersion(1, 0) ) ) ) } it("does not parse unconventionnal") { - assert(Artifact("sparrow") == None) + Artifact.parse("sparrow") shouldBe empty } it("handles special case") { - assert( - Artifact("banana_jvm_2.11") == Some( - ( - "banana_jvm", - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.11").get - ) - ) + Artifact.parse("banana_jvm_2.11") should contain( + Artifact( + "banana_jvm", + ScalaJvm(SemanticVersion(2, 11)) ) ) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/ScalaTargetOrdering.scala b/model/src/test/scala/ch.epfl.scala.index.model/ScalaTargetOrdering.scala deleted file mode 100644 index 33fab717e..000000000 --- a/model/src/test/scala/ch.epfl.scala.index.model/ScalaTargetOrdering.scala +++ /dev/null @@ -1,43 +0,0 @@ -package ch.epfl.scala.index.model -package release - -import org.scalatest._ - -class ScalaTargetOrdering extends FunSpec { - describe("Scala Targets") { - it("has an ordering") { - val s210 = SemanticVersion("2.10.6").get - val s211 = SemanticVersion("2.11.11").get - val s212 = SemanticVersion("2.12.2").get - val js067 = SemanticVersion("0.6.7").get - val js0618 = SemanticVersion("0.6.18").get - val nat03 = SemanticVersion("0.3.0").get - - val obtained = List( - ScalaTarget.scalaJs(s211, js067), - ScalaTarget.scalaJs(s212, js0618), - ScalaTarget.scalaJs(s210, js067), - ScalaTarget.scalaJs(s211, js0618), - ScalaTarget.scalaJs(s210, js0618), - ScalaTarget.scalaNative(s211, nat03), - ScalaTarget.scala(s212), - ScalaTarget.scala(s211), - ScalaTarget.scala(s210) - ).sorted - - val expected = List( - ScalaTarget.scalaNative(s211, nat03), - ScalaTarget.scalaJs(s210, js067), - ScalaTarget.scalaJs(s210, js0618), - ScalaTarget.scalaJs(s211, js067), - ScalaTarget.scalaJs(s211, js0618), - ScalaTarget.scalaJs(s212, js0618), - ScalaTarget.scala(s210), - ScalaTarget.scala(s211), - ScalaTarget.scala(s212) - ) - - assert(obtained == expected) - } - } -} diff --git a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala index 1a890d620..d70d266f3 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala @@ -2,7 +2,7 @@ package ch.epfl.scala.index.model import org.scalatest._ -class SemanticVersionTests extends FunSpec { +class SemanticVersionTests extends FunSpec with Matchers { describe("semantic versionning") { it("has an ordering") { def order(versions: List[String]): List[SemanticVersion] = @@ -22,13 +22,17 @@ class SemanticVersionTests extends FunSpec { assert( order(versions) == List( - SemanticVersion(1, 1, Some(1)), - SemanticVersion(1, 0, Some(1)), - SemanticVersion(1, 0, Some(1), None, Some(ReleaseCandidate(2))), - SemanticVersion(1, 0, Some(1), None, Some(ReleaseCandidate(1))), - SemanticVersion(1, 0, Some(1), None, Some(Milestone(2))), - SemanticVersion(1, 0, Some(1), None, Some(Milestone(1))), - SemanticVersion(1, 0, Some(1), None, Some(OtherPreRelease("BLABLA"))) + SemanticVersion(1, 1, 1), + SemanticVersion(1, 0, 1), + SemanticVersion(1, Some(0), Some(1), None, Some(ReleaseCandidate(2))), + SemanticVersion(1, Some(0), Some(1), None, Some(ReleaseCandidate(1))), + SemanticVersion(1, Some(0), Some(1), None, Some(Milestone(2))), + SemanticVersion(1, Some(0), Some(1), None, Some(Milestone(1))), + SemanticVersion(1, + Some(0), + Some(1), + None, + Some(OtherPreRelease("BLABLA"))) ) ) } @@ -37,53 +41,53 @@ class SemanticVersionTests extends FunSpec { describe("binary") { // relaxed semantic version it("major") { - assert(binary("1") == Some("1.0")) + binary("1") should contain("1") } // relaxed semantic version it("major.minor") { - assert(binary("1.2") == Some("1.2")) + binary("1.2") should contain("1.2") } it("major.minor.patch") { - assert(binary("1.2.3") == Some("1.2")) + binary("1.2.3") should contain("1.2") } // relaxed semantic version it("major.minor.patch.patch2") { - assert(binary("1.2.3.4") == Some("1.2")) + binary("1.2.3.4") should contain("1.2") } it("major.minor.patch-rc") { - assert(binary("1.2.3-RC5") == Some("1.2.3-RC5")) + binary("1.2.3-RC5") should contain("1.2.3-RC5") } it("major.minor.patch-m") { - assert(binary("1.2.3-M6") == Some("1.2.3-M6")) + binary("1.2.3-M6") should contain("1.2.3-M6") } it("major.minor.patch-xyz") { - assert(binary("1.1.1-xyz") == Some("1.1.1-xyz")) + binary("1.1.1-xyz") should contain("1.1.1-xyz") } it("major.minor.patch+meta") { - assert(binary("1.1.1+some.meta~data") == Some("1.1")) + binary("1.1.1+some.meta~data") should contain("1.1") } it("git commit") { - assert(binary("13e7afa9c1817d45b2989e545b2e9ead21d00cef") == None) + binary("13e7afa9c1817d45b2989e545b2e9ead21d00cef") shouldBe empty } // relaxed semantic version it("v sufix") { - assert(binary("v1") == Some("1.0")) + binary("v1") should contain("1") } } describe("full or toString") { // relaxed semantic version it("major") { - assert(full("1") == Some("1.0")) + full("1") should contain("1") } // relaxed semantic version @@ -122,7 +126,7 @@ class SemanticVersionTests extends FunSpec { // relaxed semantic version it("v sufix") { - assert(full("v1") == Some("1.0")) + full("v1") should contain("1") } } } @@ -130,77 +134,66 @@ class SemanticVersionTests extends FunSpec { describe("parsing") { // relaxed semantic version it("major") { - assert(parseVersion("1") == Some(SemanticVersion(1))) + parseVersion("1") should contain(SemanticVersion(1)) } // relaxed semantic version it("major.minor") { - assert(parseVersion("1.2") == Some(SemanticVersion(1, 2))) + parseVersion("1.2") should contain(SemanticVersion(1, 2)) } it("major.minor.patch") { - assert(parseVersion("1.2.3") == Some(SemanticVersion(1, 2, Some(3)))) + parseVersion("1.2.3") should contain(SemanticVersion(1, 2, 3)) } // relaxed semantic version it("major.minor.patch.patch2") { - assert( - parseVersion("1.2.3.4") == Some( - SemanticVersion(1, 2, Some(3), Some(4)) - ) + parseVersion("1.2.3.4") should contain( + SemanticVersion(1, 2, 3, 4) ) } it("major.minor.patch-rc") { - assert( - parseVersion("1.2.3-RC5") == Some( - SemanticVersion(1, 2, Some(3), None, Some(ReleaseCandidate(5))) - ) + parseVersion("1.2.3-RC5") should contain( + SemanticVersion(1, 2, 3, ReleaseCandidate(5)) ) + } it("major.minor.patch-m") { - assert( - parseVersion("1.2.3-M6") == Some( - SemanticVersion(1, 2, Some(3), None, Some(Milestone(6))) - ) + parseVersion("1.2.3-M6") should contain( + SemanticVersion(1, 2, 3, Milestone(6)) ) } it("major.minor.patch-xyz") { - assert( - parseVersion("1.1.1-xyz") == Some( - SemanticVersion(1, 1, Some(1), None, Some(OtherPreRelease("xyz"))) - ) + parseVersion("1.1.1-xyz") should contain( + SemanticVersion(1, + Some(1), + Some(1), + None, + Some(OtherPreRelease("xyz"))) ) } it("major.minor.patch+meta") { - assert( - parseVersion("1.1.1+some.meta~data") == Some( - SemanticVersion( - major = 1, - minor = 1, - patch = Some(1), - patch2 = None, - preRelease = None, - metadata = Some("some.meta~data") - ) + parseVersion("1.1.1+some.meta~data") should contain( + SemanticVersion( + major = 1, + minor = Some(1), + patch = Some(1), + metadata = Some("some.meta~data") ) ) } it("git commit") { - assert( - parseVersion("13e7afa9c1817d45b2989e545b2e9ead21d00cef") == None - ) + parseVersion("13e7afa9c1817d45b2989e545b2e9ead21d00cef") shouldBe empty } // relaxed semantic version it("v sufix") { - assert( - parseVersion("v1") == Some(SemanticVersion(1)) - ) + parseVersion("v1") should contain(SemanticVersion(1)) } } } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala index 94fd795f1..fe437378b 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala @@ -3,7 +3,7 @@ package release import org.scalatest._ -class DefaultReleaseTests extends FunSpec { +class DefaultReleaseTests extends FunSpec with Matchers { def emptyRelease(maven: MavenReference, reference: Release.Reference): Release = @@ -33,12 +33,12 @@ class DefaultReleaseTests extends FunSpec { def prepare(organization: String, repository: String, groupdId: String, - releases: List[(String, String)]) = { + releases: List[(String, String)]): Set[Release] = { releases .flatMap { case (artifactId, rawVersion) => for { - (artifact, target) <- Artifact(artifactId) + Artifact(artifact, target) <- Artifact.parse(artifactId) version <- SemanticVersion(rawVersion) } yield (artifactId, rawVersion, artifact, target, version) } @@ -95,7 +95,11 @@ class DefaultReleaseTests extends FunSpec { ) val result = - DefaultRelease(repository, ReleaseSelection.empty, releases, None, true) + DefaultRelease(repository, + ReleaseSelection.empty, + releases, + None, + defaultStableVersion = true) val versions: List[SemanticVersion] = List( @@ -109,12 +113,10 @@ class DefaultReleaseTests extends FunSpec { val targets: List[ScalaTarget] = List( - ScalaTarget.scalaJs(SemanticVersion("2.11").get, - SemanticVersion("0.6").get), - ScalaTarget.scalaJs(SemanticVersion("2.10").get, - SemanticVersion("0.6").get), - ScalaTarget.scala(SemanticVersion("2.11").get), - ScalaTarget.scala(SemanticVersion("2.10").get) + ScalaJs(SemanticVersion("2.11").get, SemanticVersion("0.6").get), + ScalaJs(SemanticVersion("2.10").get, SemanticVersion("0.6").get), + ScalaJvm(SemanticVersion("2.11").get), + ScalaJvm(SemanticVersion("2.10").get) ) val expected: Option[ReleaseOptions] = @@ -132,13 +134,13 @@ class DefaultReleaseTests extends FunSpec { repository, "cats-core", SemanticVersion("0.6.0").get, - Some(ScalaTarget.scala(SemanticVersion("2.11").get)) + Some(ScalaJvm(SemanticVersion("2.11").get)) ) ) ) ) - assert(expected == result) + result shouldBe expected } it("selected artifact") { @@ -164,7 +166,7 @@ class DefaultReleaseTests extends FunSpec { ), releases, None, - true + defaultStableVersion = true ) val expected = @@ -178,7 +180,7 @@ class DefaultReleaseTests extends FunSpec { SemanticVersion("2.4.8").get ), targets = List( - ScalaTarget.scala(SemanticVersion("2.11").get) + ScalaJvm(SemanticVersion("2.11").get) ), release = emptyRelease( MavenReference(groupdId, @@ -189,7 +191,7 @@ class DefaultReleaseTests extends FunSpec { repository, "akka-distributed-data-experimental", SemanticVersion("2.4.8").get, - Some(ScalaTarget.scala(SemanticVersion("2.11").get)) + Some(ScalaJvm(SemanticVersion("2.11").get)) ) ) ) @@ -215,7 +217,11 @@ class DefaultReleaseTests extends FunSpec { ) val result = - DefaultRelease(repository, ReleaseSelection.empty, releases, None, true) + DefaultRelease(repository, + ReleaseSelection.empty, + releases, + None, + defaultStableVersion = true) val versions: List[SemanticVersion] = List( @@ -225,8 +231,8 @@ class DefaultReleaseTests extends FunSpec { val targets: List[ScalaTarget] = List( - ScalaTarget.scala(SemanticVersion("2.12.2").get), - ScalaTarget.scala(SemanticVersion("2.12").get) + ScalaJvm(SemanticVersion("2.12.2").get), + ScalaJvm(SemanticVersion("2.12").get) ) val expected: Option[ReleaseOptions] = @@ -244,7 +250,7 @@ class DefaultReleaseTests extends FunSpec { repository, "scalafix-core", SemanticVersion("0.5.3").get, - Some(ScalaTarget.scala(SemanticVersion("2.12").get)) + Some(ScalaJvm(SemanticVersion("2.12").get)) ) ) ) diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala index 556e82163..95a6013cf 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala @@ -12,8 +12,8 @@ class MillInstallTests extends FunSuite with TestHelpers { artifactId = "http4s-core_2.12", artifactName = "http4s-core", target = Some( - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.12.3").get + ScalaJvm( + scalaVersion = SemanticVersion(2, 12, 3) ) ) ).millInstall @@ -32,8 +32,8 @@ class MillInstallTests extends FunSuite with TestHelpers { version = "0.8.2", artifactName = "doodle", target = Some( - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.11").get + ScalaJvm( + scalaVersion = SemanticVersion(2, 11) ) ), resolver = Some(BintrayResolver("noelwelsh", "maven")) diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala index d908f06e1..7f45c0e35 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala @@ -12,8 +12,8 @@ class SbtInstallTests extends FunSuite with TestHelpers { version = "2.1.1", artifactName = "paradise", target = Some( - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.12.3").get + ScalaJvm( + scalaVersion = SemanticVersion(2, 12, 3) ) ) ).sbtInstall @@ -32,8 +32,8 @@ class SbtInstallTests extends FunSuite with TestHelpers { version = "7.2.14", artifactName = "scalaz-core", target = Some( - ScalaTarget.scala( - scalaVersion = SemanticVersion("2.13.0-M1").get + ScalaJvm( + scalaVersion = SemanticVersion(2, 13, 0, Milestone(1)) ) ) ).sbtInstall @@ -52,9 +52,9 @@ class SbtInstallTests extends FunSuite with TestHelpers { version = "0.9.3", artifactName = "scalajs-dom", target = Some( - ScalaTarget.scalaJs( - scalaVersion = SemanticVersion("2.12").get, - scalaJsVersion = SemanticVersion("0.6").get + ScalaJs( + scalaVersion = SemanticVersion(2, 12), + scalaJsVersion = SemanticVersion(0, 6) ) ) ).sbtInstall @@ -73,9 +73,9 @@ class SbtInstallTests extends FunSuite with TestHelpers { version = "1.2.2", artifactName = "sbt-native-packager", target = Some( - ScalaTarget.sbt( - scalaVersion = SemanticVersion("2.10").get, - sbtVersion = SemanticVersion("0.13").get + SbtPlugin( + scalaVersion = SemanticVersion(2, 10), + sbtVersion = SemanticVersion(0, 13) ) ) ).sbtInstall @@ -94,7 +94,7 @@ class SbtInstallTests extends FunSuite with TestHelpers { version = "0.8.2", artifactName = "doodle", target = Some( - ScalaTarget.scala( + ScalaJvm( scalaVersion = SemanticVersion("2.11").get ) ), diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala new file mode 100644 index 000000000..76374058f --- /dev/null +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala @@ -0,0 +1,43 @@ +package ch.epfl.scala.index.model +package release + +import org.scalatest._ + +class ScalaTargetOrdering extends FunSpec { + describe("Scala Targets") { + it("has an ordering") { + val s210 = SemanticVersion("2.10.6").get + val s211 = SemanticVersion("2.11.11").get + val s212 = SemanticVersion("2.12.2").get + val js067 = SemanticVersion("0.6.7").get + val js0618 = SemanticVersion("0.6.18").get + val nat03 = SemanticVersion("0.3.0").get + + val obtained = List( + ScalaJs(s211, js067), + ScalaJs(s212, js0618), + ScalaJs(s210, js067), + ScalaJs(s211, js0618), + ScalaJs(s210, js0618), + ScalaNative(s211, nat03), + ScalaJvm(s212), + ScalaJvm(s211), + ScalaJvm(s210) + ).sorted(ScalaTarget.ordering) + + val expected = List( + ScalaNative(s211, nat03), + ScalaJs(s210, js067), + ScalaJs(s210, js0618), + ScalaJs(s211, js067), + ScalaJs(s211, js0618), + ScalaJs(s212, js0618), + ScalaJvm(s210), + ScalaJvm(s211), + ScalaJvm(s212) + ) + + assert(obtained == expected) + } + } +} diff --git a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala index efb4afec4..90923d659 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala @@ -225,16 +225,22 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getScalaVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("scalaVersion", filteredSearchQuery(params), filterScalaVersion) + versionAggregations("scalaVersion", + filteredSearchQuery(params), + filterScalaVersion) .map(addLabelsIfMissing(params.scalaVersions.toSet)) } def getAllScalaJsVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaJsVersion", notDeprecatedQuery, filterScalaJsVersion) + versionAggregations("scalaJsVersion", + notDeprecatedQuery, + filterScalaJsVersion) } def getScalaJsVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("scalaJsVersion", filteredSearchQuery(params), filterScalaJsVersion) + versionAggregations("scalaJsVersion", + filteredSearchQuery(params), + filterScalaJsVersion) .map(addLabelsIfMissing(params.scalaJsVersions.toSet)) } @@ -256,7 +262,9 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getSbtVersions(params: SearchParams): Future[List[(String, Long)]] = { - versionAggregations("sbtVersion", filteredSearchQuery(params), filterSbtVersion) + versionAggregations("sbtVersion", + filteredSearchQuery(params), + filterSbtVersion) .map(addLabelsIfMissing(params.sbtVersions.toSet)) } @@ -510,18 +518,25 @@ object DataRepository { } private def targetQuery(target: ScalaTarget): QueryDefinition = { - must( - termQuery("scalaVersion", target.scalaVersion.toString), - optionalQuery(target.scalaJsVersion) { version => - termQuery("scalaJsVersion", version.toString) - }, - optionalQuery(target.scalaNativeVersion) { version => - termQuery("scalaNativeVersion", version.toString) - }, - optionalQuery(target.sbtVersion) { version => - termQuery("sbtVersion", version.toString) - } - ) + target match { + case ScalaJvm(scalaVersion) => + termQuery("scalaVersion", scalaVersion.toString) + case ScalaJs(scalaVersion, jsVersion) => + must( + termQuery("scalaVersion", scalaVersion.toString), + termQuery("scalaJsVersion", jsVersion.toString) + ) + case ScalaNative(scalaVersion, nativeVersion) => + must( + termQuery("scalaVersion", scalaVersion.toString), + termQuery("scalaNativeVersion", nativeVersion.toString) + ) + case SbtPlugin(scalaVersion, sbtVersion) => + must( + termQuery("scalaVersion", scalaVersion.toString), + termQuery("sbtVersion", sbtVersion.toString) + ) + } } private val contributingQuery = boolQuery().must( diff --git a/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala b/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala index faf774abd..bb14e052b 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala @@ -83,28 +83,19 @@ class ProjectPages( val user = userState.map(_.info) - def showTarget(target: ScalaTarget): String = { + def showVersion(target: ScalaTarget): String = { target match { - case ScalaTarget(scalaVersion, None, None, None) => - scalaVersion.toString - - case ScalaTarget(scalaVersion, Some(scalaJsVersion), None, None) => - scalaVersion.toString - - case ScalaTarget(scalaVersion, None, Some(scalaNativeVersion), None) => - scalaNativeVersion.toString - - case ScalaTarget(scalaVersion, None, None, Some(sbtVersion)) => - sbtVersion.toString - - case _ => "" // impossible + case ScalaJvm(version) => version.toString + case ScalaJs(version, jsVersion) => s"${jsVersion}_$version" + case ScalaNative(version, nativeVersion) => s"${nativeVersion}_$version" + case SbtPlugin(version, sbtVersion) => s"${sbtVersion}_$version" } } dataRepository .getProjectAndReleases(Project.Reference(owner, repo)) .map { - case Some((project, releases)) => { + case Some((project, releases)) => val targets = releases .map(_.reference.target) @@ -114,7 +105,7 @@ class ProjectPages( target => ( target, - target.map(showTarget).getOrElse("Java") + target.map(showVersion).getOrElse("Java") ) ) .distinct @@ -140,7 +131,6 @@ class ProjectPages( (OK, views.html .artifacts(project, sortedReleases, targetTypes, targets, user)) - } case None => (NotFound, views.html.notfound(user)) } } @@ -379,11 +369,10 @@ class ProjectPages( ) case None => complete( - ((NotFound, - views.html - .notfound( - session.getUser(userId).map(_.info) - ))) + NotFound, + views.html.notfound( + session.getUser(userId).map(_.info) + ) ) } ) diff --git a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala index 84ecc0b23..af8aba5a8 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala @@ -61,28 +61,22 @@ class SearchApi( sbtVersion.flatMap(SemanticVersion.parse)) match { case (Some("JVM"), Some(scalaVersion), _, _, _) => - Some(ScalaTarget.scala(scalaVersion.binary)) + Some(ScalaJvm(scalaVersion.binary)) case (Some("JS"), Some(scalaVersion), Some(scalaJsVersion), _, _) => - Some(ScalaTarget.scalaJs(scalaVersion.binary, scalaJsVersion.binary)) + Some(ScalaJs(scalaVersion.binary, scalaJsVersion.binary)) case (Some("NATIVE"), Some(scalaVersion), _, Some(scalaNativeVersion), _) => - Some( - ScalaTarget.scalaNative(scalaVersion.binary, - scalaNativeVersion.binary) - ) + Some(ScalaNative(scalaVersion.binary, scalaNativeVersion.binary)) case (Some("SBT"), Some(scalaVersion), _, _, Some(sbtVersion)) => - Some( - ScalaTarget.sbt(scalaVersion.binary, sbtVersion.binary) - ) + Some(SbtPlugin(scalaVersion.binary, sbtVersion.binary)) - case _ => - None + case _ => None } } diff --git a/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala b/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala index 67c8ed1d5..f626ccf8f 100644 --- a/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala +++ b/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala @@ -3,20 +3,16 @@ package server import model.Project import model.misc.SearchParams -import model.release.ScalaTarget +import model.release.{ScalaJs, ScalaNative, ScalaTarget} import model.SemanticVersion - import data.DataPaths import data.elastic._ import data.github.GithubDownload - import org.scalatest._ import scala.concurrent.Future - import akka.actor.ActorSystem import akka.stream.ActorMaterializer - import akka.testkit.TestKit class RelevanceTest @@ -112,9 +108,9 @@ class RelevanceTest test("Scala.js targetFiltering") { val scalaJs = - ScalaTarget.scalaJs( - scalaVersion = SemanticVersion("2.12").get, - scalaJsVersion = SemanticVersion("0.6").get + ScalaJs( + scalaVersion = SemanticVersion(2, 12), + scalaJsVersion = SemanticVersion(0, 6) ) top( @@ -127,9 +123,9 @@ class RelevanceTest test("Scala.js targetFiltering (2)") { val scalaJs = - ScalaTarget.scalaJs( - scalaVersion = SemanticVersion("2.12").get, - scalaJsVersion = SemanticVersion("0.6").get + ScalaJs( + scalaVersion = SemanticVersion(2, 12), + scalaJsVersion = SemanticVersion(0, 6) ) compare( @@ -153,9 +149,9 @@ class RelevanceTest test("Scala Native targetFiltering") { val scalaNative = - ScalaTarget.scalaNative( - scalaVersion = SemanticVersion("2.11").get, - scalaNativeVersion = SemanticVersion("0.3").get + ScalaNative( + scalaVersion = SemanticVersion(2, 11), + scalaNativeVersion = SemanticVersion(0, 3) ) top( From 35e0a4cd171b895762c9bbd5831dbdaf1241f92f Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 2 Apr 2020 16:21:33 +0200 Subject: [PATCH 03/10] filter out invalid sbt and scala.js versions from result list --- .../release/ScalaTarget.scala | 20 +++++++++++ .../DataRepository.scala | 35 ++++++------------- .../ch.epfl.scala.index.views/package.scala | 5 ++- .../search/resultList.scala.html | 9 ++--- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index ccea2088c..29bca53dc 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -82,6 +82,26 @@ object ScalaTarget extends Parsers { tryParse(code, x => scalaTargetParser(x)) } + private val minScalaVersion = SemanticVersion(2, 10) + private val maxScalaVersion = SemanticVersion(2, 13) + + def isValidScalaVersion(version: SemanticVersion): Boolean = { + version >= minScalaVersion && version <= maxScalaVersion + } + + private def minScalaJsVersion = SemanticVersion(0, 6) + + def isValidScalaJsVersion(version: SemanticVersion): Boolean = { + minScalaJsVersion <= version + } + + private def minSbtVersion = SemanticVersion(0, 11) + private def maxSbtVersion = SemanticVersion(1, 3) + + def isValidSbtVersion(version: SemanticVersion): Boolean = { + minSbtVersion <= version && version <= maxSbtVersion + } + import fastparse.NoWhitespace._ import fastparse._ diff --git a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala index 90923d659..1c45bf76d 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala @@ -221,26 +221,28 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getAllScalaVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaVersion", notDeprecatedQuery, filterScalaVersion) + versionAggregations("scalaVersion", + notDeprecatedQuery, + ScalaTarget.isValidScalaVersion) } def getScalaVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("scalaVersion", filteredSearchQuery(params), - filterScalaVersion) + ScalaTarget.isValidScalaVersion) .map(addLabelsIfMissing(params.scalaVersions.toSet)) } def getAllScalaJsVersions(): Future[List[(String, Long)]] = { versionAggregations("scalaJsVersion", notDeprecatedQuery, - filterScalaJsVersion) + ScalaTarget.isValidScalaJsVersion) } def getScalaJsVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("scalaJsVersion", filteredSearchQuery(params), - filterScalaJsVersion) + ScalaTarget.isValidScalaJsVersion) .map(addLabelsIfMissing(params.scalaJsVersions.toSet)) } @@ -258,13 +260,15 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getAllSbtVersions(): Future[List[(String, Long)]] = { - versionAggregations("sbtVersion", notDeprecatedQuery, filterSbtVersion) + versionAggregations("sbtVersion", + notDeprecatedQuery, + ScalaTarget.isValidSbtVersion) } def getSbtVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("sbtVersion", filteredSearchQuery(params), - filterSbtVersion) + ScalaTarget.isValidSbtVersion) .map(addLabelsIfMissing(params.sbtVersions.toSet)) } @@ -579,25 +583,6 @@ object DataRepository { } private val frontPageCount = 12 - private val minScalaVersion = SemanticVersion(2, 10) - private val maxScalaVersion = SemanticVersion(2, 13) - - private def filterScalaVersion(version: SemanticVersion): Boolean = { - minScalaVersion <= version && version <= maxScalaVersion - } - - private def minSbtVersion = SemanticVersion(0, 11) - private def maxSbtVersion = SemanticVersion(1, 3) - - private def filterSbtVersion(version: SemanticVersion): Boolean = { - minSbtVersion <= version && version <= maxSbtVersion - } - - private def minScalaJsVersion = SemanticVersion(0, 6) - - private def filterScalaJsVersion(version: SemanticVersion): Boolean = { - minScalaJsVersion <= version - } private def labelizeTargetType(targetType: String): String = { if (targetType == "JVM") "Scala (Jvm)" diff --git a/template/src/main/scala/ch.epfl.scala.index.views/package.scala b/template/src/main/scala/ch.epfl.scala.index.views/package.scala index 5fb0e283b..97c05304d 100644 --- a/template/src/main/scala/ch.epfl.scala.index.views/package.scala +++ b/template/src/main/scala/ch.epfl.scala.index.views/package.scala @@ -127,11 +127,10 @@ package object html { } def sortVersions(versions: Set[String], - scala: Boolean = false): List[String] = { - val minVersion = SemanticVersion(2, 10) + filter: SemanticVersion => Boolean): List[String] = { versions.toList .flatMap(SemanticVersion.parse) - .filter(version => !scala || version >= minVersion) + .filter(filter) .sorted .map(version => SemanticVersion(version.major, version.minor).toString) .distinct diff --git a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html index 7899e825d..d8845231f 100644 --- a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html +++ b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html @@ -1,5 +1,6 @@ @import ch.epfl.scala.index.views.html._ @import ch.epfl.scala.index.model.Project +@import ch.epfl.scala.index.model.release.ScalaTarget @import ch.epfl.scala.index.model.misc.SearchParams @(projects: List[Project], params: SearchParams) @@ -26,7 +27,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaVersion.nonEmpty){
Scala (JVM): - @for(v <- sortVersions(project.scalaVersion, scala = true)) { + @for(v <- sortVersions(project.scalaVersion, ScalaTarget.isValidScalaVersion)) { @v }
@@ -35,7 +36,7 @@

@project.reference.organization/@project.reference.repository

@if(project.sbtVersion.nonEmpty){
Sbt: - @for(v <- sortVersions(project.sbtVersion)) { + @for(v <- sortVersions(project.sbtVersion, ScalaTarget.isValidSbtVersion)) { @v }
@@ -44,7 +45,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaJsVersion.nonEmpty){
Scala.js: - @for(v <- sortVersions(project.scalaJsVersion)) { + @for(v <- sortVersions(project.scalaJsVersion, ScalaTarget.isValidScalaJsVersion)) { @v }
@@ -53,7 +54,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaNativeVersion.nonEmpty){
Scala-Native: - @for(v <- sortVersions(project.scalaNativeVersion)) { + @for(v <- sortVersions(project.scalaNativeVersion, _ => true)) { @v }
From 2138fbc30cb6ad89176aa732724e0b4e0ff78bcd Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 2 Apr 2020 18:16:04 +0200 Subject: [PATCH 04/10] code review --- .../scala/ch.epfl.scala.index.model/SemanticVersion.scala | 6 +++--- .../ch.epfl.scala.index.model/release/ScalaTarget.scala | 2 ++ .../ch.epfl.scala.index.views/search/resultList.scala.html | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index 68fb9c05d..8e44a189a 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -39,8 +39,8 @@ case class SemanticVersion( override def toString: String = { val minorPart = minor.map(m => s".$m").getOrElse("") - val patchPart = patch.map("." + _).getOrElse("") - val patch2Part = patch2.map("." + _).getOrElse("") + val patchPart = patch.map(p => s".$p").getOrElse("") + val patch2Part = patch2.map(p2 => s".$p2").getOrElse("") val preReleasePart = preRelease .map { @@ -76,7 +76,7 @@ object SemanticVersion extends Parsers { case Some(OtherPreRelease(pr)) => (0, None, Some(pr)) } - implicit def ordering: Ordering[SemanticVersion] = Ordering.by { x => + implicit val ordering: Ordering[SemanticVersion] = Ordering.by { x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index 29bca53dc..7b7aa9aeb 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -102,6 +102,8 @@ object ScalaTarget extends Parsers { minSbtVersion <= version && version <= maxSbtVersion } + def isValidScalaNativeVersion(version: SemanticVersion): Boolean = true + import fastparse.NoWhitespace._ import fastparse._ diff --git a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html index d8845231f..b9ce0e6de 100644 --- a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html +++ b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html @@ -54,7 +54,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaNativeVersion.nonEmpty){
Scala-Native: - @for(v <- sortVersions(project.scalaNativeVersion, _ => true)) { + @for(v <- sortVersions(project.scalaNativeVersion, ScalaTarget.isValidScalaNativeVersion)) { @v }
From a012126b39961fdcd327624b6231e341418d942b Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Fri, 3 Apr 2020 13:38:39 +0200 Subject: [PATCH 05/10] introduce BinaryVersion --- .../scala/ch.epfl.scala.index.data/Main.scala | 23 +++-- .../central/CentralMissing.scala | 61 +++++------- .../elastic/SeedElasticSearch.scala | 1 - .../elastic/package.scala | 6 +- .../project/ArtifactMetaExtractor.scala | 50 +++++----- .../project/ProjectConvert.scala | 22 +---- .../ch.epfl.scala.index.model/Artifact.scala | 9 +- .../BinaryVersion.scala | 81 +++++++++++++++ .../ch.epfl.scala.index.model/Parsers.scala | 14 ++- .../PreRelease.scala | 40 ++++++++ .../ch.epfl.scala.index.model/Project.scala | 1 - .../ch.epfl.scala.index.model/Release.scala | 4 +- .../SemanticVersion.scala | 78 +++------------ .../release/DefaultRelease.scala | 49 +++------- .../release/ScalaTarget.scala | 68 ++++++++----- .../ArtifactTests.scala | 16 +-- .../BinaryVersionTests.scala | 28 ++++++ .../SemanticVersionTests.scala | 98 ------------------- .../release/DefaultReleaseTests.scala | 53 +++++----- .../release/MillInstallTests.scala | 4 +- .../release/SbtInstallTests.scala | 14 +-- .../release/ScalaTargetOrdering.scala | 43 -------- .../release/ScalaTargetTests.scala | 57 +++++++++++ .../release/TestHelpers.scala | 3 +- .../DataRepository.scala | 24 +++-- .../routes/api/SearchApi.scala | 16 +-- .../RelevanceTest.scala | 15 ++- .../ch.epfl.scala.index.views/package.scala | 7 +- 28 files changed, 435 insertions(+), 450 deletions(-) create mode 100644 model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala create mode 100644 model/src/main/scala/ch.epfl.scala.index.model/PreRelease.scala create mode 100644 model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala delete mode 100644 model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala create mode 100644 model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala diff --git a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala index 72b323856..dfdfde22e 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala @@ -1,22 +1,21 @@ package ch.epfl.scala.index.data -import bintray.{BintrayDownloadPoms, BintrayListPoms, BintrayDownloadSbtPlugins} -import cleanup.{NonStandardLib, GithubRepoExtractor} -import elastic.SeedElasticSearch -import github.GithubDownload -import maven.DownloadParentPoms -import util.PidLock - import java.nio.file.Path -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter - import akka.actor.ActorSystem import akka.stream.ActorMaterializer - +import ch.epfl.scala.index.data.bintray.{ + BintrayDownloadPoms, + BintrayDownloadSbtPlugins, + BintrayListPoms +} +import ch.epfl.scala.index.data.central.CentralMissing +import ch.epfl.scala.index.data.cleanup.{GithubRepoExtractor, NonStandardLib} +import ch.epfl.scala.index.data.elastic.SeedElasticSearch +import ch.epfl.scala.index.data.github.GithubDownload +import ch.epfl.scala.index.data.maven.DownloadParentPoms +import ch.epfl.scala.index.data.util.PidLock import com.typesafe.config.ConfigFactory - import org.slf4j.LoggerFactory import scala.sys.process.Process diff --git a/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala b/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala index e781afa87..61e044fea 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/central/CentralMissing.scala @@ -1,46 +1,37 @@ package ch.epfl.scala.index package data +package central -import ch.epfl.scala.index.model.Release -import ch.epfl.scala.index.model.release.{ - SbtPlugin, - ScalaJs, - ScalaJvm, - ScalaNative, - ScalaTarget -} -import ch.epfl.scala.index.model.SemanticVersion -import ch.epfl.scala.index.data.github.GithubDownload -import ch.epfl.scala.index.data.project.{ArtifactMetaExtractor, ProjectConvert} -import ch.epfl.scala.index.data.maven.PomsReader -import ch.epfl.scala.index.model.misc.Sha1 +import java.nio.charset.StandardCharsets +import java.nio.file.Files -import scala.util.{Failure, Success} -import scala.concurrent.{Await, Future, Promise} -import scala.concurrent.duration._ -import scala.util.Try -import akka.NotUsed import akka.actor.ActorSystem import akka.http.scaladsl.Http +import akka.http.scaladsl.model.Uri.Query import akka.http.scaladsl.model._ -import akka.http.scaladsl.model.ContentTypes._ import akka.http.scaladsl.model.headers._ -import akka.http.scaladsl.model.Uri.Query import akka.http.scaladsl.unmarshalling._ -import akka.stream.Materializer -import akka.stream.ThrottleMode +import akka.stream.{Materializer, ThrottleMode} import akka.stream.scaladsl._ -import akka.stream.{OverflowStrategy, QueueOfferResult} +import ch.epfl.scala.index.data.maven.PomsReader +import ch.epfl.scala.index.data.project.ArtifactMetaExtractor +import ch.epfl.scala.index.model.MinorBinary +import ch.epfl.scala.index.model.misc.Sha1 +import ch.epfl.scala.index.model.release.{ + SbtPlugin, + ScalaJs, + ScalaJvm, + ScalaNative +} import de.heikoseeberger.akkahttpjson4s.Json4sSupport._ import org.joda.time.DateTime import org.json4s._ -import org.json4s.native.JsonMethods._ import org.slf4j.LoggerFactory import scala.collection.immutable.Seq -import java.nio.file.Files -import java.nio.charset.StandardCharsets -import java.lang.reflect.InvocationTargetException +import scala.concurrent.duration._ +import scala.concurrent.{Await, Future} +import scala.util.{Failure, Success, Try} object CentralMissing { // q = g:"com.47deg" AND a:"sbt-microsites" @@ -260,14 +251,14 @@ class CentralMissing(paths: DataPaths)(implicit val materializer: Materializer, .flatten .toSet - val scala213 = SemanticVersion("2.13").get - val scala212 = SemanticVersion("2.12").get - val scala211 = SemanticVersion("2.11").get - val scala210 = SemanticVersion("2.10").get - val sbt013 = SemanticVersion("0.13").get - val sbt10 = SemanticVersion("1.0").get - val scalaJs06 = SemanticVersion("0.6").get - val native03 = SemanticVersion("0.3").get + val scala213 = MinorBinary(2, 13) + val scala212 = MinorBinary(2, 12) + val scala211 = MinorBinary(2, 11) + val scala210 = MinorBinary(2, 10) + val sbt013 = MinorBinary(0, 13) + val sbt10 = MinorBinary(1, 0) + val scalaJs06 = MinorBinary(0, 6) + val native03 = MinorBinary(0, 3) val allTargets = List( ScalaJvm(scala213), diff --git a/data/src/main/scala/ch.epfl.scala.index.data/elastic/SeedElasticSearch.scala b/data/src/main/scala/ch.epfl.scala.index.data/elastic/SeedElasticSearch.scala index 71416456d..5c345b891 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/elastic/SeedElasticSearch.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/elastic/SeedElasticSearch.scala @@ -87,7 +87,6 @@ class SeedElasticSearch(paths: DataPaths, githubDownload: GithubDownload)( ), keywordField("version"), keywordField("targetType") normalizer "lowercase", - keywordField("fullScalaVersion") normalizer "lowercase", keywordField("scalaVersion"), keywordField("scalaJsVersion"), keywordField("scalaNativeVersion"), diff --git a/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala b/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala index b3a7ac33c..a72dd88db 100755 --- a/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/elastic/package.scala @@ -31,7 +31,11 @@ trait ProjectProtocol { classOf[ScalaJvm], classOf[ScalaJs], classOf[ScalaNative], - classOf[SbtPlugin] + classOf[SbtPlugin], + classOf[MajorBinary], + classOf[MinorBinary], + classOf[PatchBinary], + classOf[PreReleaseBinary] ) ) ) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala index d45baa96d..64ac71792 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala @@ -4,7 +4,7 @@ package project import cleanup._ import model.release.{SbtPlugin, ScalaJvm, ScalaTarget} -import model.{Artifact, SemanticVersion} +import model.{Artifact, BinaryVersion, SemanticVersion} import maven.{ReleaseModel, SbtPluginTarget} import org.slf4j.LoggerFactory @@ -36,12 +36,12 @@ class ArtifactMetaExtractor(paths: DataPaths) { .map(_.lookup) nonStandardLookup match { - case None => { + case None => pom.sbtPluginTarget match { // This is a usual Scala library (whose artifact name is suffixed by the Scala binary version) // For example: akka-actors_2.12 - case None => { + case None => Artifact.parse(pom.artifactId).map { case Artifact(artifactName, target) => ArtifactMeta( @@ -50,14 +50,15 @@ class ArtifactMetaExtractor(paths: DataPaths) { isNonStandard = false ) } - } // Or it can be an sbt-plugin published as a maven style. In such a case the Scala target // is not suffixed to the artifact name but can be found in the model’s `sbtPluginTarget` member. - case Some(SbtPluginTarget(rawScalaVersion, rawSbtVersion)) => { - SemanticVersion(rawScalaVersion).zip( - SemanticVersion(rawSbtVersion) - ) match { + case Some(SbtPluginTarget(rawScalaVersion, rawSbtVersion)) => + BinaryVersion + .parse(rawScalaVersion) + .zip( + BinaryVersion.parse(rawSbtVersion) + ) match { case List((scalaVersion, sbtVersion)) => Some( ArtifactMeta( @@ -66,37 +67,32 @@ class ArtifactMetaExtractor(paths: DataPaths) { isNonStandard = false ) ) - case _ => { + case _ => log.error("Unable to decode the Scala target") None - } } - } } - } // For example: io.gatling - case Some(ScalaTargetFromPom) => { + case Some(ScalaTargetFromPom) => pom.dependencies .find( dep => dep.groupId == "org.scala-lang" && dep.artifactId == "scala-library" ) - .flatMap(dep => SemanticVersion(dep.version)) - .map( - version => - // we assume binary compatibility - ArtifactMeta( - artifactName = pom.artifactId, - scalaTarget = Some(ScalaJvm(version.copy(patch = None))), - isNonStandard = true + .flatMap(dep => SemanticVersion.parse(dep.version)) + .map { version => + // we assume binary compatibility + ArtifactMeta( + artifactName = pom.artifactId, + scalaTarget = Some(ScalaJvm.fromFullVersion(version)), + isNonStandard = true ) - ) - } + } // For example: typesafe config - case Some(NoScalaTargetPureJavaDependency) => { + case Some(NoScalaTargetPureJavaDependency) => Some( ArtifactMeta( artifactName = pom.artifactId, @@ -104,19 +100,17 @@ class ArtifactMetaExtractor(paths: DataPaths) { isNonStandard = true ) ) - } // For example: scala-compiler - case Some(ScalaTargetFromVersion) => { + case Some(ScalaTargetFromVersion) => SemanticVersion(pom.version).map( version => ArtifactMeta( artifactName = pom.artifactId, - scalaTarget = Some(ScalaJvm(version)), + scalaTarget = Some(ScalaJvm.fromFullVersion(version)), isNonStandard = true ) ) - } } } } diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala index 66430d810..66f872323 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala @@ -25,7 +25,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) /** * @param pomsRepoSha poms and associated meta information reference * @param stored read user update projects from disk - * @param cachedReleases use previous released cached to workarround elasticsearch consistency (write, read) + * @param cachedReleases use previous released cached to workaround elasticsearch consistency (write, read) */ def apply( pomsRepoSha: List[(ReleaseModel, LocalRepository, String)], @@ -139,19 +139,10 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) reverseDependencies = Seq(), internalDependencies = Seq(), targetType = targetType.toString, - // for artifact publish with binary, full will return binary - // ex cats_2.11 => 2.11 - fullScalaVersion = scalaVersion.map(_.toString), - scalaVersion = scalaVersion.map(_.forceBinary.toString), - scalaJsVersion = scalaJsVersion.map { - case SemanticVersion(0, minor, _, _, _, _) => - SemanticVersion(0, minor).toString - case SemanticVersion(major, _, _, _, _, _) => - SemanticVersion(major).toString - }, - scalaNativeVersion = - scalaNativeVersion.map(_.forceBinary.toString), - sbtVersion = sbtVersion.map(_.forceBinary.toString) + scalaVersion = scalaVersion.map(_.toString), + scalaJsVersion = scalaJsVersion.map(_.toString), + scalaNativeVersion = scalaNativeVersion.map(_.toString), + sbtVersion = sbtVersion.map(_.toString) ) }.toSet ++ cachedReleasesForProject @@ -322,7 +313,6 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) val project = seed.toProject( targetType = releases.map(_.targetType), - fullScalaVersion = releases.flatMap(_.fullScalaVersion), scalaVersion = releases.flatMap(_.scalaVersion), scalaJsVersion = releases.flatMap(_.scalaJsVersion), scalaNativeVersion = releases.flatMap(_.scalaNativeVersion), @@ -369,7 +359,6 @@ object ProjectConvert { Project.Reference(organization, repository) def toProject(targetType: Set[String], - fullScalaVersion: Set[String], scalaVersion: Set[String], scalaJsVersion: Set[String], scalaNativeVersion: Set[String], @@ -386,7 +375,6 @@ object ProjectConvert { created = created, updated = updated, targetType = targetType, - fullScalaVersion = fullScalaVersion, scalaVersion = scalaVersion, scalaJsVersion = scalaJsVersion, scalaNativeVersion = scalaNativeVersion, diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala b/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala index 682ed553b..9988423a7 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Artifact.scala @@ -1,6 +1,5 @@ package ch.epfl.scala.index.model -import ch.epfl.scala.index.model.release.ScalaTarget.scalaTargetParser import fastparse._ import release.ScalaTarget @@ -9,16 +8,16 @@ case class Artifact(name: String, target: ScalaTarget) object Artifact extends Parsers { import fastparse.NoWhitespace._ - private def artifactNameParser[_: P] = { + private def FullParser[_: P] = { Start ~ - (Alpha | Digit | "-".! | ".".! | (!(scalaTargetParser ~ End) ~ "_")).rep.! ~ // must end with scala target - scalaTargetParser ~ + (Alpha | Digit | "-".! | ".".! | (!(ScalaTarget.Parser ~ End) ~ "_")).rep.! ~ // must end with scala target + ScalaTarget.Parser ~ End }.map { case (name, target) => Artifact(name, target) } def parse(artifactId: String): Option[Artifact] = { - tryParse(artifactId, x => artifactNameParser(x)) + tryParse(artifactId, x => FullParser(x)) } } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala new file mode 100644 index 000000000..95238f43b --- /dev/null +++ b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala @@ -0,0 +1,81 @@ +package ch.epfl.scala.index.model + +sealed trait BinaryVersion extends Ordered[BinaryVersion] { + override def compare(that: BinaryVersion): Int = { + BinaryVersion.ordering.compare(this, that) + } +} + +final case class MajorBinary(major: Int) extends BinaryVersion { + override def toString: String = s"$major.x" +} + +final case class MinorBinary(major: Int, minor: Int) extends BinaryVersion { + override def toString: String = s"$major.$minor" +} + +final case class PatchBinary(major: Int, minor: Int, patch: Int) + extends BinaryVersion { + override def toString: String = s"$major.$minor.$patch" +} + +final case class PreReleaseBinary(major: Int, + minor: Int, + patch: Option[Int], + preRelease: PreRelease) + extends BinaryVersion { + override def toString: String = { + val patchPart = patch.map(p => s".$p").getOrElse("") + s"$major.$minor$patchPart-$preRelease" + } +} + +object BinaryVersion extends Parsers { + import fastparse._ + import fastparse.NoWhitespace._ + + // Major > Minor > Patch > PreRelease + implicit val ordering: Ordering[BinaryVersion] = Ordering.by { + case MajorBinary(major) => (3, major, None, None, None) + case MinorBinary(major, minor) => (2, major, Some(minor), None, None) + case PatchBinary(major, minor, patch) => + (1, major, Some(minor), Some(patch), None) + case PreReleaseBinary(major, minor, patch, preRelease) => + (0, major, Some(minor), patch, Some(preRelease)) + } + + def parse(input: String): Option[BinaryVersion] = { + tryParse(input, x => FullParser(x)) + } + + def Parser[_: P]: P[BinaryVersion] = { + MajorParser | MinorParser | PatchParser | PreReleaseParser + } + + private def FullParser[_: P]: P[BinaryVersion] = Parser ~ End + + private def MajorParser[_: P]: P[MajorBinary] = { + (Number ~ ".x".? ~ !".").map(MajorBinary) + } + + private def MinorParser[_: P]: P[MinorBinary] = { + (Number ~ "." ~ Number ~ !("." | "-")).map { + case (major, minor) => + MinorBinary(major, minor) + } + } + + private def PatchParser[_: P]: P[PatchBinary] = { + (Number ~ "." ~ Number ~ "." ~ Number ~ !"-").map { + case (major, minor, patch) => + PatchBinary(major, minor, patch) + } + } + + private def PreReleaseParser[_: P]: P[PreReleaseBinary] = { + (Number ~ "." ~ Number ~ ("." ~ Number).? ~ "-" ~ PreRelease.Parser).map { + case (major, minor, patch, preRelease) => + PreReleaseBinary(major, minor, patch, preRelease) + } + } +} diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala b/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala index 78da50e7d..aad426900 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Parsers.scala @@ -1,13 +1,21 @@ package ch.epfl.scala.index.model +import ch.epfl.scala.index.model.SemanticVersion.Digit + trait Parsers { import fastparse._ - protected def Alpha[_: P] = + protected def Alpha[_: P]: P[String] = CharPred(c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')).! - protected def Digit[_: P] = CharIn("0123456789").! + protected def Digit[_: P]: P[String] = CharIn("0123456789").! + + protected def Number[_: P]: P[Int] = { + import NoWhitespace._ + Digit.rep(1).!.map(_.toInt) + } - def tryParse[T](input: ParserInputSource, parser: P[_] => P[T]): Option[T] = { + protected def tryParse[T](input: ParserInputSource, + parser: P[_] => P[T]): Option[T] = { fastparse.parse(input, parser) match { case Parsed.Success(v, _) => Some(v) case _ => None diff --git a/model/src/main/scala/ch.epfl.scala.index.model/PreRelease.scala b/model/src/main/scala/ch.epfl.scala.index.model/PreRelease.scala new file mode 100644 index 000000000..0be1dde9e --- /dev/null +++ b/model/src/main/scala/ch.epfl.scala.index.model/PreRelease.scala @@ -0,0 +1,40 @@ +package ch.epfl.scala.index.model + +import ch.epfl.scala.index.model.SemanticVersion.Digit +import fastparse.{&, P} + +sealed trait PreRelease { + def isSemantic: Boolean +} +case class ReleaseCandidate(rc: Int) extends PreRelease { + def isSemantic: Boolean = true + override def toString: String = s"RC$rc" +} +case class Milestone(m: Int) extends PreRelease { + def isSemantic: Boolean = true + override def toString: String = s"M$m" +} +case class OtherPreRelease(o: String) extends PreRelease { + def isSemantic: Boolean = false + override def toString: String = o +} + +object PreRelease extends Parsers { + implicit val preReleaseOrdering: Ordering[Option[PreRelease]] = + Ordering.by { + case None => (3, None, None) + case Some(ReleaseCandidate(rc)) => (2, Some(rc), None) + case Some(Milestone(m)) => (1, Some(m), None) + case Some(OtherPreRelease(pr)) => (0, None, Some(pr)) + } + + import fastparse._ + import fastparse.NoWhitespace._ + + // http://semver.org/#spec-item-9 + def Parser[_: P]: P[PreRelease] = + (("M" | "m") ~ &(Digit) ~ Number).map(n => Milestone(n)) | + (("R" | "r") ~ ("C" | "c") ~ &(Digit) ~ Number) + .map(n => ReleaseCandidate(n)) | + (Digit | Alpha | "." | "-").rep.!.map(s => OtherPreRelease(s)) +} diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Project.scala b/model/src/main/scala/ch.epfl.scala.index.model/Project.scala index 617b94c63..cfdd53198 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Project.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Project.scala @@ -54,7 +54,6 @@ case class Project( created: Option[String], updated: Option[String], targetType: Set[String], - fullScalaVersion: Set[String], scalaVersion: Set[String], scalaJsVersion: Set[String], scalaNativeVersion: Set[String], diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala index 3172fefc7..ef49fb762 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala @@ -37,7 +37,6 @@ case class Release( internalDependencies: Seq[ScalaDependency], // this part for elasticsearch search targetType: String, // JVM, JS, Native, JAVA, SBT - fullScalaVersion: Option[String], scalaVersion: Option[String], scalaJsVersion: Option[String], scalaNativeVersion: Option[String], @@ -56,8 +55,7 @@ case class Release( s"""libraryDependencies += "${maven.groupId}" % "${reference.artifact}" % "${reference.version}"""" case Some(ScalaJs(_, _) | ScalaNative(_, _)) => s"""libraryDependencies += "${maven.groupId}" %%% "${reference.artifact}" % "${reference.version}"""" - case Some(ScalaJvm(version)) - if version.patch.isDefined && version.preRelease.isEmpty => + case Some(ScalaJvm(version: PatchBinary)) => s"""libraryDependencies += "${maven.groupId}" % "${reference.artifact}" % "${reference.version}" cross CrossVersion.full""" case _ => s"""libraryDependencies += "${maven.groupId}" %% "${reference.artifact}" % "${reference.version}"""" diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index 8e44a189a..b6054b10c 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -1,18 +1,5 @@ package ch.epfl.scala.index.model -sealed trait PreRelease { - def isSemantic: Boolean -} -case class ReleaseCandidate(rc: Long) extends PreRelease { - def isSemantic: Boolean = true -} -case class Milestone(m: Long) extends PreRelease { - def isSemantic: Boolean = true -} -case class OtherPreRelease(o: String) extends PreRelease { - def isSemantic: Boolean = false -} - /** * Semantic version, separation of possible combinations * @param major the major version number @@ -23,10 +10,10 @@ case class OtherPreRelease(o: String) extends PreRelease { * @param metadata the release metadata */ case class SemanticVersion( - major: Long, - minor: Option[Long] = None, - patch: Option[Long] = None, - patch2: Option[Long] = None, + major: Int, + minor: Option[Int] = None, + patch: Option[Int] = None, + patch2: Option[Int] = None, preRelease: Option[PreRelease] = None, metadata: Option[String] = None ) extends Ordered[SemanticVersion] { @@ -41,63 +28,36 @@ case class SemanticVersion( val minorPart = minor.map(m => s".$m").getOrElse("") val patchPart = patch.map(p => s".$p").getOrElse("") val patch2Part = patch2.map(p2 => s".$p2").getOrElse("") - - val preReleasePart = preRelease - .map { - case Milestone(d) => "M" + d.toString - case ReleaseCandidate(d) => "RC" + d.toString - case OtherPreRelease(v) => v.toString - } - .map("-" + _) - .getOrElse("") - - val metadataPart = metadata.map("+" + _).getOrElse("") - - major + minorPart + patchPart + patch2Part + preReleasePart + metadataPart + val preReleasePart = preRelease.map(r => s"-$r").getOrElse("") + val metadataPart = metadata.map(m => s"+$m").getOrElse("") + s"$major$minorPart$patchPart$patch2Part$preReleasePart$metadataPart" } - def binary: SemanticVersion = - if (preRelease.nonEmpty) this - else forceBinary - - def forceBinary: SemanticVersion = SemanticVersion(major, minor) - override def compare(that: SemanticVersion): PageIndex = { SemanticVersion.ordering.compare(this, that) } } object SemanticVersion extends Parsers { - private implicit val preReleaseOrdering: Ordering[Option[PreRelease]] = - Ordering.by { - case None => (3, None, None) - case Some(ReleaseCandidate(rc)) => (2, Some(rc), None) - case Some(Milestone(m)) => (1, Some(m), None) - case Some(OtherPreRelease(pr)) => (0, None, Some(pr)) - } - implicit val ordering: Ordering[SemanticVersion] = Ordering.by { x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) } - def apply(major: Long, minor: Long): SemanticVersion = { + def apply(major: Int, minor: Int): SemanticVersion = { SemanticVersion(major, Some(minor)) } - def apply(major: Long, minor: Long, patch: Long): SemanticVersion = { + def apply(major: Int, minor: Int, patch: Int): SemanticVersion = { SemanticVersion(major, Some(minor), Some(patch)) } - def apply(major: Long, - minor: Long, - patch: Long, - patch2: Long): SemanticVersion = { + def apply(major: Int, minor: Int, patch: Int, patch2: Int): SemanticVersion = { SemanticVersion(major, Some(minor), Some(patch), Some(patch2)) } - def apply(major: Long, - minor: Long, - patch: Long, + def apply(major: Int, + minor: Int, + patch: Int, preRelease: PreRelease): SemanticVersion = { SemanticVersion(major, Some(minor), Some(patch), None, Some(preRelease)) } @@ -105,18 +65,8 @@ object SemanticVersion extends Parsers { import fastparse._ import fastparse.NoWhitespace._ - private def Number[_: P] = Digit.rep(1).!.map(_.toLong) private def Major[_: P] = Number - // http://semver.org/#spec-item-9 - private def PreRelease[_: P]: P[PreRelease] = - "-" ~ ( - (("M" | "m") ~ &(Digit) ~ Number).map(n => Milestone(n)) | - (("R" | "r") ~ ("C" | "c") ~ &(Digit) ~ Number) - .map(n => ReleaseCandidate(n)) | - (Digit | Alpha | "." | "-").rep.!.map(s => OtherPreRelease(s)) - ) - // http://semver.org/#spec-item-10 private def MetaData[_: P] = "+" ~ AnyChar.rep.! @@ -125,7 +75,7 @@ object SemanticVersion extends Parsers { private def Patch2P[_: P] = ("." ~ Number).? // not really valid SemVer def Parser[_: P]: P[SemanticVersion] = { - ("v".? ~ Major ~ MinorP ~ PatchP ~ Patch2P ~ PreRelease.? ~ MetaData.?) + ("v".? ~ Major ~ MinorP ~ PatchP ~ Patch2P ~ ("-" ~ PreRelease.Parser).? ~ MetaData.?) .map { case (major, minor, patch, patch2, preRelease, metadata) => SemanticVersion(major, minor, patch, patch2, preRelease, metadata) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala index 599965edd..dbbf1ac7c 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala @@ -70,48 +70,29 @@ object DefaultRelease { case None => filterAll } - // descending ordering for versions - implicit def ordering: Ordering[SemanticVersion] = - SemanticVersion.ordering.reverse - - val releasesSorted = selectedReleases.toList.sortBy { release => - import release.reference._ + val releasesSorted = selectedReleases.toSeq.view.sortBy { release => + val ref = release.reference ( - // artifact - // match default artifact (ex: akka-actors is the default for akka/akka) - !defaultArtifact.contains(artifact), // false < true - // match project repository (ex: shapeless) - projectRepository == artifact, + // default artifact (ex: akka-actors is the default for akka/akka) + if (defaultArtifact.contains(ref.artifact)) 0 else 1, + // project repository (ex: shapeless) + if (projectRepository == ref.artifact) 1 else 0, // alphabetically - artifact, + ref.artifact, // version - defaultStableVersion && version.preRelease.isDefined, - version, + ref.version, // target - // stable jvm targets first - target.exists(_.targetType == Js), - target.flatMap(_.scalaVersion.preRelease).isDefined, - target.map(_.scalaVersion), - target.collect { case ScalaJs(_, scalaJsVersion) => scalaJsVersion } + ref.target ) - } + }.reverse releasesSorted.headOption.map { release => - val targets = releases - .map(_.reference.target) + val targets = releases.toSeq.view + .flatMap(_.reference.target) + .distinct + .sorted + .reverse .toList - .flatten - .sortBy( - target => - ( - target.targetType, - target.scalaVersion, - target match { - case ScalaJs(_, scalaJsVersion) => Some(scalaJsVersion) - case _ => None - } - ) - ) val artifacts = releases.map(_.reference.artifact).toList.sorted val versions = releases diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index 7b7aa9aeb..385dce47f 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -27,7 +27,7 @@ it's dependency on scala-library for example. */ sealed trait ScalaTarget extends Ordered[ScalaTarget] { - def scalaVersion: SemanticVersion + def scalaVersion: BinaryVersion def render: String def encode: String def targetType: ScalaTargetType @@ -36,21 +36,20 @@ sealed trait ScalaTarget extends Ordered[ScalaTarget] { ScalaTarget.ordering.compare(this, that) } -case class ScalaJvm(scalaVersion: SemanticVersion) extends ScalaTarget { +case class ScalaJvm(scalaVersion: BinaryVersion) extends ScalaTarget { val scalaJsVersion: Option[SemanticVersion] = None val render = s"scala $scalaVersion" val encode = s"_$scalaVersion" val targetType: ScalaTargetType = Jvm } -case class ScalaJs(scalaVersion: SemanticVersion, - scalaJsVersion: SemanticVersion) +case class ScalaJs(scalaVersion: BinaryVersion, scalaJsVersion: BinaryVersion) extends ScalaTarget { val render = s"scala-js $scalaJsVersion ($scalaVersion)" val encode = s"_sjs${scalaJsVersion}_$scalaVersion" val targetType: ScalaTargetType = Js } -case class ScalaNative(scalaVersion: SemanticVersion, - scalaNativeVersion: SemanticVersion) +case class ScalaNative(scalaVersion: BinaryVersion, + scalaNativeVersion: BinaryVersion) extends ScalaTarget { val scalaJsVersion: Option[SemanticVersion] = None val render = s"scala-native $scalaNativeVersion ($scalaNativeVersion)" @@ -58,7 +57,7 @@ case class ScalaNative(scalaVersion: SemanticVersion, val targetType: ScalaTargetType = Native } -case class SbtPlugin(scalaVersion: SemanticVersion, sbtVersion: SemanticVersion) +case class SbtPlugin(scalaVersion: BinaryVersion, sbtVersion: BinaryVersion) extends ScalaTarget { val scalaJsVersion: Option[SemanticVersion] = None val render = s"sbt $sbtVersion ($scalaVersion)" @@ -66,11 +65,30 @@ case class SbtPlugin(scalaVersion: SemanticVersion, sbtVersion: SemanticVersion) val targetType: ScalaTargetType = Sbt } +object ScalaJvm { + def fromFullVersion(fullVersion: SemanticVersion): ScalaJvm = { + val binaryVersion = fullVersion match { + case SemanticVersion(major, minor, patch, _, Some(preRelease), _) => + PreReleaseBinary( + major, + minor.getOrElse(0), + patch, + preRelease + ) + case SemanticVersion(major, minor, _, _, _, _) => + MinorBinary(major, minor.getOrElse(0)) + } + ScalaJvm(binaryVersion) + } +} + object ScalaTarget extends Parsers { // Scala > Js > Native > Sbt implicit val ordering: Ordering[ScalaTarget] = - Ordering.by[ScalaTarget, - (ScalaTargetType, SemanticVersion, Option[SemanticVersion])] { + Ordering.by[ + ScalaTarget, + (ScalaTargetType, BinaryVersion, Option[BinaryVersion]) + ] { case ScalaJvm(version) => (Jvm, version, None) case ScalaJs(version, jsVersion) => (Js, version, Some(jsVersion)) case ScalaNative(version, nativeVersion) => @@ -79,56 +97,56 @@ object ScalaTarget extends Parsers { } def parse(code: String): Option[ScalaTarget] = { - tryParse(code, x => scalaTargetParser(x)) + tryParse(code, x => Parser(x)) } - private val minScalaVersion = SemanticVersion(2, 10) - private val maxScalaVersion = SemanticVersion(2, 13) + private val minScalaVersion = MinorBinary(2, 10) + private val maxScalaVersion = MinorBinary(2, 13) - def isValidScalaVersion(version: SemanticVersion): Boolean = { + def isValidScalaVersion(version: BinaryVersion): Boolean = { version >= minScalaVersion && version <= maxScalaVersion } - private def minScalaJsVersion = SemanticVersion(0, 6) + private def minScalaJsVersion = MinorBinary(0, 6) - def isValidScalaJsVersion(version: SemanticVersion): Boolean = { + def isValidScalaJsVersion(version: BinaryVersion): Boolean = { minScalaJsVersion <= version } - private def minSbtVersion = SemanticVersion(0, 11) - private def maxSbtVersion = SemanticVersion(1, 3) + private def minSbtVersion = MinorBinary(0, 11) + private def maxSbtVersion = MinorBinary(1, 3) - def isValidSbtVersion(version: SemanticVersion): Boolean = { + def isValidSbtVersion(version: BinaryVersion): Boolean = { minSbtVersion <= version && version <= maxSbtVersion } - def isValidScalaNativeVersion(version: SemanticVersion): Boolean = true + def isValidScalaNativeVersion(version: BinaryVersion): Boolean = true import fastparse.NoWhitespace._ import fastparse._ - private def scalaPart[_: P] = "_" ~ SemanticVersion.Parser + private def scalaPart[_: P] = "_" ~ BinaryVersion.Parser private def scalaJs[_: P]: P[ScalaTarget] = - ("_sjs" ~ SemanticVersion.Parser ~ scalaPart).map { + ("_sjs" ~ BinaryVersion.Parser ~ scalaPart).map { case (scalaJsVersion, scalaVersion) => ScalaJs(scalaVersion, scalaJsVersion) } private def scalaNative[_: P]: P[ScalaTarget] = - ("_native" ~ SemanticVersion.Parser ~ scalaPart).map { + ("_native" ~ BinaryVersion.Parser ~ scalaPart).map { case (scalaNativeVersion, scalaVersion) => ScalaNative(scalaVersion, scalaNativeVersion) } private def sbt[_: P]: P[ScalaTarget] = - (scalaPart ~ "_" ~ SemanticVersion.Parser).map { + (scalaPart ~ "_" ~ BinaryVersion.Parser).map { case (scalaVersion, sbtVersion) => SbtPlugin(scalaVersion, sbtVersion) } - private def scala[_: P]: P[ScalaTarget] = scalaPart.map(ScalaJvm) + private def scala[_: P]: P[ScalaTarget] = scalaPart.map(ScalaJvm.apply) - def scalaTargetParser[_: P]: P[ScalaTarget] = + def Parser[_: P]: P[ScalaTarget] = scalaJs | scalaNative | sbt | scala } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala index 31d002eae..40c6607cf 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/ArtifactTests.scala @@ -11,8 +11,8 @@ class ArtifactTests extends FunSpec with Matchers { Artifact( "cats-core", ScalaJs( - scalaVersion = SemanticVersion(2, 11), - scalaJsVersion = SemanticVersion(0, 6) + scalaVersion = MinorBinary(2, 11), + scalaJsVersion = MinorBinary(0, 6) ) ) ) @@ -23,8 +23,8 @@ class ArtifactTests extends FunSpec with Matchers { Artifact( "cats-core", ScalaNative( - scalaVersion = SemanticVersion(2, 11), - scalaNativeVersion = SemanticVersion(0, 1) + scalaVersion = MinorBinary(2, 11), + scalaNativeVersion = MinorBinary(0, 1) ) ) ) @@ -34,7 +34,7 @@ class ArtifactTests extends FunSpec with Matchers { Artifact.parse("akka-remote-tests_2.11.0-RC4") should contain( Artifact( "akka-remote-tests", - ScalaJvm(SemanticVersion(2, 11, 0, ReleaseCandidate(4))) + ScalaJvm(PreReleaseBinary(2, 11, Some(0), ReleaseCandidate(4))) ) ) } @@ -44,8 +44,8 @@ class ArtifactTests extends FunSpec with Matchers { Artifact( "sbt-microsites", SbtPlugin( - scalaVersion = SemanticVersion(2, 12), - sbtVersion = SemanticVersion(1, 0) + scalaVersion = MinorBinary(2, 12), + sbtVersion = MinorBinary(1, 0) ) ) ) @@ -59,7 +59,7 @@ class ArtifactTests extends FunSpec with Matchers { Artifact.parse("banana_jvm_2.11") should contain( Artifact( "banana_jvm", - ScalaJvm(SemanticVersion(2, 11)) + ScalaJvm(MinorBinary(2, 11)) ) ) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala new file mode 100644 index 000000000..3ae06697d --- /dev/null +++ b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala @@ -0,0 +1,28 @@ +package ch.epfl.scala.index.model + +import org.scalatest.prop.TableDrivenPropertyChecks +import org.scalatest.{FunSpec, Matchers} + +class BinaryVersionTests + extends FunSpec + with Matchers + with TableDrivenPropertyChecks { + it("should parse any binary version") { + val inputs = Table( + ("input", "output"), + ("1", MajorBinary(1)), + ("1.x", MajorBinary(1)), + ("2.12", MinorBinary(2, 12)), + ("0.6", MinorBinary(0, 6)), + ("2.13.0", PatchBinary(2, 13, 0)), + ("0.4.0", PatchBinary(0, 4, 0)), + ("0.4.0-M2", PreReleaseBinary(0, 4, Some(0), Milestone(2))), + ("0.23.0-RC1", PreReleaseBinary(0, 23, Some(0), ReleaseCandidate(1))), + ("1.1-M1", PreReleaseBinary(1, 1, None, Milestone(1))) + ) + + forAll(inputs) { (input, output) => + BinaryVersion.parse(input) should contain(output) + } + } +} diff --git a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala index d70d266f3..5f78abfde 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala @@ -37,100 +37,6 @@ class SemanticVersionTests extends FunSpec with Matchers { ) } - describe("show") { - describe("binary") { - // relaxed semantic version - it("major") { - binary("1") should contain("1") - } - - // relaxed semantic version - it("major.minor") { - binary("1.2") should contain("1.2") - } - - it("major.minor.patch") { - binary("1.2.3") should contain("1.2") - } - - // relaxed semantic version - it("major.minor.patch.patch2") { - binary("1.2.3.4") should contain("1.2") - } - - it("major.minor.patch-rc") { - binary("1.2.3-RC5") should contain("1.2.3-RC5") - } - - it("major.minor.patch-m") { - binary("1.2.3-M6") should contain("1.2.3-M6") - } - - it("major.minor.patch-xyz") { - binary("1.1.1-xyz") should contain("1.1.1-xyz") - } - - it("major.minor.patch+meta") { - binary("1.1.1+some.meta~data") should contain("1.1") - } - - it("git commit") { - binary("13e7afa9c1817d45b2989e545b2e9ead21d00cef") shouldBe empty - } - - // relaxed semantic version - it("v sufix") { - binary("v1") should contain("1") - } - } - - describe("full or toString") { - // relaxed semantic version - it("major") { - full("1") should contain("1") - } - - // relaxed semantic version - it("major.minor") { - assert(full("1.2") == Some("1.2")) - } - - it("major.minor.patch") { - assert(full("1.2.3") == Some("1.2.3")) - } - - // relaxed semantic version - it("major.minor.patch.patch2") { - assert(full("1.2.3.4") == Some("1.2.3.4")) - } - - it("major.minor.patch-rc") { - assert(full("1.2.3-RC5") == Some("1.2.3-RC5")) - } - - it("major.minor.patch-m") { - assert(full("1.2.3-M6") == Some("1.2.3-M6")) - } - - it("major.minor.patch-xyz") { - assert(full("1.1.1-xyz") == Some("1.1.1-xyz")) - } - - it("major.minor.patch+meta") { - assert(full("1.1.1+some.meta~data") == Some("1.1.1+some.meta~data")) - } - - it("git commit") { - assert(full("13e7afa9c1817d45b2989e545b2e9ead21d00cef") == None) - } - - // relaxed semantic version - it("v sufix") { - full("v1") should contain("1") - } - } - } - describe("parsing") { // relaxed semantic version it("major") { @@ -200,8 +106,4 @@ class SemanticVersionTests extends FunSpec with Matchers { private def parseVersion(v: String): Option[SemanticVersion] = SemanticVersion(v) - private def binary(v: String): Option[String] = - SemanticVersion(v).map(_.binary.toString) - private def full(v: String): Option[String] = - SemanticVersion(v).map(_.toString) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala index fe437378b..a7c2e0d32 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala @@ -23,7 +23,6 @@ class DefaultReleaseTests extends FunSpec with Matchers { reverseDependencies = Seq(), internalDependencies = Seq(), targetType = "JVM", - fullScalaVersion = None, scalaVersion = None, scalaJsVersion = None, scalaNativeVersion = None, @@ -113,34 +112,32 @@ class DefaultReleaseTests extends FunSpec with Matchers { val targets: List[ScalaTarget] = List( - ScalaJs(SemanticVersion("2.11").get, SemanticVersion("0.6").get), - ScalaJs(SemanticVersion("2.10").get, SemanticVersion("0.6").get), - ScalaJvm(SemanticVersion("2.11").get), - ScalaJvm(SemanticVersion("2.10").get) + ScalaJvm(MinorBinary(2, 11)), + ScalaJvm(MinorBinary(2, 10)), + ScalaJs(MinorBinary(2, 11), MinorBinary(0, 6)), + ScalaJs(MinorBinary(2, 10), MinorBinary(0, 6)) ) - val expected: Option[ReleaseOptions] = - Some( - ReleaseOptions( - artifacts = List( - "cats-core" - ), - versions = versions, - targets = targets, - release = emptyRelease( - MavenReference(groupdId, "cats-core_2.11", "0.6.0"), - Release.Reference( - organization, - repository, - "cats-core", - SemanticVersion("0.6.0").get, - Some(ScalaJvm(SemanticVersion("2.11").get)) - ) + val expected = + ReleaseOptions( + artifacts = List( + "cats-core" + ), + versions = versions, + targets = targets, + release = emptyRelease( + MavenReference(groupdId, "cats-core_2.11", "0.6.0"), + Release.Reference( + organization, + repository, + "cats-core", + SemanticVersion("0.6.0").get, + Some(ScalaJvm(MinorBinary(2, 11))) ) ) ) - result shouldBe expected + result should contain(expected) } it("selected artifact") { @@ -180,7 +177,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { SemanticVersion("2.4.8").get ), targets = List( - ScalaJvm(SemanticVersion("2.11").get) + ScalaJvm(MinorBinary(2, 11)) ), release = emptyRelease( MavenReference(groupdId, @@ -191,7 +188,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { repository, "akka-distributed-data-experimental", SemanticVersion("2.4.8").get, - Some(ScalaJvm(SemanticVersion("2.11").get)) + Some(ScalaJvm(MinorBinary(2, 11))) ) ) ) @@ -231,8 +228,8 @@ class DefaultReleaseTests extends FunSpec with Matchers { val targets: List[ScalaTarget] = List( - ScalaJvm(SemanticVersion("2.12.2").get), - ScalaJvm(SemanticVersion("2.12").get) + ScalaJvm(PatchBinary(2, 12, 2)), + ScalaJvm(MinorBinary(2, 12)) ) val expected: Option[ReleaseOptions] = @@ -250,7 +247,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { repository, "scalafix-core", SemanticVersion("0.5.3").get, - Some(ScalaJvm(SemanticVersion("2.12").get)) + Some(ScalaJvm(MinorBinary(2, 12))) ) ) ) diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala index 95a6013cf..3e856bfd8 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/MillInstallTests.scala @@ -13,7 +13,7 @@ class MillInstallTests extends FunSuite with TestHelpers { artifactName = "http4s-core", target = Some( ScalaJvm( - scalaVersion = SemanticVersion(2, 12, 3) + scalaVersion = PatchBinary(2, 12, 3) ) ) ).millInstall @@ -33,7 +33,7 @@ class MillInstallTests extends FunSuite with TestHelpers { artifactName = "doodle", target = Some( ScalaJvm( - scalaVersion = SemanticVersion(2, 11) + scalaVersion = MinorBinary(2, 11) ) ), resolver = Some(BintrayResolver("noelwelsh", "maven")) diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala index 7f45c0e35..95b27a62a 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/SbtInstallTests.scala @@ -13,7 +13,7 @@ class SbtInstallTests extends FunSuite with TestHelpers { artifactName = "paradise", target = Some( ScalaJvm( - scalaVersion = SemanticVersion(2, 12, 3) + scalaVersion = PatchBinary(2, 12, 3) ) ) ).sbtInstall @@ -33,7 +33,7 @@ class SbtInstallTests extends FunSuite with TestHelpers { artifactName = "scalaz-core", target = Some( ScalaJvm( - scalaVersion = SemanticVersion(2, 13, 0, Milestone(1)) + scalaVersion = PreReleaseBinary(2, 13, Some(0), Milestone(1)) ) ) ).sbtInstall @@ -53,8 +53,8 @@ class SbtInstallTests extends FunSuite with TestHelpers { artifactName = "scalajs-dom", target = Some( ScalaJs( - scalaVersion = SemanticVersion(2, 12), - scalaJsVersion = SemanticVersion(0, 6) + scalaVersion = MinorBinary(2, 12), + scalaJsVersion = MinorBinary(0, 6) ) ) ).sbtInstall @@ -74,8 +74,8 @@ class SbtInstallTests extends FunSuite with TestHelpers { artifactName = "sbt-native-packager", target = Some( SbtPlugin( - scalaVersion = SemanticVersion(2, 10), - sbtVersion = SemanticVersion(0, 13) + scalaVersion = MinorBinary(2, 10), + sbtVersion = MinorBinary(0, 13) ) ) ).sbtInstall @@ -95,7 +95,7 @@ class SbtInstallTests extends FunSuite with TestHelpers { artifactName = "doodle", target = Some( ScalaJvm( - scalaVersion = SemanticVersion("2.11").get + scalaVersion = MinorBinary(2, 11) ) ), resolver = Some(BintrayResolver("noelwelsh", "maven")) diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala deleted file mode 100644 index 76374058f..000000000 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetOrdering.scala +++ /dev/null @@ -1,43 +0,0 @@ -package ch.epfl.scala.index.model -package release - -import org.scalatest._ - -class ScalaTargetOrdering extends FunSpec { - describe("Scala Targets") { - it("has an ordering") { - val s210 = SemanticVersion("2.10.6").get - val s211 = SemanticVersion("2.11.11").get - val s212 = SemanticVersion("2.12.2").get - val js067 = SemanticVersion("0.6.7").get - val js0618 = SemanticVersion("0.6.18").get - val nat03 = SemanticVersion("0.3.0").get - - val obtained = List( - ScalaJs(s211, js067), - ScalaJs(s212, js0618), - ScalaJs(s210, js067), - ScalaJs(s211, js0618), - ScalaJs(s210, js0618), - ScalaNative(s211, nat03), - ScalaJvm(s212), - ScalaJvm(s211), - ScalaJvm(s210) - ).sorted(ScalaTarget.ordering) - - val expected = List( - ScalaNative(s211, nat03), - ScalaJs(s210, js067), - ScalaJs(s210, js0618), - ScalaJs(s211, js067), - ScalaJs(s211, js0618), - ScalaJs(s212, js0618), - ScalaJvm(s210), - ScalaJvm(s211), - ScalaJvm(s212) - ) - - assert(obtained == expected) - } - } -} diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala new file mode 100644 index 000000000..89a10e717 --- /dev/null +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala @@ -0,0 +1,57 @@ +package ch.epfl.scala.index.model +package release + +import org.scalatest._ +import org.scalatest.prop.TableDrivenPropertyChecks + +class ScalaTargetTests + extends FunSpec + with Matchers + with TableDrivenPropertyChecks { + it("should be ordered") { + val s210 = PatchBinary(2, 10, 6) + val s211 = PatchBinary(2, 11, 11) + val s212 = PatchBinary(2, 12, 2) + val js067 = PatchBinary(0, 6, 7) + val js0618 = PatchBinary(0, 6, 18) + val nat03 = PatchBinary(0, 3, 0) + + val obtained = List( + ScalaJs(s211, js067), + ScalaJs(s212, js0618), + ScalaJs(s210, js067), + ScalaJs(s211, js0618), + ScalaJs(s210, js0618), + ScalaNative(s211, nat03), + ScalaJvm(s212), + ScalaJvm(s211), + ScalaJvm(s210) + ).sorted(ScalaTarget.ordering) + + val expected = List( + ScalaNative(s211, nat03), + ScalaJs(s210, js067), + ScalaJs(s210, js0618), + ScalaJs(s211, js067), + ScalaJs(s211, js0618), + ScalaJs(s212, js0618), + ScalaJvm(s210), + ScalaJvm(s211), + ScalaJvm(s212) + ) + + assert(obtained == expected) + } + + it("should parse any scala target") { + val cases = Table( + ("input", "target"), + ("_2.12", ScalaJvm(MinorBinary(2, 12))), + ("_sjs0.6_2.12", ScalaJs(MinorBinary(2, 12), MinorBinary(0, 6))) + ) + + forAll(cases) { (input, target) => + ScalaTarget.parse(input) should contain(target) + } + } +} diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala index e1b44a31d..81ee3a05a 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala @@ -19,7 +19,7 @@ trait TestHelpers { artifactName: String, target: Option[ScalaTarget], isNonStandardLib: Boolean = false, - resolver: Option[Resolver] = None) = { + resolver: Option[Resolver] = None): Release = { Release( maven = MavenReference( groupId = groupId, @@ -48,7 +48,6 @@ trait TestHelpers { reverseDependencies = Seq(), internalDependencies = Seq(), targetType = "", - fullScalaVersion = None, scalaVersion = None, scalaJsVersion = None, scalaNativeVersion = None, diff --git a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala index 1c45bf76d..f2d297120 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala @@ -247,16 +247,19 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getAllScalaNativeVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaNativeVersion", notDeprecatedQuery, _ => true) + versionAggregations("scalaNativeVersion", + notDeprecatedQuery, + ScalaTarget.isValidScalaNativeVersion) } def getScalaNativeVersions( params: SearchParams ): Future[List[(String, Long)]] = { - versionAggregations("scalaNativeVersion", - filteredSearchQuery(params), - _ => true) - .map(addLabelsIfMissing(params.scalaNativeVersions.toSet)) + versionAggregations( + "scalaNativeVersion", + filteredSearchQuery(params), + ScalaTarget.isValidScalaNativeVersion + ).map(addLabelsIfMissing(params.scalaNativeVersions.toSet)) } def getAllSbtVersions(): Future[List[(String, Long)]] = { @@ -319,21 +322,16 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( private def versionAggregations( field: String, query: QueryDefinition, - filterF: SemanticVersion => Boolean + filterF: BinaryVersion => Boolean ): Future[List[(String, Long)]] = { aggregations(field, query).map { versionAgg => val filteredAgg = for { (version, count) <- versionAgg.toList - semanticVersion <- SemanticVersion(version) if filterF(semanticVersion) - } yield (semanticVersion, count) + binaryVersion <- BinaryVersion.parse(version) if filterF(binaryVersion) + } yield (binaryVersion, count) filteredAgg - .groupBy { - case (version, _) => SemanticVersion(version.major, version.minor) - } - .mapValues(group => group.map { case (_, count) => count }.sum) - .toList .sortBy(_._1) .map { case (v, c) => (v.toString, c) } } diff --git a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala index af8aba5a8..65916cc07 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/SearchApi.scala @@ -55,26 +55,26 @@ class SearchApi( sbtVersion: Option[String] ): Option[ScalaTarget] = { (targetType, - scalaVersion.flatMap(SemanticVersion.parse), - scalaJsVersion.flatMap(SemanticVersion.parse), - scalaNativeVersion.flatMap(SemanticVersion.parse), - sbtVersion.flatMap(SemanticVersion.parse)) match { + scalaVersion.flatMap(BinaryVersion.parse), + scalaJsVersion.flatMap(BinaryVersion.parse), + scalaNativeVersion.flatMap(BinaryVersion.parse), + sbtVersion.flatMap(BinaryVersion.parse)) match { case (Some("JVM"), Some(scalaVersion), _, _, _) => - Some(ScalaJvm(scalaVersion.binary)) + Some(ScalaJvm(scalaVersion)) case (Some("JS"), Some(scalaVersion), Some(scalaJsVersion), _, _) => - Some(ScalaJs(scalaVersion.binary, scalaJsVersion.binary)) + Some(ScalaJs(scalaVersion, scalaJsVersion)) case (Some("NATIVE"), Some(scalaVersion), _, Some(scalaNativeVersion), _) => - Some(ScalaNative(scalaVersion.binary, scalaNativeVersion.binary)) + Some(ScalaNative(scalaVersion, scalaNativeVersion)) case (Some("SBT"), Some(scalaVersion), _, _, Some(sbtVersion)) => - Some(SbtPlugin(scalaVersion.binary, sbtVersion.binary)) + Some(SbtPlugin(scalaVersion, sbtVersion)) case _ => None } diff --git a/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala b/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala index f626ccf8f..c30405659 100644 --- a/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala +++ b/server/src/test/scala/ch.epfl.scala.index.server/RelevanceTest.scala @@ -1,10 +1,9 @@ package ch.epfl.scala.index package server -import model.Project +import model.{MinorBinary, Project, SemanticVersion} import model.misc.SearchParams import model.release.{ScalaJs, ScalaNative, ScalaTarget} -import model.SemanticVersion import data.DataPaths import data.elastic._ import data.github.GithubDownload @@ -109,8 +108,8 @@ class RelevanceTest test("Scala.js targetFiltering") { val scalaJs = ScalaJs( - scalaVersion = SemanticVersion(2, 12), - scalaJsVersion = SemanticVersion(0, 6) + scalaVersion = MinorBinary(2, 12), + scalaJsVersion = MinorBinary(0, 6) ) top( @@ -124,8 +123,8 @@ class RelevanceTest test("Scala.js targetFiltering (2)") { val scalaJs = ScalaJs( - scalaVersion = SemanticVersion(2, 12), - scalaJsVersion = SemanticVersion(0, 6) + scalaVersion = MinorBinary(2, 12), + scalaJsVersion = MinorBinary(0, 6) ) compare( @@ -150,8 +149,8 @@ class RelevanceTest test("Scala Native targetFiltering") { val scalaNative = ScalaNative( - scalaVersion = SemanticVersion(2, 11), - scalaNativeVersion = SemanticVersion(0, 3) + scalaVersion = MinorBinary(2, 11), + scalaNativeVersion = MinorBinary(0, 3) ) top( diff --git a/template/src/main/scala/ch.epfl.scala.index.views/package.scala b/template/src/main/scala/ch.epfl.scala.index.views/package.scala index 97c05304d..69d9536a2 100644 --- a/template/src/main/scala/ch.epfl.scala.index.views/package.scala +++ b/template/src/main/scala/ch.epfl.scala.index.views/package.scala @@ -127,12 +127,11 @@ package object html { } def sortVersions(versions: Set[String], - filter: SemanticVersion => Boolean): List[String] = { + filter: BinaryVersion => Boolean): List[String] = { versions.toList - .flatMap(SemanticVersion.parse) + .flatMap(BinaryVersion.parse) .filter(filter) .sorted - .map(version => SemanticVersion(version.major, version.minor).toString) - .distinct + .map(_.toString) } } From 559039533ebcb37aa4ddc925e265ea78dce0366b Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Fri, 3 Apr 2020 17:43:53 +0200 Subject: [PATCH 06/10] rework valid binary versions --- .../project/ProjectConvert.scala | 36 ++++----- .../BinaryVersion.scala | 22 ++++-- .../ch.epfl.scala.index.model/Project.scala | 28 +++++-- .../ch.epfl.scala.index.model/Release.scala | 9 ++- .../release/DefaultRelease.scala | 69 +++++++++-------- .../release/ScalaTarget.scala | 77 +++++++++++++------ .../BinaryVersionTests.scala | 13 ++++ .../release/DefaultReleaseTests.scala | 3 +- .../DataRepository.scala | 30 +++----- .../routes/ProjectPages.scala | 9 +-- .../routes/api/impl/IndexingActor.scala | 3 +- .../ch.epfl.scala.index.views/package.scala | 21 ++--- .../search/resultList.scala.html | 8 +- 13 files changed, 196 insertions(+), 132 deletions(-) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala index 66f872323..f5dab956a 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala @@ -31,7 +31,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) pomsRepoSha: List[(ReleaseModel, LocalRepository, String)], stored: Boolean = true, cachedReleases: Map[Project.Reference, Set[Release]] = Map() - ): List[(Project, Set[Release])] = { + ): List[(Project, Seq[Release])] = { val githubRepoExtractor = new GithubRepoExtractor(paths) @@ -61,7 +61,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) MavenReference(pom.groupId, pom.artifactId, pom.version) def maxMinRelease( - releases: Set[Release] + releases: Seq[Release] ): (Option[String], Option[String]) = { def sortDate(rawDates: List[String]): List[String] = { rawDates @@ -144,7 +144,7 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) scalaNativeVersion = scalaNativeVersion.map(_.toString), sbtVersion = sbtVersion.map(_.toString) ) - }.toSet ++ cachedReleasesForProject + } ++ cachedReleasesForProject val releaseCount = releases.map(_.reference.version).size @@ -265,17 +265,17 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) } def collectDependencies( - releases: Set[Release], + releases: Seq[Release], f: Release.Reference => Option[String] ): Set[String] = { (for { - release <- releases.toList - dependency <- release.scalaDependencies.toList - r <- f(dependency.reference).toList + release <- releases + dependency <- release.scalaDependencies + r <- f(dependency.reference) } yield r).toSet } - def dependencies(releases: Set[Release]): Set[String] = + def dependencies(releases: Seq[Release]): Set[String] = collectDependencies(releases, r => Some(r.name)) def belongsTo(reference: Project.Reference): Dependency => Boolean = { @@ -312,11 +312,11 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) val project = seed.toProject( - targetType = releases.map(_.targetType), - scalaVersion = releases.flatMap(_.scalaVersion), - scalaJsVersion = releases.flatMap(_.scalaJsVersion), - scalaNativeVersion = releases.flatMap(_.scalaNativeVersion), - sbtVersion = releases.flatMap(_.sbtVersion), + targetType = releases.map(_.targetType).distinct, + scalaVersion = releases.flatMap(_.scalaVersion).distinct, + scalaJsVersion = releases.flatMap(_.scalaJsVersion).distinct, + scalaNativeVersion = releases.flatMap(_.scalaNativeVersion).distinct, + sbtVersion = releases.flatMap(_.sbtVersion).distinct, dependencies = dependencies(releasesWithDependencies), dependentCount = releasesWithDependencies.view .flatMap(_.reverseDependencies.map(_.reference)) @@ -358,11 +358,11 @@ object ProjectConvert { def reference: Project.Reference = Project.Reference(organization, repository) - def toProject(targetType: Set[String], - scalaVersion: Set[String], - scalaJsVersion: Set[String], - scalaNativeVersion: Set[String], - sbtVersion: Set[String], + def toProject(targetType: List[String], + scalaVersion: List[String], + scalaJsVersion: List[String], + scalaNativeVersion: List[String], + sbtVersion: List[String], dependencies: Set[String], dependentCount: Int): Project = Project( diff --git a/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala index 95238f43b..c053b0e2c 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala @@ -33,15 +33,25 @@ final case class PreReleaseBinary(major: Int, object BinaryVersion extends Parsers { import fastparse._ import fastparse.NoWhitespace._ - - // Major > Minor > Patch > PreRelease + implicit val ordering: Ordering[BinaryVersion] = Ordering.by { - case MajorBinary(major) => (3, major, None, None, None) - case MinorBinary(major, minor) => (2, major, Some(minor), None, None) + case MajorBinary(major) => (major, None, None, None) + case MinorBinary(major, minor) => (major, Some(minor), None, None) case PatchBinary(major, minor, patch) => - (1, major, Some(minor), Some(patch), None) + (major, Some(minor), Some(patch), None) case PreReleaseBinary(major, minor, patch, preRelease) => - (0, major, Some(minor), patch, Some(preRelease)) + (major, Some(minor), patch, Some(preRelease)) + } + + def sortAndFilter( + binaryVersions: Seq[String], + filter: BinaryVersion => Boolean + ): Seq[String] = { + binaryVersions.view + .flatMap(parse) + .filter(filter) + .sorted + .map(_.toString) } def parse(input: String): Option[BinaryVersion] = { diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Project.scala b/model/src/main/scala/ch.epfl.scala.index.model/Project.scala index cfdd53198..a06088a69 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Project.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Project.scala @@ -1,5 +1,11 @@ package ch.epfl.scala.index.model +import ch.epfl.scala.index.model.release.{ + SbtPlugin, + ScalaJs, + ScalaJvm, + ScalaNative +} import misc.{GithubInfo, GithubRepo, Url} /** @@ -53,16 +59,26 @@ case class Project( id: Option[String] = None, created: Option[String], updated: Option[String], - targetType: Set[String], - scalaVersion: Set[String], - scalaJsVersion: Set[String], - scalaNativeVersion: Set[String], - sbtVersion: Set[String], + targetType: List[String], + scalaVersion: List[String], + scalaJsVersion: List[String], + scalaNativeVersion: List[String], + sbtVersion: List[String], dependencies: Set[String], dependentCount: Int, primaryTopic: Option[String] = None ) { - def hideId: Project = copy(id = None) + def formatForDisplaying: Project = { + import BinaryVersion.sortAndFilter + copy( + id = None, + scalaVersion = sortAndFilter(scalaVersion, ScalaJvm.isValid).toList, + scalaJsVersion = sortAndFilter(scalaJsVersion, ScalaJs.isValid).toList, + scalaNativeVersion = + sortAndFilter(scalaNativeVersion, ScalaNative.isValid).toList, + sbtVersion = sortAndFilter(sbtVersion, SbtPlugin.isValid).toList + ) + } def reference: Project.Reference = Project.Reference(organization, repository) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala index ef49fb762..83382e341 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/Release.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/Release.scala @@ -43,6 +43,10 @@ case class Release( sbtVersion: Option[String] ) { + def isValid: Boolean = { + reference.isValid + } + /** * string representation for sbt dependency * @return @@ -293,6 +297,10 @@ object Release { target: Option[ScalaTarget] ) extends GeneralReference { + def isValid: Boolean = { + target.exists(_.isValid) + } + def projectReference = Project.Reference(organization, repository) def name = s"$organization/$artifact" def httpUrl = { @@ -306,6 +314,5 @@ object Release { repository == "scala" && artifact == "scala-library" } - } } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala index dbbf1ac7c..610e93c06 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala @@ -37,48 +37,33 @@ case class ReleaseOptions( object DefaultRelease { def apply(projectRepository: String, selection: ReleaseSelection, - releases: Set[Release], + releases: Seq[Release], defaultArtifact: Option[String], defaultStableVersion: Boolean): Option[ReleaseOptions] = { - def filterTarget(release: Release): Boolean = - selection.target.forall( - target => release.reference.target.contains(target) - ) - - def filterArtifact(release: Release): Boolean = - selection.artifact.forall(_ == release.reference.artifact) - - def filterVersion(release: Release): Boolean = - selection.version.forall(_ == release.reference.version) - - def filterAll = - releases.filter( - release => - filterTarget(release) && - filterArtifact(release) && - filterVersion(release) - ) - val selectedReleases = selection.selected match { case Some(selected) => - if (selected == "target") releases.filter(filterTarget) - else if (selected == "artifact") releases.filter(filterArtifact) - else if (selected == "version") releases.filter(filterVersion) - else filterAll - case None => filterAll + if (selected == "target") releases.filter(filterTarget(selection)) + else if (selected == "artifact") + releases.filter(filterArtifact(selection)) + else if (selected == "version") + releases.filter(filterVersion(selection)) + else releases.filter(filterAll(selection)) + case None => releases.filter(filterAll(selection)) } - val releasesSorted = selectedReleases.toSeq.view.sortBy { release => + val releasesSorted = selectedReleases.view.sortBy { release => val ref = release.reference ( // default artifact (ex: akka-actors is the default for akka/akka) - if (defaultArtifact.contains(ref.artifact)) 0 else 1, + if (defaultArtifact.contains(ref.artifact)) 1 else 0, // project repository (ex: shapeless) if (projectRepository == ref.artifact) 1 else 0, // alphabetically ref.artifact, + // stable version first + if (defaultStableVersion && ref.version.preRelease.isDefined) 0 else 1, // version ref.version, // target @@ -87,18 +72,24 @@ object DefaultRelease { }.reverse releasesSorted.headOption.map { release => - val targets = releases.toSeq.view + val targets = releases.view .flatMap(_.reference.target) .distinct .sorted .reverse .toList - val artifacts = releases.map(_.reference.artifact).toList.sorted - val versions = releases - .map(_.reference.version) + val artifacts = releases.view + .map(_.reference.artifact) + .distinct + .sorted .toList + + val versions = releases.view + .map(_.reference.version) + .distinct .sorted(SemanticVersion.ordering.reverse) + .toList ReleaseOptions( artifacts, @@ -108,4 +99,20 @@ object DefaultRelease { ) } } + + def filterTarget(selection: ReleaseSelection)(release: Release): Boolean = + selection.target.forall( + target => release.reference.target.contains(target) + ) + + def filterArtifact(selection: ReleaseSelection)(release: Release): Boolean = + selection.artifact.forall(_ == release.reference.artifact) + + def filterVersion(selection: ReleaseSelection)(release: Release): Boolean = + selection.version.forall(_ == release.reference.version) + + def filterAll(selection: ReleaseSelection)(release: Release): Boolean = + filterTarget(selection)(release) && + filterArtifact(selection)(release) && + filterVersion(selection)(release) } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index 385dce47f..ec74c25f5 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -31,38 +31,46 @@ sealed trait ScalaTarget extends Ordered[ScalaTarget] { def render: String def encode: String def targetType: ScalaTargetType + def isValid: Boolean override def compare(that: ScalaTarget): Int = ScalaTarget.ordering.compare(this, that) } case class ScalaJvm(scalaVersion: BinaryVersion) extends ScalaTarget { - val scalaJsVersion: Option[SemanticVersion] = None val render = s"scala $scalaVersion" val encode = s"_$scalaVersion" val targetType: ScalaTargetType = Jvm + val isValid: Boolean = ScalaJvm.isValid(scalaVersion) } case class ScalaJs(scalaVersion: BinaryVersion, scalaJsVersion: BinaryVersion) extends ScalaTarget { val render = s"scala-js $scalaJsVersion ($scalaVersion)" val encode = s"_sjs${scalaJsVersion}_$scalaVersion" val targetType: ScalaTargetType = Js + val isValid: Boolean = ScalaJvm.isValid(scalaVersion) && ScalaJs.isValid( + scalaJsVersion + ) } case class ScalaNative(scalaVersion: BinaryVersion, scalaNativeVersion: BinaryVersion) extends ScalaTarget { - val scalaJsVersion: Option[SemanticVersion] = None val render = s"scala-native $scalaNativeVersion ($scalaNativeVersion)" val encode = s"_native${scalaNativeVersion}_$scalaVersion" val targetType: ScalaTargetType = Native + val isValid: Boolean = ScalaJvm.isValid(scalaVersion) && ScalaNative.isValid( + scalaNativeVersion + ) } case class SbtPlugin(scalaVersion: BinaryVersion, sbtVersion: BinaryVersion) extends ScalaTarget { - val scalaJsVersion: Option[SemanticVersion] = None val render = s"sbt $sbtVersion ($scalaVersion)" val encode = s"_${scalaVersion}_$sbtVersion" val targetType: ScalaTargetType = Sbt + val isValid: Boolean = ScalaJvm.isValid(scalaVersion) && SbtPlugin.isValid( + sbtVersion + ) } object ScalaJvm { @@ -80,6 +88,47 @@ object ScalaJvm { } ScalaJvm(binaryVersion) } + + val `2.10`: BinaryVersion = MinorBinary(2, 10) + val `2.11`: BinaryVersion = MinorBinary(2, 11) + val `2.12`: BinaryVersion = MinorBinary(2, 12) + val `2.13`: BinaryVersion = MinorBinary(2, 13) + + private def stableBinaryVersions = Set(`2.10`, `2.11`, `2.12`, `2.13`) + + def isValid(version: BinaryVersion): Boolean = + stableBinaryVersions.contains(version) +} + +object ScalaJs { + val `0.6`: BinaryVersion = MinorBinary(0, 6) + val `1.x`: BinaryVersion = MajorBinary(1) + + private def stableBinaryVersions = Set(`0.6`, `1.x`) + + def isValid(version: BinaryVersion): Boolean = + stableBinaryVersions.contains(version) +} + +object ScalaNative { + val `0.3`: BinaryVersion = MinorBinary(0, 3) + val `0.4.0-M2`: BinaryVersion = PreReleaseBinary(0, 4, Some(0), Milestone(2)) + + def isValid(version: BinaryVersion): Boolean = { + version == `0.3` || version >= `0.4.0-M2` + } +} + +object SbtPlugin { + val `0.13`: BinaryVersion = MinorBinary(0, 13) + val `1.0`: BinaryVersion = MinorBinary(1, 0) + val `1.x`: BinaryVersion = MajorBinary(1) + + private def stableBinaryVersions = Set(`0.13`, `1.0`, `1.x`) + + def isValid(version: BinaryVersion): Boolean = { + stableBinaryVersions.contains(version) + } } object ScalaTarget extends Parsers { @@ -100,28 +149,6 @@ object ScalaTarget extends Parsers { tryParse(code, x => Parser(x)) } - private val minScalaVersion = MinorBinary(2, 10) - private val maxScalaVersion = MinorBinary(2, 13) - - def isValidScalaVersion(version: BinaryVersion): Boolean = { - version >= minScalaVersion && version <= maxScalaVersion - } - - private def minScalaJsVersion = MinorBinary(0, 6) - - def isValidScalaJsVersion(version: BinaryVersion): Boolean = { - minScalaJsVersion <= version - } - - private def minSbtVersion = MinorBinary(0, 11) - private def maxSbtVersion = MinorBinary(1, 3) - - def isValidSbtVersion(version: BinaryVersion): Boolean = { - minSbtVersion <= version && version <= maxSbtVersion - } - - def isValidScalaNativeVersion(version: BinaryVersion): Boolean = true - import fastparse.NoWhitespace._ import fastparse._ diff --git a/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala index 3ae06697d..4ab1df9ab 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala @@ -25,4 +25,17 @@ class BinaryVersionTests BinaryVersion.parse(input) should contain(output) } } + + it("should be ordered") { + val inputs = Table[BinaryVersion, BinaryVersion]( + ("lower", "higher"), + (MajorBinary(1), MajorBinary(2)), + (MajorBinary(1), MinorBinary(1, 1)), // 1.x < 1.1 + (MajorBinary(1), MinorBinary(2, 1)), + (PreReleaseBinary(1, 2, None, Milestone(1)), MinorBinary(1, 2)), + (MajorBinary(1), PreReleaseBinary(2, 0, None, Milestone(1))) + ) + + forAll(inputs) { (lower, higher) => lower shouldBe < (higher)} + } } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala index a7c2e0d32..bcef3b554 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala @@ -32,7 +32,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { def prepare(organization: String, repository: String, groupdId: String, - releases: List[(String, String)]): Set[Release] = { + releases: List[(String, String)]): Seq[Release] = { releases .flatMap { case (artifactId, rawVersion) => @@ -52,7 +52,6 @@ class DefaultReleaseTests extends FunSpec with Matchers { Some(target)) ) } - .toSet } describe("Default Release") { diff --git a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala index f2d297120..8b5428e7d 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/DataRepository.scala @@ -69,7 +69,7 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( Math.ceil(result.totalHits / params.total.toDouble).toInt, itemCount = result.totalHits ), - result.to[Project].map(_.hideId) + result.to[Project].map(_.formatForDisplaying) ) } } @@ -84,7 +84,7 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( val request = search(indexName / releasesCollection).query(query).size(5000) - esClient.execute(request).map(_.to[Release]) + esClient.execute(request).map(_.to[Release].filter(_.isValid)) } /** @@ -138,7 +138,7 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( DefaultRelease( project.repository, selection, - releases.toSet, + releases, project.defaultArtifact, project.defaultStableVersion ).map(sel => (project, sel)) @@ -175,7 +175,7 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( "created", frontPageCount ) - } yield projects.map(_.hideId) + } yield projects.map(_.formatForDisplaying) } def getLatestReleases(): Future[List[Release]] = { @@ -221,35 +221,31 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( } def getAllScalaVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaVersion", - notDeprecatedQuery, - ScalaTarget.isValidScalaVersion) + versionAggregations("scalaVersion", notDeprecatedQuery, ScalaJvm.isValid) } def getScalaVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("scalaVersion", filteredSearchQuery(params), - ScalaTarget.isValidScalaVersion) + ScalaJvm.isValid) .map(addLabelsIfMissing(params.scalaVersions.toSet)) } def getAllScalaJsVersions(): Future[List[(String, Long)]] = { - versionAggregations("scalaJsVersion", - notDeprecatedQuery, - ScalaTarget.isValidScalaJsVersion) + versionAggregations("scalaJsVersion", notDeprecatedQuery, ScalaJs.isValid) } def getScalaJsVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("scalaJsVersion", filteredSearchQuery(params), - ScalaTarget.isValidScalaJsVersion) + ScalaJs.isValid) .map(addLabelsIfMissing(params.scalaJsVersions.toSet)) } def getAllScalaNativeVersions(): Future[List[(String, Long)]] = { versionAggregations("scalaNativeVersion", notDeprecatedQuery, - ScalaTarget.isValidScalaNativeVersion) + ScalaNative.isValid) } def getScalaNativeVersions( @@ -258,20 +254,18 @@ class DataRepository(paths: DataPaths, githubDownload: GithubDownload)( versionAggregations( "scalaNativeVersion", filteredSearchQuery(params), - ScalaTarget.isValidScalaNativeVersion + ScalaNative.isValid ).map(addLabelsIfMissing(params.scalaNativeVersions.toSet)) } def getAllSbtVersions(): Future[List[(String, Long)]] = { - versionAggregations("sbtVersion", - notDeprecatedQuery, - ScalaTarget.isValidSbtVersion) + versionAggregations("sbtVersion", notDeprecatedQuery, SbtPlugin.isValid) } def getSbtVersions(params: SearchParams): Future[List[(String, Long)]] = { versionAggregations("sbtVersion", filteredSearchQuery(params), - ScalaTarget.isValidSbtVersion) + SbtPlugin.isValid) .map(addLabelsIfMissing(params.sbtVersions.toSet)) } diff --git a/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala b/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala index bb14e052b..025a70495 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/routes/ProjectPages.scala @@ -156,7 +156,6 @@ class ProjectPages( .getProjectPage(Project.Reference(owner, repo), selection) .map(_.map { case (project, options) => - import options._ val twitterCard = for { github <- project.github description <- github.description @@ -169,16 +168,16 @@ class ProjectPages( ) val versions0 = - if (project.strictVersions) versions.filter(_.isSemantic) - else versions + if (project.strictVersions) options.versions.filter(_.isSemantic) + else options.versions (OK, views.project.html.project( project, options.artifacts, versions0, - targets, - release, + options.targets, + options.release, user, canEdit(owner, repo, userState), twitterCard diff --git a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/impl/IndexingActor.scala b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/impl/IndexingActor.scala index e36de9774..a886261cb 100644 --- a/server/src/main/scala/ch.epfl.scala.index.server/routes/api/impl/IndexingActor.scala +++ b/server/src/main/scala/ch.epfl.scala.index.server/routes/api/impl/IndexingActor.scala @@ -87,7 +87,8 @@ class IndexingActor( cachedReleases = cachedReleases ).head - cachedReleases = upserts(cachedReleases, projectReference, newReleases) + cachedReleases = + upserts(cachedReleases, projectReference, newReleases.toSet) val updatedProject = newProject.copy( liveData = true diff --git a/template/src/main/scala/ch.epfl.scala.index.views/package.scala b/template/src/main/scala/ch.epfl.scala.index.views/package.scala index 69d9536a2..0e293198b 100644 --- a/template/src/main/scala/ch.epfl.scala.index.views/package.scala +++ b/template/src/main/scala/ch.epfl.scala.index.views/package.scala @@ -49,12 +49,12 @@ package object html { val newUri = uri .appendQuery("sort", params.sorting) - .appendQuery("topics", params.topics.toList) - .appendQuery("targetTypes", params.targetTypes.toList) - .appendQuery("scalaVersions", params.scalaVersions.toList) - .appendQuery("scalaJsVersions", params.scalaJsVersions.toList) - .appendQuery("scalaNativeVersions", params.scalaNativeVersions.toList) - .appendQuery("sbtVersions", params.sbtVersions.toList) + .appendQuery("topics", params.topics) + .appendQuery("targetTypes", params.targetTypes) + .appendQuery("scalaVersions", params.scalaVersions) + .appendQuery("scalaJsVersions", params.scalaJsVersions) + .appendQuery("scalaNativeVersions", params.scalaNativeVersions) + .appendQuery("sbtVersions", params.sbtVersions) .appendQuery("you", you) .appendQuery("q" -> params.queryString) .appendQuery("page" -> page.toString) @@ -125,13 +125,4 @@ package object html { out.print(in.parseDateTime(date)) } - - def sortVersions(versions: Set[String], - filter: BinaryVersion => Boolean): List[String] = { - versions.toList - .flatMap(BinaryVersion.parse) - .filter(filter) - .sorted - .map(_.toString) - } } diff --git a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html index b9ce0e6de..4f781482f 100644 --- a/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html +++ b/template/src/main/twirl/ch.epfl.scala.index.views/search/resultList.scala.html @@ -27,7 +27,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaVersion.nonEmpty){
Scala (JVM): - @for(v <- sortVersions(project.scalaVersion, ScalaTarget.isValidScalaVersion)) { + @for(v <- project.scalaVersion) { @v }
@@ -36,7 +36,7 @@

@project.reference.organization/@project.reference.repository

@if(project.sbtVersion.nonEmpty){
Sbt: - @for(v <- sortVersions(project.sbtVersion, ScalaTarget.isValidSbtVersion)) { + @for(v <- project.sbtVersion) { @v }
@@ -45,7 +45,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaJsVersion.nonEmpty){
Scala.js: - @for(v <- sortVersions(project.scalaJsVersion, ScalaTarget.isValidScalaJsVersion)) { + @for(v <- project.scalaJsVersion) { @v }
@@ -54,7 +54,7 @@

@project.reference.organization/@project.reference.repository

@if(project.scalaNativeVersion.nonEmpty){
Scala-Native: - @for(v <- sortVersions(project.scalaNativeVersion, ScalaTarget.isValidScalaNativeVersion)) { + @for(v <- project.scalaNativeVersion) { @v }
From a04a5f1e099f6d0d104c107a71537d8400295f3d Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Mon, 6 Apr 2020 15:26:54 +0200 Subject: [PATCH 07/10] catch and log exceptions in SemanticVersion.tryParse --- .../scala/ch.epfl.scala.index.data/Main.scala | 21 ++++++++------ .../project/ArtifactMetaExtractor.scala | 4 +-- .../project/ProjectConvert.scala | 10 ++----- .../BinaryVersion.scala | 2 +- .../SemanticVersion.scala | 26 +++++++++++++---- .../release/DefaultRelease.scala | 2 +- .../SemanticVersionTests.scala | 26 ++++++++--------- .../release/DefaultReleaseTests.scala | 28 +++++++++---------- .../release/TestHelpers.scala | 2 +- .../release/VersionFilteringTests.scala | 4 +-- 10 files changed, 69 insertions(+), 56 deletions(-) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala index dfdfde22e..a0406e2a0 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala @@ -4,11 +4,7 @@ import java.nio.file.Path import akka.actor.ActorSystem import akka.stream.ActorMaterializer -import ch.epfl.scala.index.data.bintray.{ - BintrayDownloadPoms, - BintrayDownloadSbtPlugins, - BintrayListPoms -} +import ch.epfl.scala.index.data.bintray.{BintrayDownloadPoms, BintrayDownloadSbtPlugins, BintrayListPoms} import ch.epfl.scala.index.data.central.CentralMissing import ch.epfl.scala.index.data.cleanup.{GithubRepoExtractor, NonStandardLib} import ch.epfl.scala.index.data.elastic.SeedElasticSearch @@ -16,6 +12,7 @@ import ch.epfl.scala.index.data.github.GithubDownload import ch.epfl.scala.index.data.maven.DownloadParentPoms import ch.epfl.scala.index.data.util.PidLock import com.typesafe.config.ConfigFactory +import com.typesafe.scalalogging.LazyLogging import org.slf4j.LoggerFactory import scala.sys.process.Process @@ -23,9 +20,17 @@ import scala.sys.process.Process /** * This application manages indexed POMs. */ -object Main { +object Main extends LazyLogging { - private val logger = LoggerFactory.getLogger(getClass) + def main(args: Array[String]): Unit = { + try { + run(args) + } catch { + case fatal: Throwable => + logger.error("fatal error", fatal) + sys.exit(1) + } + } /** * Update data: @@ -39,7 +44,7 @@ object Main { * - Path of the 'index' Git repository * - Path of the 'credentials' Git repository */ - def main(args: Array[String]): Unit = { + def run(args: Array[String]): Unit = { val config = ConfigFactory.load().getConfig("org.scala_lang.index.data") val production = config.getBoolean("production") diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala index 64ac71792..4075ff752 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala @@ -81,7 +81,7 @@ class ArtifactMetaExtractor(paths: DataPaths) { dep.groupId == "org.scala-lang" && dep.artifactId == "scala-library" ) - .flatMap(dep => SemanticVersion.parse(dep.version)) + .flatMap(dep => SemanticVersion.tryParse(dep.version)) .map { version => // we assume binary compatibility ArtifactMeta( @@ -103,7 +103,7 @@ class ArtifactMetaExtractor(paths: DataPaths) { // For example: scala-compiler case Some(ScalaTargetFromVersion) => - SemanticVersion(pom.version).map( + SemanticVersion.tryParse(pom.version).map( version => ArtifactMeta( artifactName = pom.artifactId, diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala index f5dab956a..430a9dbea 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ProjectConvert.scala @@ -36,12 +36,11 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) val githubRepoExtractor = new GithubRepoExtractor(paths) log.info("Collecting Metadata") - val pomsAndMetaClean = PomMeta(pomsRepoSha, paths).flatMap { case PomMeta(pom, created, resolver) => for { artifactMeta <- artifactMetaExtractor(pom) - version <- SemanticVersion(pom.version) + version <- SemanticVersion.tryParse(pom.version) github <- githubRepoExtractor(pom) } yield (github, @@ -184,12 +183,9 @@ class ProjectConvert(paths: DataPaths, githubDownload: GithubDownload) log.info("Dependencies & Reverse Dependencies") - val mavenReferenceToReleaseReference - : Map[MavenReference, Release.Reference] = + val mavenReferenceToReleaseReference = projectsAndReleases - .flatMap { - case (_, releases) => releases - } + .flatMap { case (_, releases) => releases } .map(release => (release.maven, release.reference)) .toMap diff --git a/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala index c053b0e2c..75353ae6e 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/BinaryVersion.scala @@ -33,7 +33,7 @@ final case class PreReleaseBinary(major: Int, object BinaryVersion extends Parsers { import fastparse._ import fastparse.NoWhitespace._ - + implicit val ordering: Ordering[BinaryVersion] = Ordering.by { case MajorBinary(major) => (major, None, None, None) case MinorBinary(major, minor) => (major, Some(minor), None, None) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index b6054b10c..5708668ba 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -1,7 +1,12 @@ package ch.epfl.scala.index.model +import com.typesafe.scalalogging.LazyLogging + +import scala.util.control.NonFatal + /** * Semantic version, separation of possible combinations + * * @param major the major version number * @param minor the minor version number * @param patch the path version number @@ -38,7 +43,7 @@ case class SemanticVersion( } } -object SemanticVersion extends Parsers { +object SemanticVersion extends Parsers with LazyLogging { implicit val ordering: Ordering[SemanticVersion] = Ordering.by { x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) } @@ -83,11 +88,20 @@ object SemanticVersion extends Parsers { } private def FullParser[_: P] = Start ~ Parser ~ End - def parse(version: String): Option[SemanticVersion] = apply(version) - def apply(version: String): Option[SemanticVersion] = { - fastparse.parse(version, x => FullParser(x)) match { - case Parsed.Success(v, _) => Some(v) - case _ => None + + def tryParse(version: String): Option[SemanticVersion] = { + try { + fastparse.parse(version, x => FullParser(x)) match { + case Parsed.Success(v, _) => Some(v) + case _ => + logger.warn(s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version") + None + } + } catch { + case NonFatal(_) => + logger.warn(s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version") + None } + } } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala index 610e93c06..159f62546 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/DefaultRelease.scala @@ -17,7 +17,7 @@ object ReleaseSelection { new ReleaseSelection( target.flatMap(ScalaTarget.parse), artifactName, - version.flatMap(SemanticVersion.parse), + version.flatMap(SemanticVersion.tryParse), selected ) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala index 5f78abfde..56307053b 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala @@ -7,7 +7,7 @@ class SemanticVersionTests extends FunSpec with Matchers { it("has an ordering") { def order(versions: List[String]): List[SemanticVersion] = versions - .flatMap(v => parseVersion(v)) + .flatMap(v => SemanticVersion.tryParse(v)) .sorted(Descending[SemanticVersion]) val versions = List( @@ -40,40 +40,40 @@ class SemanticVersionTests extends FunSpec with Matchers { describe("parsing") { // relaxed semantic version it("major") { - parseVersion("1") should contain(SemanticVersion(1)) + SemanticVersion.tryParse("1") should contain(SemanticVersion(1)) } // relaxed semantic version it("major.minor") { - parseVersion("1.2") should contain(SemanticVersion(1, 2)) + SemanticVersion.tryParse("1.2") should contain(SemanticVersion(1, 2)) } it("major.minor.patch") { - parseVersion("1.2.3") should contain(SemanticVersion(1, 2, 3)) + SemanticVersion.tryParse("1.2.3") should contain(SemanticVersion(1, 2, 3)) } // relaxed semantic version it("major.minor.patch.patch2") { - parseVersion("1.2.3.4") should contain( + SemanticVersion.tryParse("1.2.3.4") should contain( SemanticVersion(1, 2, 3, 4) ) } it("major.minor.patch-rc") { - parseVersion("1.2.3-RC5") should contain( + SemanticVersion.tryParse("1.2.3-RC5") should contain( SemanticVersion(1, 2, 3, ReleaseCandidate(5)) ) } it("major.minor.patch-m") { - parseVersion("1.2.3-M6") should contain( + SemanticVersion.tryParse("1.2.3-M6") should contain( SemanticVersion(1, 2, 3, Milestone(6)) ) } it("major.minor.patch-xyz") { - parseVersion("1.1.1-xyz") should contain( + SemanticVersion.tryParse("1.1.1-xyz") should contain( SemanticVersion(1, Some(1), Some(1), @@ -83,7 +83,7 @@ class SemanticVersionTests extends FunSpec with Matchers { } it("major.minor.patch+meta") { - parseVersion("1.1.1+some.meta~data") should contain( + SemanticVersion.tryParse("1.1.1+some.meta~data") should contain( SemanticVersion( major = 1, minor = Some(1), @@ -94,16 +94,14 @@ class SemanticVersionTests extends FunSpec with Matchers { } it("git commit") { - parseVersion("13e7afa9c1817d45b2989e545b2e9ead21d00cef") shouldBe empty + SemanticVersion.tryParse("13e7afa9c1817d45b2989e545b2e9ead21d00cef") shouldBe empty + SemanticVersion.tryParse("6988989374b307bc6a57f9a3d218fead6c4c634f") shouldBe empty } // relaxed semantic version it("v sufix") { - parseVersion("v1") should contain(SemanticVersion(1)) + SemanticVersion.tryParse("v1") should contain(SemanticVersion(1)) } } } - - private def parseVersion(v: String): Option[SemanticVersion] = - SemanticVersion(v) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala index bcef3b554..18a037fd6 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/DefaultReleaseTests.scala @@ -38,7 +38,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { case (artifactId, rawVersion) => for { Artifact(artifact, target) <- Artifact.parse(artifactId) - version <- SemanticVersion(rawVersion) + version <- SemanticVersion.tryParse(rawVersion) } yield (artifactId, rawVersion, artifact, target, version) } .map { @@ -101,12 +101,12 @@ class DefaultReleaseTests extends FunSpec with Matchers { val versions: List[SemanticVersion] = List( - SemanticVersion("0.6.0").get, - SemanticVersion("0.6.0-M2").get, - SemanticVersion("0.6.0-M1").get, - SemanticVersion("0.5.0").get, - SemanticVersion("0.4.1").get, - SemanticVersion("0.4.0").get + SemanticVersion(0, 6, 0), + SemanticVersion(0, 6, 0, Milestone(2)), + SemanticVersion(0, 6, 0, Milestone(1)), + SemanticVersion(0, 5, 0), + SemanticVersion(0, 4, 1), + SemanticVersion(0, 4, 0) ) val targets: List[ScalaTarget] = @@ -130,7 +130,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { organization, repository, "cats-core", - SemanticVersion("0.6.0").get, + SemanticVersion(0, 6, 0), Some(ScalaJvm(MinorBinary(2, 11))) ) ) @@ -173,7 +173,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { "akka-distributed-data-experimental" ), versions = List( - SemanticVersion("2.4.8").get + SemanticVersion(2, 4, 8) ), targets = List( ScalaJvm(MinorBinary(2, 11)) @@ -186,7 +186,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { organization, repository, "akka-distributed-data-experimental", - SemanticVersion("2.4.8").get, + SemanticVersion(2, 4, 8), Some(ScalaJvm(MinorBinary(2, 11))) ) ) @@ -221,8 +221,8 @@ class DefaultReleaseTests extends FunSpec with Matchers { val versions: List[SemanticVersion] = List( - SemanticVersion("0.3.4").get, - SemanticVersion("0.5.3").get + SemanticVersion(0, 3, 4), + SemanticVersion(0, 5, 3) ) val targets: List[ScalaTarget] = @@ -245,7 +245,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { organization, repository, "scalafix-core", - SemanticVersion("0.5.3").get, + SemanticVersion(0, 5, 3), Some(ScalaJvm(MinorBinary(2, 12))) ) ) @@ -253,7 +253,7 @@ class DefaultReleaseTests extends FunSpec with Matchers { ) assert( - result.get.release.reference.version == SemanticVersion("0.5.3").get + result.get.release.reference.version == SemanticVersion(0, 5, 3) ) } } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala index 81ee3a05a..688d56672 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/TestHelpers.scala @@ -28,7 +28,7 @@ trait TestHelpers { ), reference = Release.Reference( artifact = artifactName, - version = SemanticVersion(version).get, + version = SemanticVersion.tryParse(version).get, target = target, // Not necessary for the test organization = "GitHub-Org", diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/VersionFilteringTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/VersionFilteringTests.scala index 8e22ffa06..3daed2fa1 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/VersionFilteringTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/VersionFilteringTests.scala @@ -56,7 +56,7 @@ class VersionFilteringTests extends FunSuite { "0.8.1-RC3", "0.8.1-RC2", "0.8.1-RC1" - ).flatMap(SemanticVersion.parse) + ).flatMap(SemanticVersion.tryParse) val obtained = versions.filter(_.isSemantic) @@ -95,7 +95,7 @@ class VersionFilteringTests extends FunSuite { "0.8.1-RC3", "0.8.1-RC2", "0.8.1-RC1" - ).flatMap(SemanticVersion.parse) + ).flatMap(SemanticVersion.tryParse) assert((obtained.toSet -- expected.toSet).isEmpty) assert((expected.toSet -- obtained.toSet).isEmpty) From eb537f2b4e23c2bcd9b757ea69bcab261be4f34d Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Mon, 6 Apr 2020 18:07:38 +0200 Subject: [PATCH 08/10] better ScalaTarget ordering --- .../ch.epfl.scala.index.model/release/ScalaTarget.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index ec74c25f5..ca9ea570a 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -55,7 +55,7 @@ case class ScalaJs(scalaVersion: BinaryVersion, scalaJsVersion: BinaryVersion) case class ScalaNative(scalaVersion: BinaryVersion, scalaNativeVersion: BinaryVersion) extends ScalaTarget { - val render = s"scala-native $scalaNativeVersion ($scalaNativeVersion)" + val render = s"scala-native $scalaNativeVersion ($scalaVersion)" val encode = s"_native${scalaNativeVersion}_$scalaVersion" val targetType: ScalaTargetType = Native val isValid: Boolean = ScalaJvm.isValid(scalaVersion) && ScalaNative.isValid( @@ -139,10 +139,9 @@ object ScalaTarget extends Parsers { (ScalaTargetType, BinaryVersion, Option[BinaryVersion]) ] { case ScalaJvm(version) => (Jvm, version, None) - case ScalaJs(version, jsVersion) => (Js, version, Some(jsVersion)) - case ScalaNative(version, nativeVersion) => - (Native, version, Some(nativeVersion)) - case SbtPlugin(version, sbtVersion) => (Sbt, version, Some(sbtVersion)) + case ScalaJs(version, jsVersion) => (Js, jsVersion, Some(version)) + case ScalaNative(version, nativeVersion) => (Native, nativeVersion, Some(version)) + case SbtPlugin(version, sbtVersion) => (Sbt, sbtVersion, Some(version)) } def parse(code: String): Option[ScalaTarget] = { From 4fd3bc8d33ad2e5e48162a9dc4c47f40bd9ca0e6 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Mon, 6 Apr 2020 18:20:54 +0200 Subject: [PATCH 09/10] fix tests + scalafmt --- .../scala/ch.epfl.scala.index.data/Main.scala | 6 +++++- .../project/ArtifactMetaExtractor.scala | 16 +++++++++------- .../SemanticVersion.scala | 12 ++++++++---- .../release/ScalaTarget.scala | 5 +++-- .../BinaryVersionTests.scala | 4 +++- .../SemanticVersionTests.scala | 4 +++- .../release/ScalaTargetTests.scala | 2 +- 7 files changed, 32 insertions(+), 17 deletions(-) diff --git a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala index a0406e2a0..c142c84bb 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/Main.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/Main.scala @@ -4,7 +4,11 @@ import java.nio.file.Path import akka.actor.ActorSystem import akka.stream.ActorMaterializer -import ch.epfl.scala.index.data.bintray.{BintrayDownloadPoms, BintrayDownloadSbtPlugins, BintrayListPoms} +import ch.epfl.scala.index.data.bintray.{ + BintrayDownloadPoms, + BintrayDownloadSbtPlugins, + BintrayListPoms +} import ch.epfl.scala.index.data.central.CentralMissing import ch.epfl.scala.index.data.cleanup.{GithubRepoExtractor, NonStandardLib} import ch.epfl.scala.index.data.elastic.SeedElasticSearch diff --git a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala index 4075ff752..a62d41c76 100644 --- a/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala +++ b/data/src/main/scala/ch.epfl.scala.index.data/project/ArtifactMetaExtractor.scala @@ -103,14 +103,16 @@ class ArtifactMetaExtractor(paths: DataPaths) { // For example: scala-compiler case Some(ScalaTargetFromVersion) => - SemanticVersion.tryParse(pom.version).map( - version => - ArtifactMeta( - artifactName = pom.artifactId, - scalaTarget = Some(ScalaJvm.fromFullVersion(version)), - isNonStandard = true + SemanticVersion + .tryParse(pom.version) + .map( + version => + ArtifactMeta( + artifactName = pom.artifactId, + scalaTarget = Some(ScalaJvm.fromFullVersion(version)), + isNonStandard = true + ) ) - ) } } } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala index 5708668ba..5e3365f6c 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/SemanticVersion.scala @@ -43,7 +43,7 @@ case class SemanticVersion( } } -object SemanticVersion extends Parsers with LazyLogging { +object SemanticVersion extends Parsers with LazyLogging { implicit val ordering: Ordering[SemanticVersion] = Ordering.by { x => (x.major, x.minor, x.patch, x.patch2, x.preRelease) } @@ -93,13 +93,17 @@ object SemanticVersion extends Parsers with LazyLogging { try { fastparse.parse(version, x => FullParser(x)) match { case Parsed.Success(v, _) => Some(v) - case _ => - logger.warn(s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version") + case _ => + logger.warn( + s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version" + ) None } } catch { case NonFatal(_) => - logger.warn(s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version") + logger.warn( + s"cannot parse ${classOf[SemanticVersion].getSimpleName} $version" + ) None } diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index ca9ea570a..91c0e47ef 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -127,7 +127,7 @@ object SbtPlugin { private def stableBinaryVersions = Set(`0.13`, `1.0`, `1.x`) def isValid(version: BinaryVersion): Boolean = { - stableBinaryVersions.contains(version) + stableBinaryVersions.contains(version) } } @@ -140,7 +140,8 @@ object ScalaTarget extends Parsers { ] { case ScalaJvm(version) => (Jvm, version, None) case ScalaJs(version, jsVersion) => (Js, jsVersion, Some(version)) - case ScalaNative(version, nativeVersion) => (Native, nativeVersion, Some(version)) + case ScalaNative(version, nativeVersion) => + (Native, nativeVersion, Some(version)) case SbtPlugin(version, sbtVersion) => (Sbt, sbtVersion, Some(version)) } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala index 4ab1df9ab..4ce6ee07e 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/BinaryVersionTests.scala @@ -36,6 +36,8 @@ class BinaryVersionTests (MajorBinary(1), PreReleaseBinary(2, 0, None, Milestone(1))) ) - forAll(inputs) { (lower, higher) => lower shouldBe < (higher)} + forAll(inputs) { (lower, higher) => + lower shouldBe <(higher) + } } } diff --git a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala index 56307053b..b35e03b47 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/SemanticVersionTests.scala @@ -49,7 +49,9 @@ class SemanticVersionTests extends FunSpec with Matchers { } it("major.minor.patch") { - SemanticVersion.tryParse("1.2.3") should contain(SemanticVersion(1, 2, 3)) + SemanticVersion.tryParse("1.2.3") should contain( + SemanticVersion(1, 2, 3) + ) } // relaxed semantic version diff --git a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala index 89a10e717..9a1dc9aad 100644 --- a/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala +++ b/model/src/test/scala/ch.epfl.scala.index.model/release/ScalaTargetTests.scala @@ -31,8 +31,8 @@ class ScalaTargetTests val expected = List( ScalaNative(s211, nat03), ScalaJs(s210, js067), - ScalaJs(s210, js0618), ScalaJs(s211, js067), + ScalaJs(s210, js0618), ScalaJs(s211, js0618), ScalaJs(s212, js0618), ScalaJvm(s210), From e882e10f8c8e4d22c86306ff9b1882c55ced5461 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 9 Apr 2020 09:28:23 +0200 Subject: [PATCH 10/10] remove sbt version1.x --- .../ch.epfl.scala.index.model/release/ScalaTarget.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala index 91c0e47ef..c269d68af 100644 --- a/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala +++ b/model/src/main/scala/ch.epfl.scala.index.model/release/ScalaTarget.scala @@ -94,7 +94,7 @@ object ScalaJvm { val `2.12`: BinaryVersion = MinorBinary(2, 12) val `2.13`: BinaryVersion = MinorBinary(2, 13) - private def stableBinaryVersions = Set(`2.10`, `2.11`, `2.12`, `2.13`) + private val stableBinaryVersions = Set(`2.10`, `2.11`, `2.12`, `2.13`) def isValid(version: BinaryVersion): Boolean = stableBinaryVersions.contains(version) @@ -104,7 +104,7 @@ object ScalaJs { val `0.6`: BinaryVersion = MinorBinary(0, 6) val `1.x`: BinaryVersion = MajorBinary(1) - private def stableBinaryVersions = Set(`0.6`, `1.x`) + private val stableBinaryVersions = Set(`0.6`, `1.x`) def isValid(version: BinaryVersion): Boolean = stableBinaryVersions.contains(version) @@ -122,9 +122,8 @@ object ScalaNative { object SbtPlugin { val `0.13`: BinaryVersion = MinorBinary(0, 13) val `1.0`: BinaryVersion = MinorBinary(1, 0) - val `1.x`: BinaryVersion = MajorBinary(1) - private def stableBinaryVersions = Set(`0.13`, `1.0`, `1.x`) + private val stableBinaryVersions = Set(`0.13`, `1.0`) def isValid(version: BinaryVersion): Boolean = { stableBinaryVersions.contains(version)