Skip to content

Commit

Permalink
[WIP] Cross-build for sbt 2.0.0-M2
Browse files Browse the repository at this point in the history
  • Loading branch information
earldouglas committed Oct 15, 2024
1 parent 92d762a commit 29a3e8e
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 41 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Create a staging release in Sonatype:
$ nix-shell
$ sbt
> set version := "4.2.5"
> publishSigned
> +publishSigned
```

Review it:
Expand Down
17 changes: 14 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ name := "sbt-war"
organization := "com.earldouglas"
sbtPlugin := true
scalacOptions ++= Seq("-feature", "-deprecation")
scalaVersion := "2.12.18" // https://scalameta.org/metals/blog/2023/07/19/silver#support-for-scala-21218
scalaVersion := "2.12.20"
crossScalaVersions += "3.3.4"
pluginCrossBuild / sbtVersion := {
scalaBinaryVersion.value match {
case "2.12" => (pluginCrossBuild / sbtVersion).value
case _ => "2.0.0-M2"
}
}

// scripted-plugin
scriptedBufferLog := false
Expand All @@ -17,8 +24,12 @@ scriptedParallelInstances := 8
// Scalafix
semanticdbEnabled := true
semanticdbVersion := scalafixSemanticdb.revision
scalacOptions += "-Ywarn-unused-import"
scalacOptions += s"-P:semanticdb:sourceroot:${baseDirectory.value}"
scalacOptions ++= {
scalaBinaryVersion.value match {
case "2.12" => Seq("-Ywarn-unused-import")
case _ => Seq.empty // ("-Wunused:imports")
}
}

// webapp-components-runner
lazy val warRunnerVersion =
Expand Down
35 changes: 35 additions & 0 deletions src/main/scala-2.12/com/earldouglas/sbt/war/Compat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.earldouglas.sbt.war

import sbt.Def.Initialize
import sbt.Keys._
import sbt.Keys.{`package` => pkg}
import sbt._

import java.io.{File => JavaFile}

object Compat {

val Compile_pkg_artifact = Compile / pkg / artifact
val Compile_sourceDirectory = Compile / sourceDirectory
val Compile_target = Compile / target
val Global_onLoad = Global / onLoad
val pkg_artifact = pkg / artifact

val warContents: Initialize[Task[Map[String, JavaFile]]] =
WebappComponentsPlugin.warContents

def managedJars(config: Configuration): Initialize[Task[Seq[File]]] =
Def.task {
Classpaths
.managedJars(config, classpathTypes.value, update.value)
.map(_.data)
.toSeq
}

def toFile(file: TaskKey[File]): Initialize[Task[File]] =
file

val classpathFiles: Initialize[Task[Seq[File]]] =
(Runtime / fullClasspath)
.map(_.files)
}
51 changes: 51 additions & 0 deletions src/main/scala-3/com/earldouglas/sbt/war/Compat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.earldouglas.sbt.war

import sbt.Def.Initialize
import sbt.Keys._
import sbt.Keys.{`package` => pkg}
import sbt._
import sbt.given

import java.io.{File => JavaFile}

import scala.language.implicitConversions

object Compat:

val Compile_pkg_artifact = Compile / pkg / artifact
val Compile_sourceDirectory = Compile / sourceDirectory
val Compile_target = Compile / target
val Global_onLoad = Global / onLoad
val pkg_artifact = pkg / artifact

val warContents: Initialize[Task[Map[String, HashedVirtualFileRef]]] =
Def.task:
val conv: FileConverter = fileConverter.value
WebappComponentsPlugin
.warContents
.value
.map:
case (dst, src) => dst -> conv.toVirtualFile(src.toPath())

def managedJars(config: Configuration): Initialize[Task[Seq[File]]] =
Def.task:
Classpaths
.managedJars(config, classpathTypes.value, update.value, fileConverter.value)
.map(_.data)
.map(fileConverter.value.toPath(_))
.map(_.toFile())
.toList

def toFile(file: TaskKey[HashedVirtualFileRef]): Initialize[Task[File]] =
Def.task:
fileConverter.value
.toPath(file.value)
.toFile()

val classpathFiles: Initialize[Task[Seq[File]]] =
Def.task:
(Runtime / fullClasspath)
.value
.map(_.data)
.map(fileConverter.value.toPath(_))
.map(_.toFile())
26 changes: 11 additions & 15 deletions src/main/scala/com/earldouglas/sbt/war/SbtWar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,7 @@ object SbtWar extends AutoPlugin {
}

val runnerJars: Initialize[Task[Seq[File]]] =
Def.task {
Classpaths
.managedJars(War, classpathTypes.value, update.value)
.map(_.data)
.toList
}
Compat.managedJars(War)

val startWar: Initialize[Task[Unit]] =
Def.task {
Expand All @@ -74,7 +69,10 @@ object SbtWar extends AutoPlugin {
"webapp.runner.launch.Main",
"--port",
warPort.value.toString(),
pkg.value.getPath()
Compat
.toFile(pkg)
.value
.getPath()
)
)
containerInstance.set(Some(process))
Expand All @@ -88,10 +86,8 @@ object SbtWar extends AutoPlugin {

val onLoadSetting: Initialize[State => State] =
Def.setting {
(Global / onLoad).value
.compose { state: State =>
state.addExitHook(stopContainerInstance(println(_)))
}
Compat.Global_onLoad.value
.compose(_.addExitHook(stopContainerInstance(println(_))))
}

val forkOptions: Initialize[Task[ForkOptions]] =
Expand All @@ -112,17 +108,17 @@ object SbtWar extends AutoPlugin {

val runnerConfigFile: File = {

val emptyDir: File = (Compile / target).value / "empty"
val emptyDir: File = (Compat.Compile_target).value / "empty"

val resourceMapString =
WebappComponentsPlugin.warContents.value
Compat.warContents.value
.map { case (k, v) =>
s"${k}->${v}"
}
.mkString(",")

val configurationFile: File =
(Compile / target).value / "webapp-components.properties"
(Compat.Compile_target).value / "webapp-components.properties"

Files
.writeString(
Expand Down Expand Up @@ -155,7 +151,7 @@ object SbtWar extends AutoPlugin {
}

Seq(
Global / onLoad := onLoadSetting.value,
Compat.Global_onLoad := onLoadSetting.value,
libraryDependencies ++= runnerLibraries.value,
warForkOptions := forkOptions.value,
warJoin := joinWar.value,
Expand Down
9 changes: 3 additions & 6 deletions src/main/scala/com/earldouglas/sbt/war/WarPackagePlugin.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package com.earldouglas.sbt.war

import sbt.Def.Initialize
import sbt.Keys.artifact
import sbt.Keys.moduleName
import sbt.Keys.{`package` => pkg}
Expand All @@ -21,9 +19,8 @@ object WarPackagePlugin extends AutoPlugin {
override lazy val projectSettings: Seq[Setting[_]] = {

// Flip warContents around from (dst -> src) to (src -> dst)
val packageContents: Initialize[Task[Seq[(java.io.File, String)]]] =
WebappComponentsPlugin.warContents
.map(_.map(_.swap).toSeq)
val packageContents =
Compat.warContents.map(_.map(_.swap).toSeq)

val packageTaskSettings: Seq[Setting[_]] =
Defaults.packageTaskSettings(pkg, packageContents)
Expand All @@ -32,7 +29,7 @@ object WarPackagePlugin extends AutoPlugin {
pkg / artifact := Artifact(moduleName.value, "war", "war")

val artifactSettings: Seq[Setting[_]] =
addArtifact(Compile / pkg / artifact, pkg)
addArtifact(Compat.Compile_pkg_artifact, pkg)

Seq(
packageTaskSettings,
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/com/earldouglas/sbt/war/WebappComponents.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ object WebappComponents {
* a mapping from destination to source of webapp resources
*/
def getResources(resourcesDir: File): Map[String, File] = {
(resourcesDir ** "*").get
(resourcesDir ** "*")
.get()
.filter(_.exists())
.filter(_.isFile())
.flatMap(file =>
Expand All @@ -47,7 +48,7 @@ object WebappComponents {
val classesMappings: Seq[(String, File)] =
for {
classpathDir <- classpathDirs
classFile <- (classpathDir ** "*").get
classFile <- (classpathDir ** "*").get()
if classFile.exists()
if classFile.isFile()
relativeFile <- IO.relativizeFile(classpathDir, classFile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.earldouglas.sbt.war

import sbt.Def.Initialize
import sbt.Def.taskKey
import sbt.Keys._
import sbt._

/** Identifies the files that compose the webapp (resources, .class
Expand Down Expand Up @@ -52,19 +51,17 @@ object WebappComponentsPlugin extends AutoPlugin {
override val projectSettings: Seq[Setting[_]] = {

val warResourcesTask: Initialize[Task[Map[String, File]]] =
(Compile / sourceDirectory)
(Compat.Compile_sourceDirectory)
.map(_ / "webapp")
.map(WebappComponents.getResources)

val warClassesTask: Initialize[Task[Map[String, File]]] =
(Runtime / fullClasspath)
.map(_.files)
.map(WebappComponents.getClasses)
Compat.classpathFiles
.map(WebappComponents.getClasses(_))

val warLibTask: Initialize[Task[Map[String, File]]] =
(Runtime / fullClasspath)
.map(_.files)
.map(WebappComponents.getLib)
Compat.classpathFiles
.map(WebappComponents.getLib(_))

Seq(
warResources := warResourcesTask.value,
Expand Down
13 changes: 13 additions & 0 deletions src/test/scala-2/com/earldouglas/sbt/war/TestCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.earldouglas.sbt.war
import java.util.{List => JavaList}
import java.util.{Map => JavaMap}
import scala.collection.JavaConverters._

object TestCompat {

def asScala[A, B](javaMap: JavaMap[A, B]): Map[A, B] =
javaMap.asScala.toMap

def asScala[A](javaList: JavaList[A]): List[A] =
javaList.asScala.toList
}
20 changes: 20 additions & 0 deletions src/test/scala-3/com/earldouglas/sbt/war/TestCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.earldouglas.sbt.war

import java.net.HttpURLConnection
import java.net.URI
import scala.jdk.CollectionConverters._
import scala.io.Source
import java.util.{List => JavaList}
import java.util.{Map => JavaMap}

object TestCompat:

def asScala[A, B](javaMap: JavaMap[A, B]): Map[A, B] =
javaMap
.asScala
.toMap

def asScala[A](javaList: JavaList[A]): List[A] =
javaList
.asScala
.toList
14 changes: 8 additions & 6 deletions src/test/scala/com/earldouglas/sbt/war/HttpClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ object HttpClient {
val response =
Response(
status = c.getResponseCode(),
headers = c
.getHeaderFields()
.asScala
.filter({ case (k, _) => k != null })
.map({ case (k, v) => (k, v.asScala.mkString(",")) })
.toMap - "Date" - "Content-Length" - "Server",
headers =
TestCompat
.asScala(c.getHeaderFields())
.filter({ case (k, _) => k != null })
.map({ case (k, v) =>
(k, TestCompat.asScala(v).mkString(","))
})
.toMap - "Date" - "Content-Length" - "Server",
body = Source.fromInputStream {
if (c.getResponseCode() < 400) {
c.getInputStream
Expand Down

0 comments on commit 29a3e8e

Please sign in to comment.