From 4ac17b57e8cb74f7f2b220ab1a7c998851cdc566 Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Wed, 21 Sep 2022 14:34:16 +0200 Subject: [PATCH 1/2] NIT compare Scala versions with `coursier.core.Version` --- modules/build/src/main/scala/scala/build/Build.scala | 6 ++---- .../main/scala/scala/build/options/ScalaVersionUtil.scala | 5 +---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index c7ea1237a2..d3fa214fce 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -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.* @@ -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(_))) diff --git a/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala b/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala index 3a9908b7b9..2e9a21e83e 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala @@ -293,9 +293,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) } } From 6019787aef28a1a7baf9ac8425e6f161be3194d5 Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Wed, 21 Sep 2022 14:54:56 +0200 Subject: [PATCH 2/2] NIT Refactor ScalaVersionUtil --- .../cli/commands/util/SharedOptionsUtil.scala | 12 +- .../scala/cli/launcher/LauncherCli.scala | 10 +- .../ActionableDependencyHandler.scala | 10 +- .../build/options/ScalaVersionUtil.scala | 122 +++++++++--------- 4 files changed, 71 insertions(+), 83 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/util/SharedOptionsUtil.scala b/modules/cli/src/main/scala/scala/cli/commands/util/SharedOptionsUtil.scala index e1092783a5..4f91b94a9c 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/util/SharedOptionsUtil.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/util/SharedOptionsUtil.scala @@ -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 @@ -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))) } diff --git a/modules/cli/src/main/scala/scala/cli/launcher/LauncherCli.scala b/modules/cli/src/main/scala/scala/cli/launcher/LauncherCli.scala index 417b19f776..08ab97e392 100644 --- a/modules/cli/src/main/scala/scala/cli/launcher/LauncherCli.scala +++ b/modules/cli/src/main/scala/scala/cli/launcher/LauncherCli.scala @@ -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._ @@ -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) diff --git a/modules/options/src/main/scala/scala/build/actionable/ActionableDependencyHandler.scala b/modules/options/src/main/scala/scala/build/actionable/ActionableDependencyHandler.scala index 7f46fe03f8..e638dc9486 100644 --- a/modules/options/src/main/scala/scala/build/actionable/ActionableDependencyHandler.scala +++ b/modules/options/src/main/scala/scala/build/actionable/ActionableDependencyHandler.scala @@ -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 @@ -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}") } } diff --git a/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala b/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala index 2e9a21e83e..d2b6fe5954 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalaVersionUtil.scala @@ -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, @@ -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 { @@ -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)) @@ -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) @@ -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, @@ -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(