mirror of https://github.com/sbt/sbt.git
Merge branch 'develop' into fix/1469-junit-xml-fork-stacktrace
This commit is contained in:
commit
4436f061e4
|
|
@ -6,3 +6,5 @@ launcher-package/src/windows/sbt text eol=lf
|
|||
**/contraband-scala/**/* -diff merge=ours
|
||||
**/contraband-scala/**/* linguist-generated=true
|
||||
**/contraband-scala/**/* diff
|
||||
|
||||
*.contra linguist-language=graphql
|
||||
|
|
|
|||
41
build.sbt
41
build.sbt
|
|
@ -84,19 +84,21 @@ def commonSettings: Seq[Setting[?]] = Def.settings(
|
|||
Test / testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"),
|
||||
Test / testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "2"),
|
||||
compile / javacOptions ++= Seq("-Xlint", "-Xlint:-serial"),
|
||||
/*
|
||||
Compile / doc / scalacOptions ++= {
|
||||
import scala.sys.process._
|
||||
val devnull = ProcessLogger(_ => ())
|
||||
val tagOrSha = ("git describe --exact-match" #|| "git rev-parse HEAD").lineStream(devnull).head
|
||||
Seq(
|
||||
"-sourcepath",
|
||||
(LocalRootProject / baseDirectory).value.getAbsolutePath,
|
||||
"-doc-source-url",
|
||||
s"https://github.com/sbt/sbt/tree/$tagOrSha€{FILE_PATH}.scala"
|
||||
)
|
||||
if (Dependencies.sbtIoPath.isEmpty && Dependencies.sbtZincPath.isEmpty) {
|
||||
import scala.sys.process.*
|
||||
val devnull = ProcessLogger(_ => ())
|
||||
val tagOrSha =
|
||||
("git describe --exact-match" #|| "git rev-parse HEAD").lineStream(devnull).head
|
||||
Seq(
|
||||
"-source-links:github://sbt/sbt",
|
||||
"-revision",
|
||||
tagOrSha
|
||||
)
|
||||
} else {
|
||||
Nil
|
||||
}
|
||||
},
|
||||
*/
|
||||
Compile / javafmtOnCompile := scalafmtOnCompile.value,
|
||||
Test / javafmtOnCompile := (Test / scalafmtOnCompile).value,
|
||||
Compile / unmanagedSources / inputFileStamps :=
|
||||
|
|
@ -186,7 +188,6 @@ lazy val sbtRoot: Project = (project in file("."))
|
|||
},
|
||||
Utils.baseScalacOptions,
|
||||
Docs.settings,
|
||||
scalacOptions += "-Ymacro-expand:none", // for both sxr and doc
|
||||
Utils.publishPomSettings,
|
||||
otherRootSettings,
|
||||
Utils.noPublish,
|
||||
|
|
@ -742,8 +743,10 @@ lazy val mainProj = (project in file("main"))
|
|||
Test / testOptions += Tests
|
||||
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
|
||||
SettingKey[Boolean]("usePipelining") := false,
|
||||
// TODO: Fix doc
|
||||
Compile / doc / sources := Nil,
|
||||
libraryDependencies += {
|
||||
// https://github.com/scala/scala3/issues/18487
|
||||
"net.hamnaberg" %% "dataclass-annotation" % dataclassScalafixVersion % Provided
|
||||
},
|
||||
mimaSettings,
|
||||
mimaBinaryIssueFilters ++= Vector(
|
||||
// Moved to sbt-ivy module (Step 5 of sbt#7640)
|
||||
|
|
@ -782,8 +785,10 @@ lazy val sbtIvyProj = (project in file("sbt-ivy"))
|
|||
name := "sbt-ivy",
|
||||
sbtPlugin := true,
|
||||
pluginCrossBuild / sbtVersion := version.value,
|
||||
// TODO: Fix doc
|
||||
Compile / doc / sources := Nil,
|
||||
libraryDependencies += {
|
||||
// https://github.com/scala/scala3/issues/18487
|
||||
"net.hamnaberg" %% "dataclass-annotation" % dataclassScalafixVersion % Provided
|
||||
},
|
||||
mimaPreviousArtifacts := Set.empty, // new module, no previous artifacts
|
||||
)
|
||||
.configure(addSbtIO)
|
||||
|
|
@ -1019,10 +1024,6 @@ lazy val sbtwProj = (project in file("sbtw"))
|
|||
description := "Windows drop-in launcher for sbt (replaces sbt.bat)",
|
||||
scalaVersion := "3.8.3",
|
||||
crossPaths := false,
|
||||
Compile / scalafix / unmanagedSources := {
|
||||
// https://github.com/scalameta/scalameta/issues/4531
|
||||
(Compile / unmanagedSources).value.filterNot(_.getName == "Main.scala")
|
||||
},
|
||||
Compile / mainClass := Some("sbtw.Main"),
|
||||
libraryDependencies += "com.github.scopt" %% "scopt" % "4.1.0",
|
||||
libraryDependencies += scalaVerify % Test,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,8 @@ object Tests {
|
|||
new Group(name, tests, runPolicy, tags)
|
||||
}
|
||||
|
||||
override def hashCode(): Int = (name, tests, runPolicy, tags).##
|
||||
|
||||
override def equals(x$1: Any): Boolean = {
|
||||
this.eq(x$1.asInstanceOf[Object]) || (x$1.isInstanceOf[Group] && ({
|
||||
val Group$1: Group = x$1.asInstanceOf[Group]
|
||||
|
|
|
|||
|
|
@ -149,7 +149,9 @@ $HelpCommand <regular expression>
|
|||
remaining commands with the exception that the JVM is not shut down.
|
||||
|
||||
If 'dev' is specified, the current sbt artifacts from the boot directory
|
||||
(`~/.sbt/boot` by default) are deleted before restarting.
|
||||
(under the default global base; `sbt.global.base` selects that location) are deleted
|
||||
before restarting, and the compiler bridge secondary cache at `zinc/org.scala-sbt`
|
||||
(honoring `sbt.global.base` and `sbt.global.zinc`) is removed.
|
||||
This forces an update of sbt and Scala, which is useful when working with development
|
||||
versions of sbt.
|
||||
If 'full' is specified, the boot directory is wiped out before restarting.
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ class NetworkClient(
|
|||
def success(message: => String): Unit = ()
|
||||
def log(level: Level.Value, message: => String): Unit = console.appendLog(level, message)
|
||||
}
|
||||
private val interactive = arguments.commandArguments.isEmpty
|
||||
|
||||
private[sbt] def connectOrStartServerAndConnect(
|
||||
promptCompleteUsers: Boolean,
|
||||
|
|
@ -712,8 +713,19 @@ class NetworkClient(
|
|||
case (`clientJob`, Some(json)) =>
|
||||
import sbt.internal.worker.codec.JsonProtocol.given
|
||||
Converter.fromJson[ClientJobParams](json) match {
|
||||
case Success(params) => clientSideRun(params).get; Vector.empty
|
||||
case Failure(_) => Vector.empty
|
||||
case Success(params) =>
|
||||
clientSideRun(params) match
|
||||
case Success(_) =>
|
||||
if interactive then console.success("ok")
|
||||
else ()
|
||||
Vector.empty
|
||||
case Failure(e) =>
|
||||
if interactive then
|
||||
Vector(
|
||||
(Level.Error, e.getMessage)
|
||||
)
|
||||
else throw e
|
||||
case Failure(_) => Vector.empty
|
||||
}
|
||||
case (`Shutdown`, Some(_)) => Vector.empty
|
||||
case (msg, _) if msg.startsWith("build/") => Vector.empty
|
||||
|
|
@ -921,9 +933,8 @@ class NetworkClient(
|
|||
withSignalHandler(contHandler, Signals.CONT) {
|
||||
interactiveThread.set(Thread.currentThread)
|
||||
val cleaned = arguments.commandArguments
|
||||
val userCommands = cleaned.takeWhile(_ != TerminateAction)
|
||||
val interactive = cleaned.isEmpty
|
||||
val exit = cleaned.nonEmpty && userCommands.isEmpty
|
||||
val userCommands = arguments.commandArguments.takeWhile(_ != TerminateAction)
|
||||
val exit = arguments.commandArguments.nonEmpty && userCommands.isEmpty
|
||||
attachUUID.set(sendJson(attach, s"""{"interactive": $interactive}"""))
|
||||
val handler: () => Unit = () => {
|
||||
def exitAbruptly() = {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ object ServerHandler {
|
|||
|
||||
lazy val fallback: ServerHandler = ServerHandler({ handler =>
|
||||
ServerIntent(
|
||||
onRequest = { case x => handler.log.debug(s"Unhandled request received: ${x.method}: $x") },
|
||||
onRequest = { case x =>
|
||||
handler.log.debug(s"Unhandled request received: ${x.method}: $x")
|
||||
handler.jsonRpcRespondError(Some(x.id), -32601, s"Unknown method: ${x.method}")
|
||||
},
|
||||
onResponse = { case x => handler.log.debug(s"Unhandled response received") },
|
||||
onNotification = { case x =>
|
||||
handler.log.debug(s"Unhandled notification received: ${x.method}: $x")
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ object Cross {
|
|||
|
||||
private def switchParser(state: State): Parser[Switch] = {
|
||||
import DefaultParsers.*
|
||||
def versionAndCommand(spacePresent: Boolean) = {
|
||||
def versionAndCommand(commandName: String)(spacePresent: Boolean) = {
|
||||
val x = Project.extract(state)
|
||||
import x.*
|
||||
val knownVersions = crossVersions(x, currentRef)
|
||||
|
|
@ -56,7 +56,7 @@ object Cross {
|
|||
ScalaHomeVersion(new File(home), Some(v).filterNot(_.isEmpty), force)
|
||||
}
|
||||
}
|
||||
val spacedVersion = if (spacePresent) version else version & spacedFirst(SwitchCommand)
|
||||
val spacedVersion = if (spacePresent) version else version & spacedFirst(commandName)
|
||||
val verboseOpt = Parser.opt(token(Space ~> "-v"))
|
||||
// Accept valid commands, or project/command patterns that may reference projects
|
||||
// not yet available after version switch (fixes #7574)
|
||||
|
|
@ -74,19 +74,24 @@ object Cross {
|
|||
switch1 | switch2
|
||||
}
|
||||
|
||||
token(SwitchCommand ~> OptSpace) flatMap { sp =>
|
||||
versionAndCommand(sp.nonEmpty)
|
||||
}
|
||||
def parse(commandName: String) =
|
||||
token(commandName ~> OptSpace) flatMap { sp =>
|
||||
versionAndCommand(commandName)(sp.nonEmpty)
|
||||
}
|
||||
parse(SwitchCommand) | parse(SwitchAlias)
|
||||
}
|
||||
|
||||
private case class CrossArgs(command: String, verbose: Boolean)
|
||||
|
||||
private def crossParser(state: State): Parser[CrossArgs] =
|
||||
token(CrossCommand <~ OptSpace) flatMap { _ =>
|
||||
(token(Parser.opt("-v" <~ Space)) ~ token(matched(state.combinedParser))).map {
|
||||
(verbose, command) => CrossArgs(command, verbose.isDefined)
|
||||
private def crossParser(state: State): Parser[CrossArgs] = {
|
||||
def parse(commandName: String) =
|
||||
token(commandName <~ OptSpace) flatMap { _ =>
|
||||
(token(Parser.opt("-v" <~ Space)) ~ token(matched(state.combinedParser))).map {
|
||||
(verbose, command) => CrossArgs(command, verbose.isDefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
parse(CrossCommand) | parse(CrossAlias)
|
||||
}
|
||||
|
||||
private def crossRestoreSessionParser: Parser[String] = token(CrossRestoreSessionCommand)
|
||||
|
||||
|
|
|
|||
|
|
@ -4289,7 +4289,9 @@ object Classpaths {
|
|||
configuration.allRepositories,
|
||||
)
|
||||
val processed = configuration.process(pomXml)
|
||||
scala.xml.XML.save(file.getAbsolutePath, processed, "UTF-8", xmlDecl = true)
|
||||
val printer = new scala.xml.PrettyPrinter(1000, 4)
|
||||
val formatted = scala.xml.XML.loadString(printer.format(processed))
|
||||
scala.xml.XML.save(file.getAbsolutePath, formatted, "UTF-8", xmlDecl = true)
|
||||
log.info("Wrote " + file.getAbsolutePath)
|
||||
file
|
||||
})
|
||||
|
|
|
|||
|
|
@ -479,6 +479,8 @@ object Keys {
|
|||
val bspBuildTargetResourcesItem = taskKey[ResourcesItem]("").withRank(DTask)
|
||||
val bspBuildTargetDependencySources = inputKey[Unit]("").withRank(DTask)
|
||||
val bspBuildTargetDependencySourcesItem = taskKey[DependencySourcesItem]("").withRank(DTask)
|
||||
val bspBuildTargetDependencyModules = inputKey[Unit]("").withRank(DTask)
|
||||
val bspBuildTargetDependencyModulesItem = taskKey[DependencyModulesItem]("").withRank(DTask)
|
||||
val bspBuildTargetOutputPaths = inputKey[Unit]("").withRank(DTask)
|
||||
val bspBuildTargetOutputPathsItem = taskKey[OutputPathsItem]("").withRank(DTask)
|
||||
val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask)
|
||||
|
|
|
|||
|
|
@ -1144,12 +1144,20 @@ object BuiltinCommands {
|
|||
.getOpt(Keys.minForcegcInterval)
|
||||
.getOrElse(GCUtil.defaultMinForcegcInterval)
|
||||
val exec: Exec = getExec(s1, minGCInterval)
|
||||
val isInteractive = exec.source match {
|
||||
case Some(src) if src.channelName.startsWith("network") =>
|
||||
exchange.channelForName(src.channelName) match {
|
||||
case Some(nc: NetworkChannel) => nc.isInteractive
|
||||
case _ => true
|
||||
}
|
||||
case _ => true
|
||||
}
|
||||
val newState = s1
|
||||
.copy(
|
||||
onFailure = Some(Exec(Shell, None)),
|
||||
remainingCommands = exec +: Exec(Shell, None) +: s1.remainingCommands
|
||||
)
|
||||
.setInteractive(true)
|
||||
.setInteractive(isInteractive)
|
||||
val res =
|
||||
if (exec.commandLine.trim.isEmpty) newState
|
||||
else newState.clearGlobalLog
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import sbt.internal.util.{
|
|||
Terminal as ITerminal
|
||||
}
|
||||
import sbt.io.{ IO, Using }
|
||||
import sbt.io.syntax.*
|
||||
import sbt.librarymanagement.SbtArtifacts
|
||||
import sbt.protocol.*
|
||||
import sbt.util.{ Logger, LoggerContext }
|
||||
|
||||
|
|
@ -75,6 +77,10 @@ private[sbt] object MainLoop:
|
|||
case e: RebootCurrent =>
|
||||
deleteLastLog(logBacking)
|
||||
deleteCurrentArtifacts(state)
|
||||
deleteZincBridgeSecondaryCache(
|
||||
state.log,
|
||||
BuildPaths.getZincDirectory(state, BuildPaths.getGlobalBase(state)),
|
||||
)
|
||||
throw new xsbti.FullReload(e.arguments.toArray, false)
|
||||
case NonFatal(e) =>
|
||||
System.err.println(
|
||||
|
|
@ -89,7 +95,6 @@ private[sbt] object MainLoop:
|
|||
|
||||
/** Deletes the current sbt artifacts from boot. */
|
||||
private[sbt] def deleteCurrentArtifacts(state: State): Unit = {
|
||||
import sbt.io.syntax.*
|
||||
val provider = state.configuration.provider
|
||||
val appId = provider.id
|
||||
// If we can obtain boot directory more accurately it'd be better.
|
||||
|
|
@ -109,6 +114,13 @@ private[sbt] object MainLoop:
|
|||
}
|
||||
}
|
||||
|
||||
/** Removes the Zinc compiler bridge secondary cache (`zincDir/org.scala-sbt`). */
|
||||
private[sbt] def deleteZincBridgeSecondaryCache(log: Logger, zincDir: File): Unit =
|
||||
val bridgeCache = zincDir / SbtArtifacts.Organization
|
||||
if bridgeCache.exists() then
|
||||
log.info(s"deleting $bridgeCache")
|
||||
IO.delete(bridgeCache)
|
||||
|
||||
/** Runs the next sequence of commands with global logging in place. */
|
||||
def runWithNewLog(state: State, logBacking: GlobalLogBacking): RunNext =
|
||||
Using.fileWriter(append = true)(logBacking.file) { writer =>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import sbt.internal.util.complete.Parser
|
|||
import sbt.internal.util.complete.Parser.{ failure, seq, success }
|
||||
import sbt.internal.util.*
|
||||
import sbt.internal.client.NetworkClient
|
||||
import sbt.internal.worker.ClientJobParams
|
||||
import sbt.std.Transform.DummyTaskMap
|
||||
import sbt.util.{ Logger, Show }
|
||||
import scala.annotation.tailrec
|
||||
|
|
@ -87,16 +88,18 @@ object Aggregation {
|
|||
import complete.*
|
||||
val log = state.log
|
||||
val extracted = Project.extract(state)
|
||||
val success = results match
|
||||
case Result.Value(_) => true
|
||||
case Result.Inc(_) => false
|
||||
// omit success printing for client-side run
|
||||
val (success, jobParams) = results match
|
||||
case Result.Value(Seq(KeyValue(_, p: ClientJobParams))) => (true, true)
|
||||
case Result.Value(_) => (true, false)
|
||||
case Result.Inc(_) => (false, false)
|
||||
val isPaused = currentChannel(state) match
|
||||
case Some(channel) => channel.isPaused
|
||||
case None => false
|
||||
results.toEither.foreach { r =>
|
||||
if show.taskValues then printSettings(r, show.print) else ()
|
||||
}
|
||||
if !isPaused && show.success && !state.get(suppressShow).getOrElse(false) then
|
||||
if !isPaused && show.success && !state.get(suppressShow).getOrElse(false) && !jobParams then
|
||||
printSuccess(start, stop, extracted, success, cacheSummary, log)
|
||||
else ()
|
||||
|
||||
|
|
|
|||
|
|
@ -226,6 +226,13 @@ private[sbt] object Clean {
|
|||
case d: DiskActionCacheStore => d.clear()
|
||||
case _ => ()
|
||||
IO.delete(outputDirectory.toFile())
|
||||
IO.delete(
|
||||
s.configuration
|
||||
.provider()
|
||||
.scalaProvider()
|
||||
.launcher()
|
||||
.bootDirectory()
|
||||
)
|
||||
s
|
||||
Command.command(CleanFull, h)(expunge andThen clearCachesFun)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,15 +331,19 @@ defaults
|
|||
Nil
|
||||
|
||||
val CrossCommand = "+"
|
||||
val CrossAlias = "cross"
|
||||
val CrossRestoreSessionCommand = "+-"
|
||||
val SwitchCommand = "++"
|
||||
val SwitchAlias = "switch"
|
||||
|
||||
def crossHelp: Help = Help.more(CrossCommand, CrossDetailed)
|
||||
def crossHelp: Help =
|
||||
Help.more(CrossCommand, CrossDetailed) ++ Help.more(CrossAlias, CrossDetailed)
|
||||
def crossRestoreSessionHelp = Help.more(CrossRestoreSessionCommand, CrossRestoreSessionDetailed)
|
||||
def switchHelp: Help = Help.more(SwitchCommand, SwitchDetailed)
|
||||
def switchHelp: Help =
|
||||
Help.more(SwitchCommand, SwitchDetailed) ++ Help.more(SwitchAlias, SwitchDetailed)
|
||||
|
||||
def CrossDetailed =
|
||||
s"""$CrossCommand [-v] <command>
|
||||
s"""$CrossCommand (or $CrossAlias) [-v] <command>
|
||||
Runs <command> for each Scala version specified for cross-building.
|
||||
|
||||
For each string in `crossScalaVersions` in each project project, this command sets
|
||||
|
|
@ -359,7 +363,7 @@ defaults
|
|||
"""
|
||||
|
||||
def SwitchDetailed =
|
||||
s"""$SwitchCommand <scala-version>[!] [-v] [<command>]
|
||||
s"""$SwitchCommand (or $SwitchAlias) <scala-version>[!] [-v] [<command>]
|
||||
Changes the Scala version and runs a command.
|
||||
|
||||
<scala-version> may be an actual Scala version such as 3.1.3, or a Semantic Version selector
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ object LintUnused {
|
|||
keyName => includes(keyName)
|
||||
},
|
||||
lintExcludeFilter := {
|
||||
val excludedPrefixes = List("release", "sonatype", "watch", "whitesource")
|
||||
val excludedPrefixes = List("release", "sonatype", "watch")
|
||||
val excludes = excludeLintKeys.value.map(_.scopedKey.key.label)
|
||||
keyName => excludes(keyName) || excludedPrefixes.exists(keyName.startsWith(_))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ private[sbt] object PomGenerator:
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
{makeModuleID(crossMid)}
|
||||
{info.map(i => <name>{i.nameFormal}</name>).getOrElse(NodeSeq.Empty)}
|
||||
{info.map(makeDescription).getOrElse(NodeSeq.Empty)}
|
||||
{info.map(makeHomePage).getOrElse(NodeSeq.Empty)}
|
||||
{info.map(makeStartYear).getOrElse(NodeSeq.Empty)}
|
||||
{info.map(makeOrganization).getOrElse(NodeSeq.Empty)}
|
||||
{info.map(makeScmInfo).getOrElse(NodeSeq.Empty)}
|
||||
|
|
@ -96,6 +98,16 @@ private[sbt] object PomGenerator:
|
|||
private val IgnoreTypes: Set[String] =
|
||||
Set(Artifact.SourceType, Artifact.DocType, Artifact.PomType)
|
||||
|
||||
private def makeDescription(info: ModuleInfo): NodeSeq =
|
||||
if info.description != null && info.description.nonEmpty then
|
||||
<description>{info.description}</description>
|
||||
else NodeSeq.Empty
|
||||
|
||||
private def makeHomePage(info: ModuleInfo): NodeSeq =
|
||||
info.homepage match
|
||||
case Some(h) => <url>{h}</url>
|
||||
case _ => NodeSeq.Empty
|
||||
|
||||
private def makeStartYear(info: ModuleInfo): NodeSeq =
|
||||
info.startYear match
|
||||
case Some(y) => <inceptionYear>{y}</inceptionYear>
|
||||
|
|
|
|||
|
|
@ -166,6 +166,21 @@ object BuildServerProtocol {
|
|||
state.value.respondEvent(result)
|
||||
}.evaluated,
|
||||
bspBuildTargetDependencySources / aggregate := false,
|
||||
bspBuildTargetDependencyModules := bspInputTask { (workspace, filter) =>
|
||||
val items = bspBuildTargetDependencyModulesItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val buildItems = workspace.builds
|
||||
.map { case (targetId, loadedBuildUnit) =>
|
||||
val projRef = ProjectRef(loadedBuildUnit.unit.uri, loadedBuildUnit.root)
|
||||
(projRef / updateSbtClassifiers).map(getDependencyModulesItem(targetId, _))
|
||||
}
|
||||
.toSeq
|
||||
.join
|
||||
.value
|
||||
val result = DependencyModulesResult((successfulItems ++ buildItems).toVector)
|
||||
state.value.respondEvent(result)
|
||||
}.evaluated,
|
||||
bspBuildTargetDependencyModules / aggregate := false,
|
||||
bspBuildTargetCompile := bspInputTask { (workspace, filter) =>
|
||||
val s = state.value
|
||||
workspace.warnIfBuildsNonEmpty(Method.Compile, s.log)
|
||||
|
|
@ -306,6 +321,7 @@ object BuildServerProtocol {
|
|||
ResourcesItem(id, uris)
|
||||
},
|
||||
bspBuildTargetDependencySourcesItem := dependencySourcesItemTask.value,
|
||||
bspBuildTargetDependencyModulesItem := dependencyModulesItemTask.value,
|
||||
bspBuildTargetOutputPathsItem := {
|
||||
val id = bspTargetIdentifier.value
|
||||
OutputPathsItem(id, Vector(OutputPathItem(target.value.toURI, OutputPathItemKind.Directory)))
|
||||
|
|
@ -374,6 +390,7 @@ object BuildServerProtocol {
|
|||
final val Resources = "buildTarget/resources"
|
||||
final val OutputPaths = "buildTarget/outputPaths"
|
||||
final val DependencySources = "buildTarget/dependencySources"
|
||||
final val DependencyModules = "buildTarget/dependencyModules"
|
||||
final val Compile = "buildTarget/compile"
|
||||
final val Test = "buildTarget/test"
|
||||
final val Run = "buildTarget/run"
|
||||
|
|
@ -439,6 +456,12 @@ object BuildServerProtocol {
|
|||
val command = Keys.bspBuildTargetDependencySources.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.DependencyModules =>
|
||||
val param = Converter.fromJson[DependencyModulesParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
val command = Keys.bspBuildTargetDependencyModules.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.Compile =>
|
||||
val param = Converter.fromJson[CompileParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
|
|
@ -856,6 +879,13 @@ object BuildServerProtocol {
|
|||
)
|
||||
}
|
||||
|
||||
private def dependencyModulesItemTask: Def.Initialize[Task[DependencyModulesItem]] = Def.task {
|
||||
getDependencyModulesItem(
|
||||
Keys.bspTargetIdentifier.value,
|
||||
Keys.updateClassifiers.value
|
||||
)
|
||||
}
|
||||
|
||||
private def getDependencySourceItem(
|
||||
targetId: BuildTargetIdentifier,
|
||||
updateReport: UpdateReport
|
||||
|
|
@ -869,6 +899,25 @@ object BuildServerProtocol {
|
|||
DependencySourcesItem(targetId, sources.toVector.distinct)
|
||||
}
|
||||
|
||||
private def getDependencyModulesItem(
|
||||
targetId: BuildTargetIdentifier,
|
||||
updateReport: UpdateReport
|
||||
): DependencyModulesItem = {
|
||||
val modules = for {
|
||||
configuration <- updateReport.configurations.view
|
||||
module <- configuration.modules.view
|
||||
} yield {
|
||||
val moduleId = module.module
|
||||
DependencyModule(
|
||||
name = s"${moduleId.organization}:${moduleId.name}",
|
||||
version = moduleId.revision,
|
||||
dataKind = None,
|
||||
data = None,
|
||||
)
|
||||
}
|
||||
DependencyModulesItem(targetId, modules.toVector.distinct)
|
||||
}
|
||||
|
||||
private def bspCompileState: Initialize[BuildServerProtocol.BspCompileState] = Def.setting {
|
||||
new BuildServerProtocol.BspCompileState()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
|
||||
import sbt.internal.util.{ ConsoleOut, GlobalLogging, MainAppender }
|
||||
import sbt.io.IO
|
||||
import sbt.io.syntax.*
|
||||
import sbt.librarymanagement.SbtArtifacts
|
||||
import sbt.util.Logger
|
||||
|
||||
object MainLoopZincCacheTest extends verify.BasicTestSuite:
|
||||
|
||||
private def withTestLog[A](f: Logger => A): A =
|
||||
val logFile = File.createTempFile("sbt-mlz", ".log")
|
||||
try
|
||||
val gl = GlobalLogging.initial(
|
||||
MainAppender.globalDefault(ConsoleOut.globalProxy),
|
||||
logFile,
|
||||
ConsoleOut.globalProxy
|
||||
)
|
||||
f(gl.full)
|
||||
finally IO.delete(logFile)
|
||||
|
||||
test("deleteZincBridgeSecondaryCache removes org.scala-sbt under zincDir"):
|
||||
IO.withTemporaryDirectory: tmp =>
|
||||
val zincRoot = tmp / "zinc"
|
||||
val bridge = zincRoot / SbtArtifacts.Organization
|
||||
IO.write(bridge / "marker.txt", "cached")
|
||||
withTestLog: log =>
|
||||
MainLoop.deleteZincBridgeSecondaryCache(log, zincRoot)
|
||||
assert(!bridge.exists(), s"expected $bridge deleted")
|
||||
|
||||
test("deleteZincBridgeSecondaryCache is a no-op when org.scala-sbt is absent"):
|
||||
IO.withTemporaryDirectory: tmp =>
|
||||
val zincRoot = tmp / "zinc"
|
||||
IO.createDirectory(zincRoot)
|
||||
withTestLog: log =>
|
||||
MainLoop.deleteZincBridgeSecondaryCache(log, zincRoot)
|
||||
assert(zincRoot.exists())
|
||||
|
||||
end MainLoopZincCacheTest
|
||||
|
|
@ -36,8 +36,6 @@ object Dependencies {
|
|||
}
|
||||
|
||||
lazy val sbtIoPath = getSbtModulePath("sbtio.path")
|
||||
lazy val sbtUtilPath = getSbtModulePath("sbtutil.path")
|
||||
lazy val sbtLmPath = getSbtModulePath("sbtlm.path")
|
||||
lazy val sbtZincPath = getSbtModulePath("sbtzinc.path")
|
||||
|
||||
def addSbtModule(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/**
|
||||
* @param name Module name
|
||||
* @param version Module version
|
||||
* @param dataKind Kind of data to expect in the `data` field.
|
||||
* @param data Language-specific metadata about this module.
|
||||
*/
|
||||
final class DependencyModule private (
|
||||
val name: String,
|
||||
val version: String,
|
||||
val dataKind: Option[String],
|
||||
val data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: DependencyModule => (this.name == x.name) && (this.version == x.version) && (this.dataKind == x.dataKind) && (this.data == x.data)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.DependencyModule".##) + name.##) + version.##) + dataKind.##) + data.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"DependencyModule(" + name + ", " + version + ", " + dataKind + ", " + data + ")"
|
||||
}
|
||||
private def copy(name: String = name, version: String = version, dataKind: Option[String] = dataKind, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = data): DependencyModule = {
|
||||
new DependencyModule(name, version, dataKind, data)
|
||||
}
|
||||
def withName(name: String): DependencyModule = {
|
||||
copy(name = name)
|
||||
}
|
||||
def withVersion(version: String): DependencyModule = {
|
||||
copy(version = version)
|
||||
}
|
||||
def withDataKind(dataKind: Option[String]): DependencyModule = {
|
||||
copy(dataKind = dataKind)
|
||||
}
|
||||
def withDataKind(dataKind: String): DependencyModule = {
|
||||
copy(dataKind = Option(dataKind))
|
||||
}
|
||||
def withData(data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): DependencyModule = {
|
||||
copy(data = data)
|
||||
}
|
||||
def withData(data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): DependencyModule = {
|
||||
copy(data = Option(data))
|
||||
}
|
||||
}
|
||||
object DependencyModule {
|
||||
|
||||
def apply(name: String, version: String, dataKind: Option[String], data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): DependencyModule = new DependencyModule(name, version, dataKind, data)
|
||||
def apply(name: String, version: String, dataKind: String, data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): DependencyModule = new DependencyModule(name, version, Option(dataKind), Option(data))
|
||||
}
|
||||
40
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesItem.scala
generated
Normal file
40
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesItem.scala
generated
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
final class DependencyModulesItem private (
|
||||
val target: Option[sbt.internal.bsp.BuildTargetIdentifier],
|
||||
val modules: Vector[sbt.internal.bsp.DependencyModule]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: DependencyModulesItem => (this.target == x.target) && (this.modules == x.modules)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.bsp.DependencyModulesItem".##) + target.##) + modules.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"DependencyModulesItem(" + target + ", " + modules + ")"
|
||||
}
|
||||
private def copy(target: Option[sbt.internal.bsp.BuildTargetIdentifier] = target, modules: Vector[sbt.internal.bsp.DependencyModule] = modules): DependencyModulesItem = {
|
||||
new DependencyModulesItem(target, modules)
|
||||
}
|
||||
def withTarget(target: Option[sbt.internal.bsp.BuildTargetIdentifier]): DependencyModulesItem = {
|
||||
copy(target = target)
|
||||
}
|
||||
def withTarget(target: sbt.internal.bsp.BuildTargetIdentifier): DependencyModulesItem = {
|
||||
copy(target = Option(target))
|
||||
}
|
||||
def withModules(modules: Vector[sbt.internal.bsp.DependencyModule]): DependencyModulesItem = {
|
||||
copy(modules = modules)
|
||||
}
|
||||
}
|
||||
object DependencyModulesItem {
|
||||
|
||||
def apply(target: Option[sbt.internal.bsp.BuildTargetIdentifier], modules: Vector[sbt.internal.bsp.DependencyModule]): DependencyModulesItem = new DependencyModulesItem(target, modules)
|
||||
def apply(target: sbt.internal.bsp.BuildTargetIdentifier, modules: Vector[sbt.internal.bsp.DependencyModule]): DependencyModulesItem = new DependencyModulesItem(Option(target), modules)
|
||||
}
|
||||
33
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesParams.scala
generated
Normal file
33
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesParams.scala
generated
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/** Dependency Modules Request */
|
||||
final class DependencyModulesParams private (
|
||||
val targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: DependencyModulesParams => (this.targets == x.targets)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + "sbt.internal.bsp.DependencyModulesParams".##) + targets.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"DependencyModulesParams(" + targets + ")"
|
||||
}
|
||||
private def copy(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): DependencyModulesParams = {
|
||||
new DependencyModulesParams(targets)
|
||||
}
|
||||
def withTargets(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): DependencyModulesParams = {
|
||||
copy(targets = targets)
|
||||
}
|
||||
}
|
||||
object DependencyModulesParams {
|
||||
|
||||
def apply(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): DependencyModulesParams = new DependencyModulesParams(targets)
|
||||
}
|
||||
33
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesResult.scala
generated
Normal file
33
protocol/src/main/contraband-scala/sbt/internal/bsp/DependencyModulesResult.scala
generated
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/** Dependency Modules Result */
|
||||
final class DependencyModulesResult private (
|
||||
val items: Vector[sbt.internal.bsp.DependencyModulesItem]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: DependencyModulesResult => (this.items == x.items)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + "sbt.internal.bsp.DependencyModulesResult".##) + items.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"DependencyModulesResult(" + items + ")"
|
||||
}
|
||||
private def copy(items: Vector[sbt.internal.bsp.DependencyModulesItem]): DependencyModulesResult = {
|
||||
new DependencyModulesResult(items)
|
||||
}
|
||||
def withItems(items: Vector[sbt.internal.bsp.DependencyModulesItem]): DependencyModulesResult = {
|
||||
copy(items = items)
|
||||
}
|
||||
}
|
||||
object DependencyModulesResult {
|
||||
|
||||
def apply(items: Vector[sbt.internal.bsp.DependencyModulesItem]): DependencyModulesResult = new DependencyModulesResult(items)
|
||||
}
|
||||
33
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModuleFormats.scala
generated
Normal file
33
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModuleFormats.scala
generated
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait DependencyModuleFormats { self: sbt.internal.util.codec.JValueFormats & sjsonnew.BasicJsonProtocol =>
|
||||
given DependencyModuleFormat: JsonFormat[sbt.internal.bsp.DependencyModule] = new JsonFormat[sbt.internal.bsp.DependencyModule] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.DependencyModule = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val name = unbuilder.readField[String]("name")
|
||||
val version = unbuilder.readField[String]("version")
|
||||
val dataKind = unbuilder.readField[Option[String]]("dataKind")
|
||||
val data = unbuilder.readField[Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]]("data")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.DependencyModule(name, version, dataKind, data)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.DependencyModule, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("name", obj.name)
|
||||
builder.addField("version", obj.version)
|
||||
builder.addField("dataKind", obj.dataKind)
|
||||
builder.addField("data", obj.data)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesItemFormats.scala
generated
Normal file
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesItemFormats.scala
generated
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait DependencyModulesItemFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats & sjsonnew.BasicJsonProtocol & sbt.internal.bsp.codec.DependencyModuleFormats & sbt.internal.util.codec.JValueFormats =>
|
||||
given DependencyModulesItemFormat: JsonFormat[sbt.internal.bsp.DependencyModulesItem] = new JsonFormat[sbt.internal.bsp.DependencyModulesItem] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.DependencyModulesItem = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val target = unbuilder.readField[Option[sbt.internal.bsp.BuildTargetIdentifier]]("target")
|
||||
val modules = unbuilder.readField[Vector[sbt.internal.bsp.DependencyModule]]("modules")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.DependencyModulesItem(target, modules)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.DependencyModulesItem, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("target", obj.target)
|
||||
builder.addField("modules", obj.modules)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesParamsFormats.scala
generated
Normal file
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesParamsFormats.scala
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait DependencyModulesParamsFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats & sjsonnew.BasicJsonProtocol =>
|
||||
given DependencyModulesParamsFormat: JsonFormat[sbt.internal.bsp.DependencyModulesParams] = new JsonFormat[sbt.internal.bsp.DependencyModulesParams] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.DependencyModulesParams = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val targets = unbuilder.readField[Vector[sbt.internal.bsp.BuildTargetIdentifier]]("targets")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.DependencyModulesParams(targets)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.DependencyModulesParams, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("targets", obj.targets)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesResultFormats.scala
generated
Normal file
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DependencyModulesResultFormats.scala
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait DependencyModulesResultFormats { self: sbt.internal.bsp.codec.DependencyModulesItemFormats & sbt.internal.bsp.codec.BuildTargetIdentifierFormats & sjsonnew.BasicJsonProtocol & sbt.internal.bsp.codec.DependencyModuleFormats & sbt.internal.util.codec.JValueFormats =>
|
||||
given DependencyModulesResultFormat: JsonFormat[sbt.internal.bsp.DependencyModulesResult] = new JsonFormat[sbt.internal.bsp.DependencyModulesResult] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.DependencyModulesResult = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val items = unbuilder.readField[Vector[sbt.internal.bsp.DependencyModulesItem]]("items")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.DependencyModulesResult(items)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.DependencyModulesResult, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("items", obj.items)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,10 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
|||
with sbt.internal.bsp.codec.DependencySourcesParamsFormats
|
||||
with sbt.internal.bsp.codec.DependencySourcesItemFormats
|
||||
with sbt.internal.bsp.codec.DependencySourcesResultFormats
|
||||
with sbt.internal.bsp.codec.DependencyModulesParamsFormats
|
||||
with sbt.internal.bsp.codec.DependencyModuleFormats
|
||||
with sbt.internal.bsp.codec.DependencyModulesItemFormats
|
||||
with sbt.internal.bsp.codec.DependencyModulesResultFormats
|
||||
with sbt.internal.bsp.codec.TaskStartParamsFormats
|
||||
with sbt.internal.bsp.codec.TaskProgressParamsFormats
|
||||
with sbt.internal.bsp.codec.TaskFinishParamsFormats
|
||||
|
|
|
|||
|
|
@ -409,6 +409,35 @@ type DependencySourcesItem {
|
|||
sources: [java.net.URI]
|
||||
}
|
||||
|
||||
## Dependency Modules Request
|
||||
type DependencyModulesParams {
|
||||
targets: [sbt.internal.bsp.BuildTargetIdentifier]
|
||||
}
|
||||
|
||||
## Dependency Modules Result
|
||||
type DependencyModulesResult {
|
||||
items: [sbt.internal.bsp.DependencyModulesItem]
|
||||
}
|
||||
|
||||
type DependencyModulesItem {
|
||||
target: sbt.internal.bsp.BuildTargetIdentifier
|
||||
modules: [sbt.internal.bsp.DependencyModule]
|
||||
}
|
||||
|
||||
type DependencyModule {
|
||||
## Module name
|
||||
name: String!
|
||||
|
||||
## Module version
|
||||
version: String!
|
||||
|
||||
## Kind of data to expect in the `data` field.
|
||||
dataKind: String
|
||||
|
||||
## Language-specific metadata about this module.
|
||||
data: sjsonnew.shaded.scalajson.ast.unsafe.JValue
|
||||
}
|
||||
|
||||
## Task Notifications
|
||||
|
||||
type TaskStartParams {
|
||||
|
|
|
|||
4
sbt
4
sbt
|
|
@ -142,7 +142,7 @@ download_url () {
|
|||
local jar="$2"
|
||||
mkdir -p $(dirname "$jar") && {
|
||||
if command -v curl > /dev/null; then
|
||||
curl --silent -L "$url" --output "$jar"
|
||||
curl --fail --silent -L "$url" --output "$jar"
|
||||
elif command -v wget > /dev/null; then
|
||||
wget --quiet -O "$jar" "$url"
|
||||
else
|
||||
|
|
@ -362,7 +362,7 @@ addSbtScriptProperty () {
|
|||
}
|
||||
|
||||
addJdkWorkaround () {
|
||||
local is_25="$(expr $java_version "=" 25)"
|
||||
local is_25="$(expr $java_version ">=" 25)"
|
||||
if [[ "$hide_jdk_warnings" == "0" ]]; then
|
||||
:
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration/>
|
||||
|
|
@ -15,7 +15,7 @@ def completionsParser(state: State) =
|
|||
{
|
||||
val notQuoted = (NotQuoted ~ any.*) map { case (nq, s) => (nq +: s).mkString }
|
||||
val quotedOrUnquotedSingleArgument = Space ~> (StringVerbatim | StringEscapable | notQuoted)
|
||||
applyEffect(token(quotedOrUnquotedSingleArgument ?? "" examples ("", " ")))(runCompletions(state))
|
||||
applyEffect(token((quotedOrUnquotedSingleArgument ?? "").examples("", " ")))(runCompletions(state))
|
||||
}
|
||||
def runCompletions(state: State)(input: String): State = {
|
||||
val xs = Parser.completions(state.combinedParser, input, 9).get map {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ lazy val bar = taskKey[Unit]("Runs the bar task")
|
|||
def makeFoo(config: Configuration): Setting[?] =
|
||||
config / foo := IO.write(file(s"${config.name}-foo"), "foo")
|
||||
|
||||
lazy val PerformanceTest = (config("pt") extend Test)
|
||||
lazy val PerformanceTest = config("pt").extend(Test)
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.configs(PerformanceTest)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
lazy val scala212 = "2.12.21"
|
||||
lazy val scala213 = "2.13.12"
|
||||
|
||||
ThisBuild / scalaVersion := scala212
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
crossScalaVersions := Seq(scala212, scala213),
|
||||
)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Test that "cross" works as an alias for "+"
|
||||
> cross clean
|
||||
|
||||
# Test that "cross" works with verbose flag
|
||||
> cross -v compile
|
||||
|
||||
# Test that "switch" works as an alias for "++"
|
||||
> switch 2.13.12!
|
||||
|
||||
# Test that "switch" works with a command
|
||||
> switch 2.12.21! compile
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import sbt.TupleSyntax.*
|
||||
lazy val root = (project in file(".")).settings(
|
||||
a := (baseDirectory mapN (b => if ((b / "succeed").exists) () else sys.error("fail"))).value,
|
||||
a := baseDirectory.mapN(b => if ((b / "succeed").exists) () else sys.error("fail")).value,
|
||||
// deprecated?
|
||||
// b := (a.task(at => nop dependsOn(at))).value,
|
||||
c := (a mapN { _ => () }).value,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ val aResolver = Def.setting {
|
|||
|
||||
val bResolver = Def.setting {
|
||||
val dir = (ThisBuild / baseDirectory).value / "b-repo"
|
||||
Resolver.file("b-resolver", dir)(Resolver.defaultIvyPatterns)
|
||||
Resolver.file("b-resolver", dir)(using Resolver.defaultIvyPatterns)
|
||||
}
|
||||
|
||||
val apiBaseSetting = apiURL := Some(apiBase(name.value))
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ val check = inputKey[Unit]("")
|
|||
val sample = AttributeKey[Int]("demo-key")
|
||||
val dummyKey = taskKey[Unit]("")
|
||||
|
||||
def updateDemoInit = state map { s => (s get sample getOrElse 9) + 1 }
|
||||
def updateDemoInit = state map { s => s.get(sample).getOrElse(9) + 1 }
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
updateDemo := (updateDemoInit updateState demoState).value,
|
||||
updateDemo := updateDemoInit.updateState(demoState).value,
|
||||
check := checkInit.evaluated,
|
||||
inMemorySetting,
|
||||
persistedSetting,
|
||||
|
|
@ -27,19 +27,19 @@ lazy val root = (project in file(".")).
|
|||
dummyKey := (),
|
||||
)
|
||||
|
||||
def demoState(s: State, i: Int): State = s put (sample, i + 1)
|
||||
def demoState(s: State, i: Int): State = s.put(sample, i + 1)
|
||||
|
||||
def checkInit: Initialize[InputTask[Unit]] = Def inputTask {
|
||||
val key = (token(Space ~> IntBasic) ~ token(Space ~> IntBasic).?).parsed
|
||||
val (curExpected, prevExpected) = key
|
||||
val value = updateDemo.value
|
||||
val prev = state.value get sample
|
||||
val prev = state.value.get(sample)
|
||||
assert(value == curExpected, s"Expected current value to be $curExpected, got $value")
|
||||
assert(prev == prevExpected, s"Expected previous value to be $prevExpected, got $prev")
|
||||
}
|
||||
|
||||
def inMemorySetting = keep := (getPrevious(keep) map { case None => 3; case Some(x) => x + 1} keepAs(keep)).value
|
||||
def persistedSetting = persist := (loadPrevious(persist) map { case None => 17; case Some(x) => x + 1} storeAs(persist)).value
|
||||
def inMemorySetting = keep := getPrevious(keep) .map { case None => 3; case Some(x) => x + 1}.keepAs(keep).value
|
||||
def persistedSetting = persist := loadPrevious(persist).map { case None => 17; case Some(x) => x + 1}.storeAs(persist).value
|
||||
|
||||
def inMemoryCheck = checkKeep := (inputCheck( (ctx, s) => Space ~> str( getFromContext( keep, ctx, s)) )).evaluated
|
||||
def persistedCheck = checkPersist := (inputCheck( (ctx, s) => Space ~> str(loadFromContext(persist, ctx, s)) )).evaluated
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
lazy val helloWithoutStreams = taskKey[Unit]("")
|
||||
lazy val helloWithStreams = taskKey[Unit]("")
|
||||
|
||||
helloWithoutStreams := {
|
||||
throw new RuntimeException("boom without streams!")
|
||||
}
|
||||
|
||||
helloWithStreams := {
|
||||
val log = streams.value.log
|
||||
throw new RuntimeException("boom with streams!")
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
-> helloWithoutStreams
|
||||
-> helloWithStreams
|
||||
|
|
@ -63,7 +63,7 @@ def org = "test"
|
|||
def mainArtifact = Artifact(artifactID, tpe, ext, classifier)
|
||||
|
||||
// define the IDs to use for publishing and retrieving
|
||||
def publishedID = org % artifactID % vers artifacts(mainArtifact)
|
||||
def publishedID = (org % artifactID % vers).artifacts(mainArtifact)
|
||||
def retrieveID = org % "test-retrieve" % "2.0"
|
||||
|
||||
// check that the test class is on the compile classpath, either because it was compiled or because it was properly retrieved
|
||||
|
|
@ -80,5 +80,5 @@ def checkTask(classpath: TaskKey[Classpath]) =
|
|||
// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
|
||||
def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
|
||||
val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
|
||||
Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
|
||||
Resolver.file("User Local", ivyHome / "local")(using Resolver.defaultIvyPatterns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,5 +33,5 @@ val a = project
|
|||
// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
|
||||
def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
|
||||
val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
|
||||
Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
|
||||
Resolver.file("User Local", ivyHome / "local")(using Resolver.defaultIvyPatterns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ lazy val check = taskKey[Unit]("check classifier in update report")
|
|||
|
||||
lazy val root = (project in file(".")).settings(
|
||||
scalaVersion := "2.13.16",
|
||||
libraryDependencies += "io.netty" % "netty-transport-native-epoll" % "4.1.118.Final" classifier "linux-x86_64",
|
||||
libraryDependencies += ("io.netty" % "netty-transport-native-epoll" % "4.1.118.Final").classifier("linux-x86_64"),
|
||||
check := {
|
||||
val report = update.value
|
||||
val modules = report.configurations.flatMap(_.modules)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ivyPaths := IvyPaths(baseDirectory.value.toString, Some(((ThisBuild / baseDirectory).value / "ivy" / "cache").toString))
|
||||
ThisBuild / csrCacheDirectory := (ThisBuild / baseDirectory).value / "coursier-cache"
|
||||
|
||||
libraryDependencies += "org.testng" % "testng" % "5.7" classifier "jdk15"
|
||||
libraryDependencies += ("org.testng" % "testng" % "5.7").classifier("jdk15")
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
ThisBuild / scalaVersion := "2.11.12"
|
||||
libraryDependencies += "org.jclouds.api" % "nova" % "1.5.9" classifier "tests"
|
||||
libraryDependencies += ("org.jclouds.api" % "nova" % "1.5.9").classifier("tests")
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ libraryDependencies += "bad" % "mvn" % "1.0"
|
|||
TaskKey[Unit]("check") := {
|
||||
val cp = (Compile / fullClasspath).value
|
||||
def isTestJar(n: String): Boolean =
|
||||
(n contains "scalacheck") ||
|
||||
(n contains "specs2")
|
||||
n.contains("scalacheck") ||
|
||||
n.contains("specs2")
|
||||
val testLibs = cp map (_.data.name) filter isTestJar
|
||||
assert(testLibs.isEmpty, s"Compile Classpath has test libs:\n * ${testLibs.mkString("\n * ")}")
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
resolvers += Resolver.file("buggy", file("repo"))(
|
||||
resolvers += Resolver.file("buggy", file("repo"))(using
|
||||
Patterns(
|
||||
ivyPatterns = Vector("[organization]/[module]/[revision]/ivy.xml"),
|
||||
artifactPatterns = Vector("[organization]/[module]/[revision]/[artifact].[ext]"),
|
||||
|
|
@ -8,5 +8,5 @@ resolvers += Resolver.file("buggy", file("repo"))(
|
|||
)
|
||||
)
|
||||
|
||||
libraryDependencies += "a" % "b" % "1.0.0" % "compile->runtime" artifacts(Artifact("b1", "jar", "jar"))
|
||||
libraryDependencies += "a" % "b" % "1.0.0" % "test->runtime" artifacts(Artifact("b1", "jar", "jar"))
|
||||
libraryDependencies += ("a" % "b" % "1.0.0" % "compile->runtime").artifacts(Artifact("b1", "jar", "jar"))
|
||||
libraryDependencies += ("a" % "b" % "1.0.0" % "test->runtime").artifacts(Artifact("b1", "jar", "jar"))
|
||||
|
|
|
|||
|
|
@ -61,5 +61,5 @@ val use2 = project
|
|||
// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
|
||||
def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
|
||||
val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
|
||||
Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
|
||||
Resolver.file("User Local", ivyHome / "local")(using Resolver.defaultIvyPatterns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
libraryDependencies += "org.vaadin" % "dontpush-addon-ozonelayer" % "0.4.6" exclude("org.atmosphere", "atmosphere-compat-jetty")
|
||||
libraryDependencies += ("org.vaadin" % "dontpush-addon-ozonelayer" % "0.4.6").exclude("org.atmosphere", "atmosphere-compat-jetty")
|
||||
|
||||
resolvers += "asdf" at "https://maven.vaadin.com/vaadin-addons"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ def check(className: String): Def.Initialize[Task[Unit]] =
|
|||
import sbt.TupleSyntax.*
|
||||
(Compile / fullClasspath, fileConverter.toTaskable) mapN { (cp, c) =>
|
||||
given FileConverter = c
|
||||
val existing = cp.files.filter(_.toFile.getName contains "scala-library")
|
||||
val existing = cp.files.filter(_.toFile.getName.contains("scala-library"))
|
||||
println("Full classpath: " + cp.mkString("\n\t", "\n\t", ""))
|
||||
println("scala-library.jar: " + existing.mkString("\n\t", "\n\t", ""))
|
||||
val loader = ClasspathUtilities.toLoader(existing.map(_.toFile()))
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ def libraryDeps(base: File) = {
|
|||
def check(ver: String) =
|
||||
(Compile / dependencyClasspath) map { jars =>
|
||||
val log4j = jars map (_.data) collect {
|
||||
case f if f.name contains "log4j-" => f.name
|
||||
case f if f.name.contains("log4j-") => f.name
|
||||
}
|
||||
if (log4j.size != 1 || !log4j.head.contains(ver))
|
||||
sys.error("Did not download the correct jar.")
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ val publishPort = 3030
|
|||
// Publish to HTTP server (localhost) - ivyless publish uses PUT
|
||||
// Resolver.url expects java.net.URL; in build.sbt "url" is sbt.URI, so use java.net.URL explicitly
|
||||
publishTo := Some(
|
||||
Resolver.url("test-repo", new java.net.URI(s"http://localhost:$publishPort/").toURL)(Resolver.ivyStylePatterns)
|
||||
Resolver.url("test-repo", new java.net.URI(s"http://localhost:$publishPort/").toURL)(using Resolver.ivyStylePatterns)
|
||||
.withAllowInsecureProtocol(true)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ scalaVersion := "3.8.3"
|
|||
val publishRepoBase = settingKey[File]("Base directory for publish repo")
|
||||
publishRepoBase := baseDirectory.value / "repo"
|
||||
|
||||
publishTo := Some(Resolver.file("test-repo", publishRepoBase.value)(Resolver.ivyStylePatterns))
|
||||
publishTo := Some(Resolver.file("test-repo", publishRepoBase.value)(using Resolver.ivyStylePatterns))
|
||||
|
||||
useIvy := false
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ version := ( if(stable.value) "1.0" else "1.1-SNAPSHOT" )
|
|||
|
||||
publishTo := {
|
||||
val base = baseDirectory.value / ( if(stable.value) "stable" else "snapshot" )
|
||||
Some( Resolver.file("local-" + base, base)(Resolver.ivyStylePatterns) )
|
||||
Some( Resolver.file("local-" + base, base)(using Resolver.ivyStylePatterns) )
|
||||
}
|
||||
|
||||
publishMavenStyle := false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
addSbtPlugin("org.example" % "def" % "latest.integration")
|
||||
|
||||
resolvers ++= {
|
||||
def r(tpe: String) = Resolver.file(s"local-$tpe", baseDirectory.value / ".." / tpe)(Resolver.ivyStylePatterns)
|
||||
def r(tpe: String) = Resolver.file(s"local-$tpe", baseDirectory.value / ".." / tpe)(using Resolver.ivyStylePatterns)
|
||||
r("snapshot") :: r("stable") :: Nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import scala.xml._
|
||||
|
||||
lazy val root = (project in file(".")) settings (
|
||||
lazy val root = (project in file(".")).settings(
|
||||
readPom := Def.uncached {
|
||||
val vf = makePom.value
|
||||
val converter = fileConverter.value
|
||||
XML.loadFile(converter.toPath(vf).toFile)
|
||||
},
|
||||
description := "pom.xml test description",
|
||||
homepage := Some(url("https://example.com/pom_test_url")),
|
||||
TaskKey[Unit]("checkPom") := checkPom.value,
|
||||
TaskKey[Unit]("checkExtra") := checkExtra.value,
|
||||
TaskKey[Unit]("checkVersionPlusMapping") := checkVersionPlusMapping.value,
|
||||
|
|
@ -65,13 +67,17 @@ lazy val checkReleaseNotesURL = readPom.map: pomXml =>
|
|||
lazy val checkPom = Def.task {
|
||||
val pomXML = readPom.value
|
||||
checkProject(pomXML)
|
||||
val urlFromPom = (pomXML \ "url").text
|
||||
assert(urlFromPom == "https://example.com/pom_test_url", s"Expected homepage url, got: $urlFromPom")
|
||||
val descriptionFromPom = (pomXML \ "description").text
|
||||
assert(descriptionFromPom == "pom.xml test description", s"Expected description, got: $descriptionFromPom")
|
||||
val ivyRepositories = fullResolvers.value
|
||||
withRepositories(pomXML) { repositoriesElement =>
|
||||
val repositories = repositoriesElement \ "repository"
|
||||
val writtenRepositories = repositories.map(read).distinct
|
||||
val mavenStyleRepositories = (ivyRepositories.collect {
|
||||
case x: MavenRepository
|
||||
if (x.name != "public") && (x.name != "jcenter") && !(x.root startsWith "file:") =>
|
||||
if (x.name != "public") && (x.name != "jcenter") && !(x.root.startsWith("file:")) =>
|
||||
normalize(x)
|
||||
}).distinct
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ TaskKey[Unit]("checkName") := Def.uncached {
|
|||
val path = converter.toPath(vf).toAbsolutePath.toString
|
||||
val module = moduleName.value
|
||||
val n = name.value
|
||||
assert(path contains module, s"Path $path did not contain module name $module")
|
||||
assert(path.contains(module), s"Path $path did not contain module name $module")
|
||||
assert(!path.contains(n), s"Path $path contained $n")
|
||||
()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
libraryDependencies ++= Seq("natives-windows", "natives-linux", "natives-osx") map ( c =>
|
||||
"org.lwjgl.lwjgl" % "lwjgl-platform" % "2.8.2" classifier c
|
||||
("org.lwjgl.lwjgl" % "lwjgl-platform" % "2.8.2").classifier(c)
|
||||
)
|
||||
|
||||
autoScalaLibrary := false
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ def commonSettings: Seq[Def.Setting[?]] =
|
|||
scalaVersion := "2.10.4",
|
||||
ThisBuild / organization := "org.example",
|
||||
ThisBuild / version := "1.0-SNAPSHOT",
|
||||
resolvers += Resolver.file("old-local", file(sys.props("user.home") + "/.ivy2/local"))(Resolver.ivyStylePatterns)
|
||||
resolvers += Resolver.file("old-local", file(sys.props("user.home") + "/.ivy2/local"))(using Resolver.ivyStylePatterns)
|
||||
)
|
||||
|
||||
lazy val main = project.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ lazy val root = (project in file("."))
|
|||
dependencyOverrides += "org.webjars.npm" % "is-number" % "5.0.0",
|
||||
check := {
|
||||
val cp = (Compile / externalDependencyClasspath).value.map {_.data.name}.sorted
|
||||
if (!(cp contains "is-number-5.0.0.jar")) {
|
||||
if (!cp.contains("is-number-5.0.0.jar")) {
|
||||
sys.error("is-number-5.0.0 not found when it should be included: " + cp.toString)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def pomIncludeRepository(base: File, prev: MavenRepository => Boolean): MavenRep
|
|||
}
|
||||
|
||||
def addSlash(s: String): String = s match {
|
||||
case s if s endsWith "/" => s
|
||||
case s if s.endsWith("/") => s
|
||||
case _ => s + "/"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ lazy val root = (project in file("."))
|
|||
.settings(
|
||||
scalaVersion := "2.13.16",
|
||||
autoScalaLibrary := false,
|
||||
libraryDependencies += "org.eclipse.jetty" % "jetty-webapp" % "11.0.15" artifacts (Artifact("jetty-webapp", "war", "war")),
|
||||
libraryDependencies += ("org.eclipse.jetty" % "jetty-webapp" % "11.0.15").artifacts(Artifact("jetty-webapp", "war", "war")),
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.4.3",
|
||||
// classified artifact with non-default type: both <type> and <classifier> must appear
|
||||
libraryDependencies += ("com.example" % "classified-war" % "1.0")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
val root = project in file(".")
|
||||
val subJar = project in file("subJar")
|
||||
def warArtifact = (Compile / packageBin / artifact) ~= (_ withType "war" withExtension "war")
|
||||
val subWar = project in file("subWar") settings warArtifact
|
||||
val subParent = project in file("subParent") settings ((Compile / publishArtifact) := false)
|
||||
def warArtifact = (Compile / packageBin / artifact) ~= (_.withType("war").withExtension("war"))
|
||||
val subWar = project.in(file("subWar")).settings(warArtifact)
|
||||
val subParent = project.in(file("subParent")).settings((Compile / publishArtifact) := false)
|
||||
|
||||
val checkPom = taskKey[Unit]("")
|
||||
(ThisBuild / checkPom) := {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ lazy val root = (project in file(".")).
|
|||
"d" % "d" % "1.0" % "test",
|
||||
"e" % "e" % "1.0" % Custom,
|
||||
"f" % "f" % "1.0" % "custom,optional,runtime",
|
||||
"g" % "g" % "1.0" % "custom,runtime" classifier "foo",
|
||||
"h" % "h" % "1.0" % "custom,optional,runtime" classifier "foo"
|
||||
("g" % "g" % "1.0" % "custom,runtime").classifier("foo"),
|
||||
("h" % "h" % "1.0" % "custom,optional,runtime").classifier("foo")
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ lazy val root = (project in file(".")).
|
|||
)
|
||||
|
||||
def checkServletAPI(paths: Seq[File], shouldBeIncluded: Boolean, label: String) = {
|
||||
val servletAPI = paths.find(_.getName contains "servlet-api")
|
||||
val servletAPI = paths.find(_.getName.contains("servlet-api"))
|
||||
if (shouldBeIncluded) {
|
||||
if (servletAPI.isEmpty) sys.error(s"Servlet API should have been included in $label.")
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ lazy val root = (project in file(".")).
|
|||
organization := "A",
|
||||
version := "1.0",
|
||||
ivyPaths := baseDirectory( dir => IvyPaths(dir, Some(dir / "ivy" / "cache")) ).value,
|
||||
externalResolvers := (baseDirectory map { base => Resolver.file("local", base / "ivy" / "local" asFile)(Resolver.ivyStylePatterns) :: Nil }).value
|
||||
externalResolvers := (baseDirectory map { base => Resolver.file("local", base / "ivy" / "local" asFile)(using Resolver.ivyStylePatterns) :: Nil }).value
|
||||
)),
|
||||
mavenStyle,
|
||||
interProject,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ lazy val root = (project in file(".")).
|
|||
organization := "A",
|
||||
version := "1.0",
|
||||
ivyPaths := baseDirectory( dir => IvyPaths(dir, Some(dir / "ivy" / "cache")) ).value,
|
||||
externalResolvers := (baseDirectory map { base => Resolver.file("local", base / "ivy" / "local" asFile)(Resolver.ivyStylePatterns) :: Nil }).value
|
||||
externalResolvers := (baseDirectory map { base => Resolver.file("local", base / "ivy" / "local" asFile)(using Resolver.ivyStylePatterns) :: Nil }).value
|
||||
)),
|
||||
mavenStyle,
|
||||
name := "Retrieve Test",
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ libraryDependencies += "org.scala-lang" % "scala-actors" % "2.11.12"
|
|||
lazy val check = taskKey[Unit]("Runs the check")
|
||||
|
||||
check := {
|
||||
val lastLog = BuiltinCommands lastLogFile state.value
|
||||
val lastLog = BuiltinCommands.lastLogFile(state.value)
|
||||
val last = IO read lastLog.get
|
||||
def containsWarn1 = last contains "Binary version (1.1.0) for dependency org.scala-lang#scala-actors-migration_2.11;1.1.0"
|
||||
def containsWarn2 = last contains "Binary version (0.9.1) for dependency org.scala-lang#scala-pickling_2.11;0.9.1"
|
||||
def containsWarn3 = last contains "differs from Scala binary version in project (2.11)."
|
||||
def containsWarn1 = last.contains("Binary version (1.1.0) for dependency org.scala-lang#scala-actors-migration_2.11;1.1.0")
|
||||
def containsWarn2 = last.contains("Binary version (0.9.1) for dependency org.scala-lang#scala-pickling_2.11;0.9.1")
|
||||
def containsWarn3 = last.contains("differs from Scala binary version in project (2.11).")
|
||||
if (containsWarn1 && containsWarn3) sys error "scala-actors-migration isn't exempted from the Scala binary version check"
|
||||
if (containsWarn2 && containsWarn3) sys error "scala-pickling isn't exempted from the Scala binary version check"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ def localCache =
|
|||
|
||||
lazy val sharedResolver: Resolver = {
|
||||
val r = Resolver.defaultShared
|
||||
r withConfiguration (r.configuration withIsLocal false)
|
||||
r.withConfiguration(r.configuration.withIsLocal(false))
|
||||
//MavenRepository("example-shared-repo", "file:///tmp/shared-maven-repo-bad-example")
|
||||
//Resolver.file("example-shared-repo", repoDir)(Resolver.defaultPatterns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ def localCache =
|
|||
|
||||
lazy val sharedResolver: Resolver = {
|
||||
val r = Resolver.defaultShared
|
||||
r withConfiguration (r.configuration withIsLocal false)
|
||||
r.withConfiguration(r.configuration.withIsLocal(false))
|
||||
//MavenRepository("example-shared-repo", "file:///tmp/shared-maven-repo-bad-example")
|
||||
//Resolver.file("example-shared-repo", repoDir)(Resolver.defaultPatterns)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ lazy val root = (project in file("."))
|
|||
autoScalaLibrary := false,
|
||||
managedScalaInstance := false,
|
||||
transitiveClassifiers := Seq("sources"),
|
||||
TaskKey[Unit]("checkSources") := (updateClassifiers map checkSources).value,
|
||||
TaskKey[Unit]("checkBinaries") := (update map checkBinaries).value,
|
||||
TaskKey[Unit]("checkSources") := updateClassifiers.map(checkSources).value,
|
||||
TaskKey[Unit]("checkBinaries") := update.map(checkBinaries).value,
|
||||
)
|
||||
|
||||
def getSources(report: UpdateReport) = report.matching(artifactFilter(`classifier` = "sources") )
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ ThisBuild / scalaVersion := "2.12.12"
|
|||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.5.22",
|
||||
TaskKey[Unit]("checkSources") := (updateClassifiers map checkSources).value,
|
||||
TaskKey[Unit]("checkBinaries") := (update map checkBinaries).value
|
||||
TaskKey[Unit]("checkSources") := updateClassifiers.map(checkSources).value,
|
||||
TaskKey[Unit]("checkBinaries") := update.map(checkBinaries).value
|
||||
)
|
||||
|
||||
def getSources(report: UpdateReport) = report.matching(artifactFilter(`classifier` = "sources") )
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
libraryDependencies += "org.example" % "def" % "2.0" classifier("tests")
|
||||
libraryDependencies += ("org.example" % "def" % "2.0").classifier("tests")
|
||||
|
||||
externalResolvers := Seq("example" at (baseDirectory.value / "ivy-repo").toURI.toString)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ libraryDependencies += "exclude.test" % "app" % "1.0.0"
|
|||
val checkDependencies = taskKey[Unit]("Checks that dependencies are correct.")
|
||||
|
||||
checkDependencies := {
|
||||
val hasBadJar = (Compile / fullClasspath).value.exists { jar => jar.data.name contains "bottom-1.0.0.jar"}
|
||||
val hasBadJar = (Compile / fullClasspath).value.exists { jar => jar.data.name.contains("bottom-1.0.0.jar")}
|
||||
val errorJarString = (Compile / fullClasspath).value.map(_.data.name).mkString(" * ", "\n * ", "")
|
||||
val hasBadMiddleJar = (Compile / fullClasspath).value.exists { jar => jar.data.name contains "middle-1.0.0.jar"}
|
||||
val hasBadMiddleJar = (Compile / fullClasspath).value.exists { jar => jar.data.name.contains("middle-1.0.0.jar")}
|
||||
assert(!hasBadMiddleJar, s"Failed to exclude excluded dependency on classpath!\nFound:\n$errorJarString")
|
||||
assert(!hasBadJar, s"Failed to exclude transitive excluded dependency on classpath!\nFound:\n$errorJarString")
|
||||
val modules =
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
ThisBuild / scalaVersion := "2.11.12"
|
||||
|
||||
libraryDependencies += "ccl.northwestern.edu" % "netlogo" % "5.3.1" % "provided" from s"https://github.com/NetLogo/NetLogo/releases/download/5.3.1/NetLogo.jar"
|
||||
libraryDependencies += ("ccl.northwestern.edu" % "netlogo" % "5.3.1" % "provided").from(s"https://github.com/NetLogo/NetLogo/releases/download/5.3.1/NetLogo.jar")
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ def localCache =
|
|||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
localCache,
|
||||
libraryDependencies += "org.jsoup" % "jsoup" % "1.9.1" % Test from "https://jsoup.org/packages/jsoup-1.9.1.jar",
|
||||
libraryDependencies += ("org.jsoup" % "jsoup" % "1.9.1" % Test).from("https://jsoup.org/packages/jsoup-1.9.1.jar"),
|
||||
ivyLoggingLevel := UpdateLogging.Full,
|
||||
TaskKey[Unit]("checkInTest") := checkClasspath(Test).value,
|
||||
TaskKey[Unit]("checkInCompile") := checkClasspath(Compile).value
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ val commonSettings = Seq[Def.Setting[?]](
|
|||
lazy val bippy = project settings (
|
||||
commonSettings,
|
||||
resolvers += Resolver
|
||||
.file("ivy-local", file(sys.props("user.home")) / ".ivy2" / "local")(Resolver.ivyStylePatterns),
|
||||
.file("ivy-local", file(sys.props("user.home")) / ".ivy2" / "local")(using Resolver.ivyStylePatterns),
|
||||
publishTo := Some(Resolver.file("local-repo", localRepo.value))
|
||||
)
|
||||
|
||||
|
|
@ -40,6 +40,6 @@ InputKey[Unit]("check") := {
|
|||
val s = IO readStream jar.getInputStream(jar.getJarEntry("Bippy.scala"))
|
||||
|
||||
val expected = s"def release = $n"
|
||||
assert(s contains expected, s"""Bippy should contain $expected, contents:\n$s""")
|
||||
assert(s.contains(expected), s"""Bippy should contain $expected, contents:\n$s""")
|
||||
()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
resolvers += Resolver.file("ivy-local", file(sys.props("user.home")) / ".ivy2" / "local")(Resolver.ivyStylePatterns)
|
||||
resolvers += Resolver.file("ivy-local", file(sys.props("user.home")) / ".ivy2" / "local")(using Resolver.ivyStylePatterns)
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ lazy val root = (project in file(".")).
|
|||
val acp = (a / Compile / externalDependencyClasspath).value.sortBy {_.data.name}
|
||||
val bcp = (b / Compile / externalDependencyClasspath).value.sortBy {_.data.name}
|
||||
|
||||
if (acp exists { _.data.name contains "slf4j-api-1.7.5.jar" }) {
|
||||
if (acp exists { _.data.name.contains("slf4j-api-1.7.5.jar") }) {
|
||||
sys.error("slf4j-api-1.7.5.jar found when it should NOT be included: " + acp.toString)
|
||||
}
|
||||
if (bcp exists { _.data.name contains "dispatch-core_2.11-0.11.1.jar" }) {
|
||||
if (bcp exists { _.data.name.contains("dispatch-core_2.11-0.11.1.jar") }) {
|
||||
sys.error("dispatch-core_2.11-0.11.1.jar found when it should NOT be included: " + bcp.toString)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ lazy val b = project
|
|||
|
||||
lazy val bResolver = Def.setting {
|
||||
val dir = (ThisBuild / baseDirectory).value / "b-repo"
|
||||
Resolver.file("b-resolver", dir)(Resolver.defaultIvyPatterns)
|
||||
Resolver.file("b-resolver", dir)(using Resolver.defaultIvyPatterns)
|
||||
}
|
||||
|
||||
lazy val check = taskKey[Unit]("")
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
scalaVersion := "2.12.8"
|
||||
libraryDependencies += "org.jclouds.api" % "nova" % "1.5.9" classifier "tests"
|
||||
libraryDependencies += ("org.jclouds.api" % "nova" % "1.5.9").classifier("tests")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
scalaVersion := "2.12.21"
|
||||
|
||||
libraryDependencies += "ccl.northwestern.edu" % "netlogo" % "5.3.1" % "provided" from s"https://github.com/NetLogo/NetLogo/releases/download/5.3.1/NetLogo.jar"
|
||||
libraryDependencies += ("ccl.northwestern.edu" % "netlogo" % "5.3.1" % "provided").from(s"https://github.com/NetLogo/NetLogo/releases/download/5.3.1/NetLogo.jar")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
scalaVersion := "2.12.8"
|
||||
|
||||
resolvers += Resolver.file("space-repo", file(raw"/tmp/space the final frontier/repo"))(Resolver.ivyStylePatterns)
|
||||
resolvers += Resolver.file("space-repo", file(raw"/tmp/space the final frontier/repo"))(using Resolver.ivyStylePatterns)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ mainClass := Some("jartest.Main")
|
|||
Compile / packageBin / packageOptions := {
|
||||
def manifestExtra = {
|
||||
val mf = new Manifest
|
||||
mf.getMainAttributes.put(Attributes.Name.CLASS_PATH, makeString(scalaInstance.value.libraryJars))
|
||||
mf.getMainAttributes.put(Attributes.Name.CLASS_PATH, makeString(scalaInstance.value.libraryJars.toSeq))
|
||||
mf
|
||||
}
|
||||
(Compile / packageBin / packageOptions).value :+ Package.JarManifest(manifestExtra)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ packageOptions := {
|
|||
def manifestExtra = {
|
||||
import java.util.jar._
|
||||
val mf = new Manifest
|
||||
mf.getMainAttributes.put(Attributes.Name.CLASS_PATH, makeString(scalaInstance.value.libraryJars))
|
||||
mf.getMainAttributes.put(Attributes.Name.CLASS_PATH, makeString(scalaInstance.value.libraryJars.toSeq))
|
||||
mf
|
||||
}
|
||||
Package.JarManifest(manifestExtra) +: packageOptions.value
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
val test123 = project in file(".") enablePlugins TestP settings(
|
||||
val test123 = project.in(file(".")).enablePlugins(TestP).settings(
|
||||
Compile / resourceGenerators += Def.task {
|
||||
streams.value.log.info("resource generated in settings")
|
||||
Seq.empty[File]
|
||||
|
|
@ -6,9 +6,9 @@ val test123 = project in file(".") enablePlugins TestP settings(
|
|||
)
|
||||
|
||||
TaskKey[Unit]("check") := {
|
||||
val last = IO read (BuiltinCommands lastLogFile state.value).get
|
||||
val last = IO.read(BuiltinCommands.lastLogFile(state.value).get)
|
||||
def assertContains(expectedString: String) =
|
||||
if (!(last contains expectedString)) sys error s"Expected string $expectedString to be present"
|
||||
if (!last.contains(expectedString)) sys error s"Expected string $expectedString to be present"
|
||||
assertContains("resource generated in settings")
|
||||
assertContains("resource generated in plugin")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ val root = (project in file("."))
|
|||
|
||||
TaskKey[Unit]("checkScalaVersion", "test") := Def.uncached {
|
||||
val sv = scalaVersion.value
|
||||
assert(sv startsWith "3.", s"Found $sv!")
|
||||
assert(sv.startsWith("3."), s"Found $sv!")
|
||||
}
|
||||
|
||||
TaskKey[Unit]("checkArtifacts", "test") := Def.uncached {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
val loadCount = AttributeKey[Int]("load-count")
|
||||
val unloadCount = AttributeKey[Int]("unload-count")
|
||||
def f(key: AttributeKey[Int]) = (s: State) => {
|
||||
val previous = s get key getOrElse 0
|
||||
val previous = s.get(key)getOrElse(0)
|
||||
s.put(key, previous + 1)
|
||||
}
|
||||
Seq(
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
InputKey[Unit]("checkCount") := {
|
||||
val s = state.value
|
||||
val args = Def.spaceDelimited().parsed
|
||||
def get(label: String) = s get AttributeKey[Int](label) getOrElse 0
|
||||
def get(label: String) = s.get(AttributeKey[Int](label)).getOrElse(0)
|
||||
val loadCount = get("load-count")
|
||||
val unloadCount = get("unload-count")
|
||||
val expectedLoad = args(0).toInt
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ object Common {
|
|||
|
||||
|
||||
val UpdateK3 = Command.command("UpdateK3"): (st: State) =>
|
||||
val ex = Project extract st
|
||||
val ex = Project.extract(st)
|
||||
import ex._
|
||||
val session2 = BuiltinCommands.setThis(ex, Seq(k3 := {}), """k3 := {
|
||||
|//
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ lazy val commonSettings = Seq(
|
|||
val ivyHome = Classpaths.bootIvyHome(appConfiguration.value) getOrElse sys.error(
|
||||
"Launcher did not provide the Ivy home directory."
|
||||
)
|
||||
Resolver.file("real-local", ivyHome / "local")(Resolver.ivyStylePatterns)
|
||||
Resolver.file("real-local", ivyHome / "local")(using Resolver.ivyStylePatterns)
|
||||
},
|
||||
resolvers += Resolver.mavenLocal,
|
||||
resolvers += ("test-repo" at ((ThisBuild / baseDirectory).value / "repo/").asURL.toString)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
lazy val a = project in file(".") dependsOn(b)
|
||||
lazy val a = project.in(file(".")).dependsOn(b)
|
||||
lazy val b = project
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ lazy val dep = project
|
|||
|
||||
lazy val use = project.
|
||||
settings(
|
||||
(Compile / unmanagedJars) += ((dep / Compile / packageBin) map Attributed.blank).value
|
||||
(Compile / unmanagedJars) += (dep / Compile / packageBin).map(Attributed.blank).value
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ object Main:
|
|||
val sbtHome = new File(
|
||||
sys.env
|
||||
.get("SBT_HOME")
|
||||
.getOrElse:
|
||||
.getOrElse(
|
||||
sys.env.get("SBT_BIN_DIR").map(d => new File(d).getParent).getOrElse(cwd.getAbsolutePath)
|
||||
)
|
||||
)
|
||||
val sbtBinDir = new File(sbtHome, "bin")
|
||||
|
||||
|
|
@ -26,86 +27,88 @@ object Main:
|
|||
System.exit(if exitCode == 0 then 0 else 1)
|
||||
|
||||
private def run(cwd: File, sbtHome: File, sbtBinDir: File, opts: LauncherOptions): Int =
|
||||
if opts.help then return printUsage()
|
||||
if opts.version || opts.numericVersion || opts.scriptVersion then
|
||||
return handleVersionCommands(cwd, sbtHome, sbtBinDir, opts)
|
||||
if opts.shutdownAll then
|
||||
if opts.help then printUsage()
|
||||
else if opts.version || opts.numericVersion || opts.scriptVersion then
|
||||
handleVersionCommands(cwd, sbtHome, sbtBinDir, opts)
|
||||
else if opts.shutdownAll then
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
return Runner.shutdownAll(javaCmd)
|
||||
|
||||
if !opts.allowEmpty && !opts.sbtNew && !ConfigLoader.isSbtProjectDir(cwd) then
|
||||
Runner.shutdownAll(javaCmd)
|
||||
else if !opts.allowEmpty && !opts.sbtNew && !ConfigLoader.isSbtProjectDir(cwd) then
|
||||
System.err.println(
|
||||
"[error] Neither build.sbt nor a 'project' directory in the current directory: " + cwd
|
||||
)
|
||||
System.err.println("[error] run 'sbt new', touch build.sbt, or run 'sbt --allow-empty'.")
|
||||
return 1
|
||||
1
|
||||
else
|
||||
val buildPropsVersion = ConfigLoader.sbtVersionFromBuildProperties(cwd)
|
||||
|
||||
val buildPropsVersion = ConfigLoader.sbtVersionFromBuildProperties(cwd)
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
val javaVer = Runner.javaVersion(javaCmd)
|
||||
val minJdk = Runner.minimumJdkVersion(buildPropsVersion)
|
||||
if javaVer > 0 && javaVer < minJdk then
|
||||
if minJdk >= 17 then
|
||||
System.err.println(
|
||||
"[error] sbt 2.x requires JDK 17 or above, but you have JDK " + javaVer
|
||||
)
|
||||
else System.err.println("[error] sbt requires at least JDK 8+, you have " + javaVer)
|
||||
1
|
||||
else
|
||||
val bspMode = opts.residual.exists(a => a == "bsp" || a == "-bsp" || a == "--bsp")
|
||||
val clientOpt = opts.client || sys.env.get("SBT_NATIVE_CLIENT").contains("true")
|
||||
val useNativeClient =
|
||||
if bspMode then false
|
||||
else shouldRunNativeClient(opts.copy(client = clientOpt), buildPropsVersion)
|
||||
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
val javaVer = Runner.javaVersion(javaCmd)
|
||||
val minJdk = Runner.minimumJdkVersion(buildPropsVersion)
|
||||
if javaVer > 0 && javaVer < minJdk then
|
||||
if minJdk >= 17 then
|
||||
System.err.println("[error] sbt 2.x requires JDK 17 or above, but you have JDK " + javaVer)
|
||||
else System.err.println("[error] sbt requires at least JDK 8+, you have " + javaVer)
|
||||
return 1
|
||||
if useNativeClient then
|
||||
val scriptPath = sbtBinDir.getAbsolutePath.replace("\\", "/") + "/sbt.bat"
|
||||
Runner.runNativeClient(sbtBinDir, scriptPath, opts)
|
||||
else
|
||||
val sbtJar = opts.sbtJar
|
||||
.filter(p => new File(p).isFile)
|
||||
.getOrElse(new File(sbtBinDir, "sbt-launch.jar").getAbsolutePath)
|
||||
if !new File(sbtJar).isFile then
|
||||
System.err.println("[error] Launcher jar not found: " + sbtJar)
|
||||
1
|
||||
else
|
||||
var javaOpts = ConfigLoader.loadJvmOpts(cwd)
|
||||
if javaOpts.isEmpty then javaOpts = ConfigLoader.defaultJavaOpts
|
||||
var sbtOpts = Runner.buildSbtOpts(opts)
|
||||
|
||||
val bspMode = opts.residual.exists(a => a == "bsp" || a == "-bsp" || a == "--bsp")
|
||||
val clientOpt = opts.client || sys.env.get("SBT_NATIVE_CLIENT").contains("true")
|
||||
val useNativeClient =
|
||||
if bspMode then false
|
||||
else shouldRunNativeClient(opts.copy(client = clientOpt), buildPropsVersion)
|
||||
val (residualJava, bootArgs) = Runner.splitResidual(opts.residual)
|
||||
javaOpts = javaOpts ++ residualJava
|
||||
|
||||
if useNativeClient then
|
||||
val scriptPath = sbtBinDir.getAbsolutePath.replace("\\", "/") + "/sbt.bat"
|
||||
return Runner.runNativeClient(sbtBinDir, scriptPath, opts)
|
||||
val (finalJava, finalSbt) = if opts.mem.isDefined then
|
||||
val evictedJava = Memory.evictMemoryOpts(javaOpts)
|
||||
val evictedSbt = Memory.evictMemoryOpts(sbtOpts)
|
||||
val memOpts = Memory.addMemory(opts.mem.get, javaVer)
|
||||
(evictedJava ++ memOpts, evictedSbt)
|
||||
else Memory.addDefaultMemory(javaOpts, sbtOpts, javaVer, LauncherOptions.defaultMemMb)
|
||||
sbtOpts = finalSbt
|
||||
|
||||
val sbtJar = opts.sbtJar
|
||||
.filter(p => new File(p).isFile)
|
||||
.getOrElse(new File(sbtBinDir, "sbt-launch.jar").getAbsolutePath)
|
||||
if !new File(sbtJar).isFile then
|
||||
System.err.println("[error] Launcher jar not found: " + sbtJar)
|
||||
return 1
|
||||
if !opts.noHideJdkWarnings && javaVer >= 25 then
|
||||
sbtOpts = sbtOpts ++ Seq(
|
||||
"--sun-misc-unsafe-memory-access=allow",
|
||||
"--enable-native-access=ALL-UNNAMED"
|
||||
)
|
||||
val javaOptsWithDebug = opts.jvmDebug.fold(finalJava)(port =>
|
||||
finalJava :+ s"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$port"
|
||||
)
|
||||
|
||||
var javaOpts = ConfigLoader.loadJvmOpts(cwd)
|
||||
if javaOpts.isEmpty then javaOpts = ConfigLoader.defaultJavaOpts
|
||||
var sbtOpts = Runner.buildSbtOpts(opts)
|
||||
|
||||
val (residualJava, bootArgs) = Runner.splitResidual(opts.residual)
|
||||
javaOpts = javaOpts ++ residualJava
|
||||
|
||||
val (finalJava, finalSbt) = if opts.mem.isDefined then
|
||||
val evictedJava = Memory.evictMemoryOpts(javaOpts)
|
||||
val evictedSbt = Memory.evictMemoryOpts(sbtOpts)
|
||||
val memOpts = Memory.addMemory(opts.mem.get, javaVer)
|
||||
(evictedJava ++ memOpts, evictedSbt)
|
||||
else Memory.addDefaultMemory(javaOpts, sbtOpts, javaVer, LauncherOptions.defaultMemMb)
|
||||
sbtOpts = finalSbt
|
||||
|
||||
if !opts.noHideJdkWarnings && javaVer == 25 then
|
||||
sbtOpts = sbtOpts ++ Seq(
|
||||
"--sun-misc-unsafe-memory-access=allow",
|
||||
"--enable-native-access=ALL-UNNAMED"
|
||||
)
|
||||
val javaOptsWithDebug = opts.jvmDebug.fold(finalJava)(port =>
|
||||
finalJava :+ s"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$port"
|
||||
)
|
||||
|
||||
Runner.runJvm(javaCmd, javaOptsWithDebug, sbtOpts, sbtJar, bootArgs, opts.verbose)
|
||||
Runner.runJvm(javaCmd, javaOptsWithDebug, sbtOpts, sbtJar, bootArgs, opts.verbose)
|
||||
|
||||
private def shouldRunNativeClient(
|
||||
opts: LauncherOptions,
|
||||
buildPropsVersion: Option[String]
|
||||
): Boolean =
|
||||
if opts.sbtNew then return false
|
||||
if opts.jvmClient then return false
|
||||
val version = buildPropsVersion.getOrElse(LauncherOptions.initSbtVersion)
|
||||
val parts = version.split("[.-]").take(2).flatMap(s => scala.util.Try(s.toInt).toOption)
|
||||
val (major, minor) = (parts.lift(0).getOrElse(0), parts.lift(1).getOrElse(0))
|
||||
if major >= 2 then !opts.server
|
||||
else if major >= 1 && minor >= 4 then opts.client
|
||||
else false
|
||||
if opts.sbtNew then false
|
||||
else if opts.jvmClient then false
|
||||
else
|
||||
val version = buildPropsVersion.getOrElse(LauncherOptions.initSbtVersion)
|
||||
val parts = version.split("[.-]").take(2).flatMap(s => scala.util.Try(s.toInt).toOption)
|
||||
val (major, minor) = (parts.lift(0).getOrElse(0), parts.lift(1).getOrElse(0))
|
||||
if major >= 2 then !opts.server
|
||||
else if major >= 1 && minor >= 4 then opts.client
|
||||
else false
|
||||
|
||||
private def handleVersionCommands(
|
||||
cwd: File,
|
||||
|
|
@ -115,8 +118,8 @@ object Main:
|
|||
): Int =
|
||||
if opts.scriptVersion then
|
||||
println(LauncherOptions.initSbtVersion)
|
||||
return 0
|
||||
if opts.version then
|
||||
0
|
||||
else if opts.version then
|
||||
if ConfigLoader.isSbtProjectDir(cwd) then
|
||||
projectSbtVersion(cwd).foreach: version =>
|
||||
println("sbt version in this project: " + version)
|
||||
|
|
@ -125,21 +128,22 @@ object Main:
|
|||
System.err.println(
|
||||
"[info] Actual version of sbt is declared using project\\build.properties for each build."
|
||||
)
|
||||
return 0
|
||||
if opts.numericVersion then
|
||||
0
|
||||
else if opts.numericVersion then
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
val sbtJar = opts.sbtJar
|
||||
.filter(p => new File(p).isFile)
|
||||
.getOrElse(new File(sbtBinDir, "sbt-launch.jar").getAbsolutePath)
|
||||
if !new File(sbtJar).isFile then
|
||||
System.err.println("[error] Launcher jar not found for version check")
|
||||
return 1
|
||||
try
|
||||
val out = Process(Seq(javaCmd, "-jar", sbtJar, "sbtVersion")).!!
|
||||
println(out.linesIterator.toSeq.lastOption.map(_.trim).getOrElse(""))
|
||||
return 0
|
||||
catch { case _: Exception => return 1 }
|
||||
0
|
||||
1
|
||||
else
|
||||
try
|
||||
val out = Process(Seq(javaCmd, "-jar", sbtJar, "sbtVersion")).!!
|
||||
println(out.linesIterator.toSeq.lastOption.map(_.trim).getOrElse(""))
|
||||
0
|
||||
catch { case _: Exception => 1 }
|
||||
else 0
|
||||
|
||||
private def projectSbtVersion(cwd: File): Option[String] =
|
||||
ConfigLoader.sbtVersionFromBuildProperties(cwd).flatMap(normalizeVersion)
|
||||
|
|
|
|||
|
|
@ -524,6 +524,19 @@ class BuildServerTest extends AbstractServerTest {
|
|||
)
|
||||
}
|
||||
|
||||
test("buildTarget/dependencyModules") {
|
||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||
val targets = Vector(buildTarget, badBuildTarget).map(BuildTargetIdentifier.apply)
|
||||
val id = dependencyModules(targets.map(_.uri))
|
||||
val res = svr.session.waitForResultInResponseMsg[DependencyModulesResult](10.seconds, id).get
|
||||
val runAndTestItem = res.items.find(_.target.contains(BuildTargetIdentifier(buildTarget))).get
|
||||
assert(
|
||||
runAndTestItem.modules.exists(_.name.contains("jsoniter-scala-core")),
|
||||
s"dependencyModules should include jsoniter-scala-core, got: ${runAndTestItem.modules.map(_.name)}"
|
||||
)
|
||||
}
|
||||
|
||||
test("buildTarget/outputPaths") {
|
||||
val buildTarget = buildTargetUri("util", "Compile")
|
||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||
|
|
@ -753,6 +766,11 @@ class BuildServerTest extends AbstractServerTest {
|
|||
sendRequest("buildTarget/sources", SourcesParams(targets))
|
||||
}
|
||||
|
||||
private def dependencyModules(buildTargets: Seq[URI]): String = {
|
||||
val targets = buildTargets.map(BuildTargetIdentifier.apply).toVector
|
||||
sendRequest("buildTarget/dependencyModules", DependencyModulesParams(targets))
|
||||
}
|
||||
|
||||
private def sendRequest(method: String): String = {
|
||||
val id = svr.session.nextId()
|
||||
svr.session.sendJsonRpc(id, method, "{}").get
|
||||
|
|
|
|||
|
|
@ -79,6 +79,16 @@ class ResponseTest extends AbstractServerTest {
|
|||
}
|
||||
}
|
||||
|
||||
test("unknown method returns error") {
|
||||
val id = svr.session.nextId()
|
||||
svr.session.sendJsonRpc(id, "build/foo", "{}").get
|
||||
val response = svr.session.waitForResponseMsg(10.seconds, id).get
|
||||
assert(
|
||||
response.error.exists(_.code == -32601),
|
||||
s"Expected method-not-found error, got: $response"
|
||||
)
|
||||
}
|
||||
|
||||
private def neverReceiveResponse(
|
||||
duration: FiniteDuration
|
||||
)(predicate: sbt.internal.protocol.JsonRpcResponseMessage => Boolean): Unit =
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import java.util.concurrent.atomic.AtomicReference
|
|||
|
||||
import testing.{ Event as TEvent, OptionalThrowable, Status as TStatus, TestSelector }
|
||||
import util.{ AbstractLogger, Level, ControlEvent, LogEvent }
|
||||
import sbt.io.IO
|
||||
import sbt.protocol.testing.TestResult
|
||||
import sbt.internal.worker1.ForkTestMain
|
||||
import sbt.io.IO
|
||||
import verify.BasicTestSuite
|
||||
import scala.xml.XML
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ package sbt.util
|
|||
|
||||
import java.io.{ File, IOException }
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.{ Files, Path, Paths, StandardCopyOption }
|
||||
import java.nio.file.{ AtomicMoveNotSupportedException, Files, Path, Paths, StandardCopyOption }
|
||||
import sbt.internal.util.{ ActionCacheEvent, CacheEventLog, StringVirtualFile1 }
|
||||
import sbt.io.syntax.*
|
||||
import sbt.io.IO
|
||||
|
|
@ -82,40 +82,40 @@ object ActionCache:
|
|||
case e: Exception =>
|
||||
cacheEventLog.append(ActionCacheEvent.Error)
|
||||
throw e
|
||||
val json = Converter.toJsonUnsafe(result)
|
||||
val normalizedOutputDir = outputDirectory.toAbsolutePath.normalize()
|
||||
val uncacheableOutputs =
|
||||
outputs.filter(f =>
|
||||
f match
|
||||
case vf if vf.id.endsWith(ActionCache.dirZipExt) =>
|
||||
false
|
||||
case _ =>
|
||||
val outputPath = fileConverter.toPath(f).toAbsolutePath.normalize()
|
||||
!outputPath.startsWith(normalizedOutputDir)
|
||||
)
|
||||
if uncacheableOutputs.nonEmpty then
|
||||
cacheEventLog.append(ActionCacheEvent.Error)
|
||||
logger.error(
|
||||
s"Cannot cache task because its output files are outside the output directory: \n" +
|
||||
uncacheableOutputs.mkString(" - ", "\n - ", "")
|
||||
)
|
||||
result
|
||||
else
|
||||
cacheEventLog.append(ActionCacheEvent.OnsiteTask)
|
||||
val (input, valuePath) = mkInput(key, codeContentHash, extraHash, config.cacheVersion)
|
||||
val valueFile = StringVirtualFile1(valuePath, CompactPrinter(json))
|
||||
val newOutputs = Vector(valueFile) ++ outputs.toVector
|
||||
try
|
||||
try
|
||||
val json = Converter.toJsonUnsafe(result)
|
||||
val normalizedOutputDir = outputDirectory.toAbsolutePath.normalize()
|
||||
val uncacheableOutputs =
|
||||
outputs.filter(f =>
|
||||
f match
|
||||
case vf if vf.id.endsWith(ActionCache.dirZipExt) =>
|
||||
false
|
||||
case _ =>
|
||||
val outputPath = fileConverter.toPath(f).toAbsolutePath.normalize()
|
||||
!outputPath.startsWith(normalizedOutputDir)
|
||||
)
|
||||
if uncacheableOutputs.nonEmpty then
|
||||
cacheEventLog.append(ActionCacheEvent.Error)
|
||||
logger.error(
|
||||
s"Cannot cache task because its output files are outside the output directory: \n" +
|
||||
uncacheableOutputs.mkString(" - ", "\n - ", "")
|
||||
)
|
||||
result
|
||||
else
|
||||
cacheEventLog.append(ActionCacheEvent.OnsiteTask)
|
||||
val (input, valuePath) = mkInput(key, codeContentHash, extraHash, config.cacheVersion)
|
||||
val valueFile = StringVirtualFile1(valuePath, CompactPrinter(json))
|
||||
val newOutputs = Vector(valueFile) ++ outputs.toVector
|
||||
store.put(UpdateActionResultRequest(input, newOutputs, exitCode = 0)) match
|
||||
case Right(cachedResult) =>
|
||||
store.syncBlobs(cachedResult.outputFiles, outputDirectory)
|
||||
result
|
||||
case Left(e) => throw e
|
||||
catch
|
||||
case e: IOException =>
|
||||
logger.debug(s"Skipping cache storage due to error: ${e.getMessage}")
|
||||
cacheEventLog.append(ActionCacheEvent.Error)
|
||||
result
|
||||
catch
|
||||
case e: IOException =>
|
||||
logger.debug(s"Skipping cache storage due to error: ${e.getMessage}")
|
||||
cacheEventLog.append(ActionCacheEvent.Error)
|
||||
result
|
||||
|
||||
// Single cache lookup - use exitCode to distinguish success from failure
|
||||
getWithFailure(key, codeContentHash, extraHash, tags, config) match
|
||||
|
|
@ -270,6 +270,36 @@ object ActionCache:
|
|||
|
||||
private val default2010Timestamp: Long = 1262304000000L
|
||||
|
||||
/**
|
||||
* Publishes `builtZip` as `destZip` by staging next to the destination and renaming into place.
|
||||
* Avoids races from a direct `Files.copy` into `destZip` under parallel task execution.
|
||||
*/
|
||||
private def installPackagedZip(builtZip: Path, destZip: Path, fallbackStagingDir: Path): Unit =
|
||||
val stagingDir = Option(destZip.getParent) match
|
||||
case Some(parent) =>
|
||||
Files.createDirectories(parent)
|
||||
parent
|
||||
case None => fallbackStagingDir
|
||||
|
||||
val staging = Files.createTempFile(
|
||||
stagingDir,
|
||||
destZip.getFileName.toString + ".",
|
||||
dirZipExt + ".tmp",
|
||||
)
|
||||
try
|
||||
Files.copy(builtZip, staging, StandardCopyOption.REPLACE_EXISTING)
|
||||
try
|
||||
Files.move(
|
||||
staging,
|
||||
destZip,
|
||||
StandardCopyOption.REPLACE_EXISTING,
|
||||
StandardCopyOption.ATOMIC_MOVE,
|
||||
)
|
||||
catch
|
||||
case _: AtomicMoveNotSupportedException =>
|
||||
Files.move(staging, destZip, StandardCopyOption.REPLACE_EXISTING)
|
||||
finally Files.deleteIfExists(staging)
|
||||
|
||||
def packageDirectory(
|
||||
dir: VirtualFileRef,
|
||||
conv: FileConverter,
|
||||
|
|
@ -311,7 +341,7 @@ object ActionCache:
|
|||
tempZipPath.toFile(),
|
||||
Some(default2010Timestamp)
|
||||
)
|
||||
Files.copy(tempZipPath, zipPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
installPackagedZip(tempZipPath, zipPath, tempDir.toPath())
|
||||
|
||||
conv.toVirtualFile(zipPath)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
package sbt.util
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.{ Files, Path, Paths }
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.{ CyclicBarrier, ExecutorService, Executors, TimeUnit }
|
||||
|
||||
import sbt.internal.util.CacheEventLog
|
||||
import sbt.internal.util.StringVirtualFile1
|
||||
import sbt.io.IO
|
||||
|
|
@ -7,18 +12,15 @@ import sbt.io.syntax.*
|
|||
import verify.BasicTestSuite
|
||||
import xsbti.{
|
||||
CompileFailed,
|
||||
FileConverter,
|
||||
HashedVirtualFileRef,
|
||||
Problem,
|
||||
Position,
|
||||
Severity,
|
||||
VirtualFile,
|
||||
FileConverter,
|
||||
VirtualFileRef
|
||||
VirtualFileRef,
|
||||
}
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.Files
|
||||
import java.util.Optional
|
||||
|
||||
import ActionCache.InternalActionResult
|
||||
|
||||
object ActionCacheTest extends BasicTestSuite:
|
||||
|
|
@ -259,6 +261,36 @@ object ActionCacheTest extends BasicTestSuite:
|
|||
assert(v2 == 42)
|
||||
assert(called == 2)
|
||||
|
||||
test("packageDirectory is safe when many threads package the same directory concurrently"):
|
||||
IO.withTemporaryDirectory: tmp =>
|
||||
val root = tmp.toPath
|
||||
val classesDir = root.resolve("classes")
|
||||
Files.createDirectories(classesDir)
|
||||
Files.writeString(classesDir.resolve("A.class"), "compiled")
|
||||
val classesPathStr = classesDir.toString
|
||||
val dirRef = VirtualFileRef.of(classesPathStr)
|
||||
val conv = new FileConverter:
|
||||
override def toPath(ref: VirtualFileRef): Path = Paths.get(ref.id)
|
||||
override def toVirtualFile(path: Path): VirtualFile =
|
||||
val content =
|
||||
if Files.isRegularFile(path) then
|
||||
new String(Files.readAllBytes(path), StandardCharsets.UTF_8)
|
||||
else ""
|
||||
StringVirtualFile1(path.toString, content)
|
||||
val threadCount = 64
|
||||
val barrier = new CyclicBarrier(threadCount)
|
||||
val pool: ExecutorService = Executors.newFixedThreadPool(threadCount)
|
||||
try
|
||||
val tasks =
|
||||
for _ <- 1 to threadCount yield pool.submit: () =>
|
||||
barrier.await(30, TimeUnit.SECONDS)
|
||||
ActionCache.packageDirectory(dirRef, conv, root)
|
||||
tasks.foreach(_.get(60, TimeUnit.SECONDS))
|
||||
val zipPath = Paths.get(classesPathStr + ActionCache.dirZipExt)
|
||||
assert(Files.isRegularFile(zipPath))
|
||||
assert(Files.size(zipPath) > 0L)
|
||||
finally pool.shutdown()
|
||||
|
||||
test("Changing cacheVersion invalidates the cache"):
|
||||
withDiskCache(testCacheVersionInvalidation)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue