Skip to content

Commit a254163

Browse files
committed
Add fallback to scalac when JVM for Bloop cannot be downloaded
1 parent 332ad1e commit a254163

File tree

6 files changed

+68
-39
lines changed

6 files changed

+68
-39
lines changed

modules/build/src/main/scala/scala/build/internal/util/WarningMessages.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,7 @@ object WarningMessages {
101101

102102
val offlineModeBloopNotFound =
103103
"Offline mode is ON and Bloop could not be fetched from the local cache, using scalac as fallback"
104+
105+
val offlineModeBloopJvmNotFound =
106+
"Offline mode is ON and a JVM for Bloop could not be fetched from the local cache, using scalac as fallback"
104107
}

modules/cli/src/main/scala/scala/cli/commands/bloop/Bloop.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ object Bloop extends ScalaCommand[BloopOptions] {
3939
.map(JvmUtils.downloadJvm(_, options))
4040
.getOrElse {
4141
JvmUtils.getJavaCmdVersionOrHigher(17, options)
42-
}
42+
}.orExit(logger)
4343

4444
opts.compilationServer.bloopRifleConfig(
4545
opts.global.logging.logger,

modules/cli/src/main/scala/scala/cli/commands/pgp/PgpExternalCommand.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ object PgpExternalCommand {
159159
JvmUtils.getJavaCmdVersionOrHigher(
160160
scalaCliSigningJvmVersion,
161161
buildOptions
162-
)
162+
).orThrow
163163

164164
launcher(
165165
cache,

modules/cli/src/main/scala/scala/cli/commands/shared/SharedOptions.scala

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ import scala.build.Ops.EitherOptOps
1818
import scala.build.*
1919
import scala.build.compiler.{BloopCompilerMaker, ScalaCompilerMaker, SimpleScalaCompilerMaker}
2020
import scala.build.directives.DirectiveDescription
21-
import scala.build.errors.{AmbiguousPlatformError, BuildException, ConfigDbException}
21+
import scala.build.errors.{AmbiguousPlatformError, BuildException, ConfigDbException, Severity}
2222
import scala.build.input.{Element, Inputs, ResourceDirectory, ScalaCliInvokeData}
2323
import scala.build.interactive.Interactive
2424
import scala.build.interactive.Interactive.{InteractiveAsk, InteractiveNop}
2525
import scala.build.internal.util.ConsoleUtils.ScalaCliConsole
26+
import scala.build.internal.util.WarningMessages
2627
import scala.build.internal.{Constants, FetchExternalBinary, ObjectCodeWrapper, OsLibc, Util}
2728
import scala.build.options.ScalaVersionUtil.fileWithTtl0
2829
import scala.build.options.{ComputeVersion, Platform, ScalacOpt, ShadowingSeq}
@@ -514,15 +515,19 @@ final case class SharedOptions(
514515

515516
def bloopRifleConfig(): Either[BuildException, BloopRifleConfig] = either {
516517
val options = value(buildOptions(false, None))
517-
lazy val defaultJvmCmd =
518-
JvmUtils.downloadJvm(OsLibc.baseDefaultJvm(OsLibc.jvmIndexOs, "17"), options)
519-
val javaCmd = compilationServer.bloopJvm.map(JvmUtils.downloadJvm(_, options)).orElse {
520-
for (javaHome <- options.javaHomeLocationOpt()) yield {
521-
val (javaHomeVersion, javaHomeCmd) = OsLibc.javaHomeVersion(javaHome.value)
522-
if (javaHomeVersion >= 17) javaHomeCmd
523-
else defaultJvmCmd
524-
}
525-
}.getOrElse(defaultJvmCmd)
518+
lazy val defaultJvmCmd = value {
519+
JvmUtils.downloadJvm(OsLibc.defaultJvm(OsLibc.jvmIndexOs), options)
520+
}
521+
522+
val javaCmd = compilationServer.bloopJvm
523+
.map(jvmId => value(JvmUtils.downloadJvm(jvmId, options)))
524+
.orElse {
525+
for (javaHome <- options.javaHomeLocationOpt()) yield {
526+
val (javaHomeVersion, javaHomeCmd) = OsLibc.javaHomeVersion(javaHome.value)
527+
if (javaHomeVersion >= 17) javaHomeCmd
528+
else defaultJvmCmd
529+
}
530+
}.getOrElse(defaultJvmCmd)
526531

527532
compilationServer.bloopRifleConfig(
528533
logging.logger,
@@ -537,19 +542,25 @@ final case class SharedOptions(
537542
def compilerMaker(
538543
threads: BuildThreads,
539544
scaladoc: Boolean = false
540-
): Either[BuildException, ScalaCompilerMaker] = either {
545+
): Either[BuildException, ScalaCompilerMaker] =
541546
if (scaladoc)
542-
SimpleScalaCompilerMaker("java", Nil, scaladoc = true)
547+
Right(SimpleScalaCompilerMaker("java", Nil, scaladoc = true))
543548
else if (compilationServer.server.getOrElse(true))
544-
new BloopCompilerMaker(
545-
value(bloopRifleConfig()),
546-
threads.bloop,
547-
strictBloopJsonCheckOrDefault,
548-
coursier.offline.getOrElse(false)
549-
)
549+
bloopRifleConfig() match {
550+
case Right(config) =>
551+
Right(new BloopCompilerMaker(
552+
config,
553+
threads.bloop,
554+
strictBloopJsonCheckOrDefault,
555+
coursier.offline.getOrElse(false)
556+
))
557+
case Left(ex) if coursier.offline.contains(true) =>
558+
logger.diagnostic(WarningMessages.offlineModeBloopJvmNotFound, Severity.Warning)
559+
Right(SimpleScalaCompilerMaker("java", Nil))
560+
case Left(ex) => Left(ex)
561+
}
550562
else
551-
SimpleScalaCompilerMaker("java", Nil)
552-
}
563+
Right(SimpleScalaCompilerMaker("java", Nil))
553564

554565
lazy val coursierCache = coursier.coursierCache(logging.logger.coursierLogger(""))
555566

modules/cli/src/main/scala/scala/cli/commands/util/JvmUtils.scala

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ package util
44
import java.io.File
55

66
import scala.build.EitherCps.{either, value}
7-
import scala.build.errors.{BuildException, UnrecognizedDebugModeError}
7+
import scala.build.errors.{BuildException, JvmDownloadError, UnrecognizedDebugModeError}
88
import scala.build.internal.CsLoggerUtil.*
99
import scala.build.internal.OsLibc
1010
import scala.build.options.{JavaOpt, JavaOptions, ShadowingSeq}
1111
import scala.build.{Os, Position, Positioned, options as bo}
1212
import scala.cli.commands.shared.{CoursierOptions, SharedJvmOptions, SharedOptions}
1313
import scala.concurrent.ExecutionContextExecutorService
14-
import scala.util.Properties
1514
import scala.util.control.NonFatal
15+
import scala.util.{Failure, Properties, Success, Try}
1616

1717
object JvmUtils {
1818
def javaOptions(opts: SharedJvmOptions): Either[BuildException, JavaOptions] = either {
@@ -67,38 +67,43 @@ object JvmUtils {
6767
)
6868
}
6969

70-
def downloadJvm(jvmId: String, options: bo.BuildOptions): String = {
70+
def downloadJvm(jvmId: String, options: bo.BuildOptions): Either[BuildException, String] = {
7171
implicit val ec: ExecutionContextExecutorService = options.finalCache.ec
7272
val javaHomeManager = options.javaHomeManager
7373
.withMessage(s"Downloading JVM $jvmId")
7474
val logger = javaHomeManager.cache
7575
.flatMap(_.archiveCache.cache.loggerOpt)
7676
.getOrElse(_root_.coursier.cache.CacheLogger.nop)
77-
val command = {
78-
val path = logger.use {
79-
try javaHomeManager.get(jvmId).unsafeRun()
80-
catch {
81-
case NonFatal(e) => throw new Exception(e)
82-
}
83-
}
84-
os.Path(path)
77+
78+
val javaHomePathOrError = Try(javaHomeManager.get(jvmId).unsafeRun()) match {
79+
case Success(path) => Right(path)
80+
case Failure(e) => Left(JvmDownloadError(jvmId, e))
81+
}
82+
83+
for {
84+
javaHomePath <- javaHomePathOrError
85+
} yield {
86+
val javaHome = os.Path(javaHomePath)
87+
val ext = if (Properties.isWin) ".exe" else ""
88+
val javaCmd = (javaHome / "bin" / s"java$ext").toString
89+
javaCmd
8590
}
86-
val ext = if (Properties.isWin) ".exe" else ""
87-
val javaCmd = (command / "bin" / s"java$ext").toString
88-
javaCmd
8991
}
9092

9193
def getJavaCmdVersionOrHigher(
9294
javaVersion: Int,
9395
options: bo.BuildOptions
94-
): String = {
96+
): Either[BuildException, String] = {
9597
val javaHomeCmdOpt = for {
9698
javaHome <- options.javaHomeLocationOpt()
9799
(javaHomeVersion, javaHomeCmd) = OsLibc.javaHomeVersion(javaHome.value)
98100
if javaHomeVersion >= javaVersion
99101
} yield javaHomeCmd
100102

101-
javaHomeCmdOpt.getOrElse(downloadJvm(javaVersion.toString, options))
103+
javaHomeCmdOpt match {
104+
case Some(cmd) => Right(cmd)
105+
case None => downloadJvm(javaVersion.toString, options)
106+
}
102107
}
103108

104109
def getJavaCmdVersionOrHigher(
@@ -110,6 +115,7 @@ object JvmUtils {
110115

111116
for {
112117
options <- sharedOpts.buildOptions()
113-
} yield getJavaCmdVersionOrHigher(javaVersion, options)
118+
javaCmd <- getJavaCmdVersionOrHigher(javaVersion, options)
119+
} yield javaCmd
114120
}
115121
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package scala.build.errors
2+
3+
import scala.build.Position
4+
5+
final class JvmDownloadError(jvmId: String, cause: Throwable)
6+
extends BuildException(
7+
s"Cannot download JVM: $jvmId",
8+
cause = cause
9+
)

0 commit comments

Comments
 (0)