Skip to content

Commit

Permalink
Add a global offline config key
Browse files Browse the repository at this point in the history
  • Loading branch information
Gedochao committed Sep 30, 2024
1 parent 442facc commit 30e9e41
Show file tree
Hide file tree
Showing 20 changed files with 85 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ object BloopExit extends ScalaCommand[BloopExitOptions] {
import opts.*
compilationServer.bloopRifleConfig(
global.logging.logger,
coursier.coursierCache(global.logging.logger.coursierLogger("Downloading Bloop")),
coursier.coursierCache(global.logging.logger, cacheLoggerPrefix = "Downloading Bloop"),
global.logging.verbosity,
"java", // shouldn't be used…
Directories.directories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object BloopOutput extends ScalaCommand[BloopOutputOptions] {
override def runCommand(options: BloopOutputOptions, args: RemainingArgs, logger: Logger): Unit = {
val bloopRifleConfig = options.compilationServer.bloopRifleConfig(
logger,
CoursierOptions().coursierCache(logger.coursierLogger("Downloading Bloop")), // unused here
CoursierOptions().coursierCache(logger, cacheLoggerPrefix = "Downloading Bloop"), // unused here
options.global.logging.verbosity,
"unused-java", // unused here
Directories.directories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ object BloopStart extends ScalaCommand[BloopStartOptions] {
import opts.*
val buildOptions = BuildOptions(
javaOptions = JvmUtils.javaOptions(jvm).orExit(global.logging.logger),
internal = InternalOptions(
cache = Some(coursier.coursierCache(global.logging.logger.coursierLogger("")))
)
internal = InternalOptions(cache = Some(coursier.coursierCache(global.logging.logger)))
)

compilationServer.bloopRifleConfig(
global.logging.logger,
coursier.coursierCache(global.logging.logger.coursierLogger("Downloading Bloop")),
coursier.coursierCache(global.logging.logger, cacheLoggerPrefix = "Downloading Bloop"),
global.logging.verbosity,
buildOptions.javaHome().value.javaCommand,
Directories.directories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object Config extends ScalaCommand[ConfigOptions] {
)
sys.exit(1)
}
val coursierCache = options.coursier.coursierCache(logger.coursierLogger(""))
val coursierCache = options.coursier.coursierCache(logger)
val secKeyEntry = Keys.pgpSecretKey
val pubKeyEntry = Keys.pgpPublicKey

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Default(actualHelp: => RuntimeCommandsHelp)
Version.runCommand(
options = VersionOptions(
global = options.shared.global,
offline = options.shared.coursier.getOffline().getOrElse(false)
offline = options.shared.coursier.getOffline(logger).getOrElse(false)
),
args = args,
logger = logger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ object SecretCreate extends ScalaCommand[SecretCreateOptions] {
).orExit(logger)
}

val cache = options.coursier.coursierCache(logger.coursierLogger(""))
val cache = options.coursier.coursierCache(logger)
val archiveCache = ArchiveCache().withCache(cache)

LibSodiumJni.init(cache, archiveCache, logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object New extends ScalaCommand[NewOptions] {
Seq.empty,
Some(scalaParameters),
logger,
CoursierOptions().coursierCache(logger.coursierLogger("")),
CoursierOptions().coursierCache(logger),
None
) match {
case Right(value) => value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ abstract class PgpExternalCommand extends ExternalCommand {

val logger = options.global.logging.logger

val cache = options.coursier.coursierCache(logger.coursierLogger(""))
val cache = options.coursier.coursierCache(logger)
val retCode = tryRun(
cache,
remainingArgs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object PgpPush extends ScalaCommand[PgpPushOptions] {
sys.exit(1)
}

lazy val coursierCache = options.coursier.coursierCache(logger.coursierLogger(""))
lazy val coursierCache = options.coursier.coursierCache(logger)

for (key <- all) {
val path = os.Path(key, os.pwd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object PublishSetup extends ScalaCommand[PublishSetupOptions] {
): Unit = {
Publish.maybePrintLicensesAndExit(options.publishParams)

val coursierCache = options.coursier.coursierCache(logger.coursierLogger(""))
val coursierCache = options.coursier.coursierCache(logger)
val directories = Directories.directories

lazy val configDb = ConfigDbUtils.configDb.orExit(logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import caseapp.*
import com.github.plokhotnyuk.jsoniter_scala.core.*
import com.github.plokhotnyuk.jsoniter_scala.macros.*
import coursier.cache.{CacheLogger, CachePolicy, FileCache}
import coursier.util.Task

import scala.build.Logger
import scala.build.internals.EnvVar
import scala.cli.commands.tags
import scala.cli.config.Keys
import scala.cli.util.ConfigDbUtils
import scala.concurrent.duration.Duration

// format: off
Expand Down Expand Up @@ -39,24 +43,28 @@ final case class CoursierOptions(
private def validateChecksums =
coursierValidateChecksums.getOrElse(true)

def coursierCache(logger: CacheLogger) = {
var baseCache = FileCache().withLogger(logger)
def coursierCache(logger: Logger, cacheLogger: CacheLogger): FileCache[Task] = {
var baseCache = FileCache().withLogger(cacheLogger)
if (!validateChecksums)
baseCache = baseCache.withChecksums(Nil)
val ttlOpt = ttl.map(_.trim).filter(_.nonEmpty).map(Duration(_))
for (ttl0 <- ttlOpt)
baseCache = baseCache.withTtl(ttl0)
for (loc <- cache.filter(_.trim.nonEmpty))
baseCache = baseCache.withLocation(loc)
for (isOffline <- getOffline() if isOffline)
for (isOffline <- getOffline(logger) if isOffline)
baseCache = baseCache.withCachePolicies(Seq(CachePolicy.LocalOnly))

baseCache
}

def getOffline(): Option[Boolean] = offline
def coursierCache(logger: Logger, cacheLoggerPrefix: String = ""): FileCache[Task] =
coursierCache(logger, logger.coursierLogger(cacheLoggerPrefix))

def getOffline(logger: Logger): Option[Boolean] = offline
.orElse(EnvVar.Coursier.coursierMode.valueOpt.map(_ == "offline"))
.orElse(Option(System.getProperty("coursier.mode")).map(_ == "offline"))
.orElse(ConfigDbUtils.getConfigDbOpt(logger).flatMap(_.get(Keys.offline).toOption.flatten))
}

object CoursierOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ final case class SharedOptions(
strictBloopJsonCheck = strictBloopJsonCheck,
interactive = Some(() => interactive),
exclude = exclude.map(Positioned.commandLine),
offline = coursier.getOffline()
offline = coursier.getOffline(logger)
),
notForBloopOptions = bo.PostBuildOptions(
scalaJsLinkerOptions = linkerOptions(js),
Expand Down Expand Up @@ -603,11 +603,11 @@ final case class SharedOptions(
options => bloopRifleConfig(Some(options)),
threads.bloop,
strictBloopJsonCheckOrDefault,
coursier.getOffline().getOrElse(false)
coursier.getOffline(logger).getOrElse(false)
)
else SimpleScalaCompilerMaker("java", Nil)

lazy val coursierCache = coursier.coursierCache(logging.logger.coursierLogger(""))
lazy val coursierCache: FileCache[Task] = coursier.coursierCache(logging.logger)

def inputs(
args: Seq[String],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object LauncherCli {
def runAndExit(version: String, options: LauncherOptions, remainingArgs: Seq[String]): Nothing = {

val logger = LoggingOptions().logger
val cache = CoursierOptions().coursierCache(logger.coursierLogger(""))
val cache = CoursierOptions().coursierCache(logger)
val scalaVersion = options.cliScalaVersion.getOrElse(scalaCliScalaVersion(version))
val scalaParameters = ScalaParameters(scalaVersion)
val snapshotsRepo = Seq(Repositories.central, Repositories.sonatype("snapshots"))
Expand Down
2 changes: 1 addition & 1 deletion modules/cli/src/test/scala/cli/tests/LauncherCliTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class LauncherCliTest extends munit.FunSuite {

test("resolve nightly version".flaky) {
val logger = TestLogger()
val cache = CoursierOptions().coursierCache(logger.coursierLogger(""))
val cache = CoursierOptions().coursierCache(logger)
val scalaParameters = ScalaParameters(Constants.defaultScalaVersion)

val nightlyCliVersion = LauncherCli.resolveNightlyScalaCliVersion(cache, scalaParameters)
Expand Down
8 changes: 8 additions & 0 deletions modules/config/src/main/scala/scala/cli/config/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ object Keys {
description = "Globally enables power mode (the '--power' launcher flag)."
)

val offline = new Key.BooleanEntry(
prefix = Seq.empty,
name = "offline",
specificationLevel = SpecificationLevel.IMPLEMENTATION,
description = "Globally enables offline mode (the '--offline' flag)."
)

val suppressDirectivesInMultipleFilesWarning =
new Key.BooleanEntry(
prefix = Seq("suppress-warning"),
Expand Down Expand Up @@ -172,6 +179,7 @@ object Keys {
suppressDirectivesInMultipleFilesWarning,
suppressOutdatedDependenciessWarning,
suppressExperimentalFeatureWarning,
offline,
pgpPublicKey,
pgpSecretKey,
pgpSecretKeyPassword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,4 +560,45 @@ class ConfigTests extends ScalaCliSuite {
}
}

for {
offlineSetting <- Seq(true, false)
prefillCache <- if (offlineSetting) Seq(true, false) else Seq(false)
caption = s"offline mode: $offlineSetting, " +
(offlineSetting -> prefillCache match {
case (true, true) => "build should succeed when cache was pre-filled"
case (true, false) => "build should fail when cache is empty"
case _ => "dependencies should be downloaded as normal"
})
}
test(caption) {
TestInputs(
os.rel / "simple.sc" -> "println(dotty.tools.dotc.config.Properties.versionNumberString)"
)
.fromRoot { root =>
val configFile = os.rel / "config" / "config.json"
val localRepoPath = root / "local-repo"
val envs = Map(
"COURSIER_CACHE" -> localRepoPath.toString,
"SCALA_CLI_CONFIG" -> configFile.toString
)
os.proc(TestUtil.cli, "bloop", "exit", "--power").call(cwd = root)
os.proc(TestUtil.cli, "config", "offline", offlineSetting.toString)
.call(cwd = root, env = envs)
if (prefillCache) for {
artifactName <- Seq(
"scala3-compiler_3",
"scala3-staging_3",
"scala3-tasty-inspector_3",
"scala3-sbt-bridge"
)
artifact = s"org.scala-lang:$artifactName:${Constants.scala3Next}"
} os.proc(TestUtil.cs, "fetch", "--cache", localRepoPath, artifact).call(cwd = root)
val buildExpectedToSucceed = !offlineSetting || prefillCache
val r = os.proc(TestUtil.cli, "run", "simple.sc", "--with-compiler")
.call(cwd = root, env = envs, check = buildExpectedToSucceed)
if (buildExpectedToSucceed) expect(r.out.trim() == Constants.scala3Next)
else expect(r.exitCode == 1)
}
}

}
5 changes: 5 additions & 0 deletions website/docs/guides/power/offline.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ or
scala-cli -Dcoursier.mode=offline run Main.scala
```

Finally, it's possible to enable offline mode via global config:
```bash ignore
scala-cli --power config offline true
```

## Changes in behaviour

### Scala artifacts
Expand Down
1 change: 1 addition & 0 deletions website/docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Available keys:
- interactive Globally enables interactive mode (the '--interactive' flag).
- interactive-was-suggested Setting indicating if the global interactive mode was already suggested.
- java.properties Java properties for Scala CLI's execution.
- offline Globally enables offline mode (the '--offline' flag).
- pgp.public-key The PGP public key, used for signing.
- pgp.secret-key The PGP secret key, used for signing.
- pgp.secret-key-password The PGP secret key password, used for signing.
Expand Down
1 change: 1 addition & 0 deletions website/docs/reference/scala-command/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Available keys:
- interactive Globally enables interactive mode (the '--interactive' flag).
- interactive-was-suggested Setting indicating if the global interactive mode was already suggested.
- java.properties Java properties for Scala CLI's execution.
- offline Globally enables offline mode (the '--offline' flag).
- pgp.public-key The PGP public key, used for signing.
- pgp.secret-key The PGP secret key, used for signing.
- pgp.secret-key-password The PGP secret key password, used for signing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ Available keys:
- interactive Globally enables interactive mode (the '--interactive' flag).
- interactive-was-suggested Setting indicating if the global interactive mode was already suggested.
- java.properties Java properties for Scala CLI's execution.
- offline Globally enables offline mode (the '--offline' flag).
- pgp.public-key The PGP public key, used for signing.
- pgp.secret-key The PGP secret key, used for signing.
- pgp.secret-key-password The PGP secret key password, used for signing.
Expand Down

0 comments on commit 30e9e41

Please sign in to comment.