Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIT ScalaVersionUtil refactor #1384

Merged
merged 2 commits into from Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 2 additions & 4 deletions modules/build/src/main/scala/scala/build/Build.scala
Expand Up @@ -18,7 +18,7 @@ import scala.build.compiler.{ScalaCompiler, ScalaCompilerMaker}
import scala.build.errors.*
import scala.build.internal.resource.ResourceMapper
import scala.build.internal.{Constants, CustomCodeWrapper, MainClass, Util}
import scala.build.options.ScalaVersionUtil.maybeScalaPatchVersion
import scala.build.options.ScalaVersionUtil.asVersion
import scala.build.options.*
import scala.build.options.validation.ValidationException
import scala.build.postprocessing.*
Expand Down Expand Up @@ -828,9 +828,7 @@ object Build {

val scalacReleaseV =
// the -release flag is not supported for Scala 2.12.x < 2.12.5
if params.scalaVersion.startsWith("2.12") &&
params.scalaVersion.maybeScalaPatchVersion.exists(_ < 5)
then Nil
if params.scalaVersion.asVersion < "2.12.5".asVersion then Nil
else
releaseFlagVersion
.map(v => List("-release", v).map(ScalacOpt(_)))
Expand Down
Expand Up @@ -18,6 +18,7 @@ import scala.build.interactive.Interactive
import scala.build.interactive.Interactive.{InteractiveAsk, InteractiveNop}
import scala.build.internal.CsLoggerUtil.*
import scala.build.internal.{Constants, FetchExternalBinary, OsLibc, Util}
import scala.build.options.ScalaVersionUtil.fileWithTtl0
import scala.build.options.{Platform, ScalacOpt, ShadowingSeq}
import scala.build.options as bo
import scala.cli.ScalaCli
Expand All @@ -36,14 +37,9 @@ object SharedOptionsUtil extends CommandHelpers {
private def downloadInputs(cache: FileCache[Task]): String => Either[String, Array[Byte]] = {
url =>
val artifact = Artifact(url).withChanging(true)
val res = cache.logger.use {
try cache.withTtl(0.seconds).file(artifact).run.unsafeRun()(cache.ec)
catch {
case NonFatal(e) => throw new Exception(e)
}
}
res
.left.map(_.describe)
cache.fileWithTtl0(artifact)
.left
.map(_.describe)
.map(f => os.read.bytes(os.Path(f, Os.pwd)))
}

Expand Down
10 changes: 2 additions & 8 deletions modules/cli/src/main/scala/scala/cli/launcher/LauncherCli.scala
Expand Up @@ -8,6 +8,7 @@ import dependency._

import scala.build.internal.CsLoggerUtil.CsCacheExtensions
import scala.build.internal.{Constants, OsLibc, Runner}
import scala.build.options.ScalaVersionUtil.fileWithTtl0
import scala.build.options.{BuildOptions, JavaOptions}
import scala.build.{Artifacts, Os, Positioned}
import scala.cli.commands.util.CommonOps._
Expand Down Expand Up @@ -83,14 +84,7 @@ object LauncherCli {
val snapshotRepoUrl =
s"https://oss.sonatype.org/content/repositories/snapshots/org/virtuslab/scala-cli/cli_${scalaParameters.scalaBinaryVersion}/"
val artifact = Artifact(snapshotRepoUrl).withChanging(true)
val res = cache.logger.use {
try cache.withTtl(0.seconds).file(artifact).run.unsafeRun()(cache.ec)
catch {
case NonFatal(e) => throw new Exception(e)
}
}

res match {
cache.fileWithTtl0(artifact) match {
case Left(_) =>
System.err.println("Unable to find nightly Scala CLI version")
sys.exit(1)
Expand Down
Expand Up @@ -10,6 +10,7 @@ import scala.build.actionable.errors.ActionableHandlerError
import scala.build.errors.BuildException
import scala.build.internal.Util._
import scala.build.options.BuildOptions
import scala.build.options.ScalaVersionUtil.versionsWithTtl0
import scala.concurrent.duration.DurationInt

case object ActionableDependencyHandler
Expand Down Expand Up @@ -43,15 +44,8 @@ case object ActionableDependencyHandler
val cache = buildOptions.finalCache
val csModule = value(dependency.toCs(scalaParams)).module

val res = cache.withTtl(0.seconds).logger.use {
Versions(cache)
.withModule(csModule)
.result()
.unsafeRun()(cache.ec)
}

value {
res.versions.latest(coursier.core.Latest.Release).toRight {
cache.versionsWithTtl0(csModule).versions.latest(coursier.core.Latest.Release).toRight {
new ActionableHandlerError(s"No latest version found for ${dependency.render}")
}
}
Expand Down
@@ -1,13 +1,15 @@
package scala.build.options

import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core.*
import com.github.plokhotnyuk.jsoniter_scala.macros.*
import coursier.Versions
import coursier.cache.FileCache
import coursier.core.{Version, Versions => CoreVersions}
import coursier.cache.{ArtifactError, FileCache}
import coursier.core.{Module, Repository, Version, Versions as CoreVersions}
import coursier.util.{Artifact, Task}

import scala.build.CoursierUtils._
import java.io.File

import scala.build.CoursierUtils.*
import scala.build.EitherCps.{either, value}
import scala.build.errors.{
BuildException,
Expand All @@ -27,6 +29,44 @@ object ScalaVersionUtil {
private def scala2Library = cmod"org.scala-lang:scala-library"
private def scala3Library = cmod"org.scala-lang:scala3-library_3"

extension (cache: FileCache[Task]) {
def fileWithTtl0(artifact: Artifact): Either[ArtifactError, File] =
cache.logger.use {
try cache.withTtl(0.seconds).file(artifact).run.unsafeRun()(cache.ec)
catch {
case NonFatal(e) => throw new Exception(e)
}
}

def versionsWithTtl0(
module: Module,
repositories: Seq[Repository] = Seq.empty
): Versions.Result =
cache.withTtl(0.seconds).logger.use {
val versionsWithModule = Versions(cache)
.withModule(module)
val versionsWithRepositories =
if repositories.nonEmpty then versionsWithModule.withRepositories(repositories)
else versionsWithModule
versionsWithRepositories
.result()
.unsafeRun()(cache.ec)
}
}

extension (versionsResult: Versions.Result) {
def verify(
versionString: String,
latestSupportedStableVersions: Seq[String]
): Either[BuildException, Unit] =
if versionsResult.versions.available.contains(versionString) then Right(())
else
Left(new NoValidScalaVersionFoundError(
versionsResult.versions.available,
latestSupportedStableVersions
))
}

object GetNightly {

private object Scala2Repo {
Expand All @@ -42,17 +82,13 @@ object ScalaVersionUtil {
val scala2NightlyRepo =
"https://scala-ci.typesafe.com/ui/api/v1/ui/nativeBrowser/scala-integration/org/scala-lang/scala-compiler"
val artifact = Artifact(scala2NightlyRepo).withChanging(true)
val res = cache.logger.use {
try cache.withTtl(0.seconds).file(artifact).run.unsafeRun()(cache.ec)
catch {
case NonFatal(e) => throw new Exception(e)
val res = cache.fileWithTtl0(artifact)
.left.map { err =>
val msg =
"""|Unable to compute the latest Scala 2 nightly version.
|Throws error during downloading web page repository for Scala 2.""".stripMargin
new ScalaVersionError(msg, cause = err)
}
}.left.map { err =>
val msg =
"""|Unable to compute the latest Scala 2 nightly version.
|Throws error during downloading web page repository for Scala 2.""".stripMargin
new ScalaVersionError(msg, cause = err)
}

val res0 = value(res)
val content = os.read.bytes(os.Path(res0, os.pwd))
Expand Down Expand Up @@ -88,12 +124,8 @@ object ScalaVersionUtil {
cache: FileCache[Task],
latestSupportedStableVersions: Seq[String]
): Either[BuildException, String] = {
val res = cache.withTtl(0.seconds).logger.use {
Versions(cache)
.withModule(scala3Library)
.result()
.unsafeRun()(cache.ec)
}.versions.available.filter(_.endsWith("-NIGHTLY"))
val res = cache.versionsWithTtl0(scala3Library)
.versions.available.filter(_.endsWith("-NIGHTLY"))

val threeXNightlies = res.filter(_.startsWith(s"3.$threeSubBinaryNum.")).map(Version(_))
if (threeXNightlies.nonEmpty) Right(threeXNightlies.max.repr)
Expand All @@ -105,15 +137,11 @@ object ScalaVersionUtil {
/** @return
* Either a BuildException or the calculated (ScalaVersion, ScalaBinaryVersion) tuple
*/
def scala3(cache: FileCache[Task]): Either[BuildException, String] = {
val res = cache.withTtl(0.seconds).logger.use {
Versions(cache)
.withModule(scala3Library)
.result()
.unsafeRun()(cache.ec)
}
latestScalaVersionFrom(res.versions, "latest Scala 3 nightly build")
}
def scala3(cache: FileCache[Task]): Either[BuildException, String] =
latestScalaVersionFrom(
cache.versionsWithTtl0(scala3Library).versions,
"latest Scala 3 nightly build"
)

private def latestScalaVersionFrom(
versions: CoreVersions,
Expand All @@ -136,40 +164,16 @@ object ScalaVersionUtil {
versionString: String,
cache: FileCache[Task],
latestSupportedStableVersions: Seq[String]
): Either[BuildException, Unit] = {
val res = cache.withTtl(0.seconds).logger.use {
Versions(cache)
.withModule(scala2Library)
.withRepositories(Seq(coursier.Repositories.scalaIntegration))
.result()
.unsafeRun()(cache.ec)
}
if (res.versions.available.contains(versionString))
Right(())
else
Left(
new NoValidScalaVersionFoundError(res.versions.available, latestSupportedStableVersions)
)
}
): Either[BuildException, Unit] =
cache.versionsWithTtl0(scala2Library, Seq(coursier.Repositories.scalaIntegration))
.verify(versionString, latestSupportedStableVersions)

def scala3(
versionString: String,
cache: FileCache[Task],
latestSupportedStableVersions: Seq[String]
): Either[BuildException, Unit] = {
val res = cache.withTtl(0.seconds).logger.use {
Versions(cache)
.withModule(scala3Library)
.result()
.unsafeRun()(cache.ec)
}
if (res.versions.available.contains(versionString))
Right(())
else
Left(
new NoValidScalaVersionFoundError(res.versions.available, latestSupportedStableVersions)
)
}
): Either[BuildException, Unit] =
cache.versionsWithTtl0(scala3Library).verify(versionString, latestSupportedStableVersions)
}

def validateNonStable(
Expand Down Expand Up @@ -293,9 +297,6 @@ object ScalaVersionUtil {
}

extension (sv: String) {
def maybeScalaPatchVersion: Option[Int] = sv
.split('.').drop(2).headOption
.flatMap(_.split('-').headOption)
.flatMap(pv => Try(pv.toInt).toOption)
def asVersion: Version = Version(sv)
}
}