Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade sbt riddl #446

Merged
merged 7 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
package com.reactific.riddl.sbt.plugin

import com.reactific.riddl.sbt.SbtRiddlPluginBuildInfo
import com.reactific.riddl.sbt.plugin.RiddlSbtPlugin.V
import sbt.{Def, *}
import sbt.*
import sbt.Keys.*
import sbt.internal.util.ManagedLogger
import sbt.plugins.JvmPlugin

import java.io.File
import java.nio.file.FileSystem
import scala.language.postfixOps
import scala.sys.process.*

Expand All @@ -21,7 +23,7 @@ object RiddlSbtPlugin extends AutoPlugin {

object autoImport {

lazy val riddlcPath = settingKey[File]("Path to `riddlc` compiler")
lazy val riddlcPath = settingKey[Option[File]]("Optional path to riddlc").withRank(KeyRanks.Invisible)

lazy val riddlcConf = settingKey[File]("Path to the config file")

Expand All @@ -30,37 +32,11 @@ object RiddlSbtPlugin extends AutoPlugin {
lazy val riddlcMinVersion = {
settingKey[String]("Ensure the riddlc used is at least this version")
}
}

import autoImport.*

lazy val compileTask = taskKey[Unit]("A task to invoke riddlc compiler")
lazy val infoTask = taskKey[Unit]("A task to invoke riddlc info command")

// Allow riddlc to be run from inside an sbt shell
def riddlcCommand = Command.args(
name = "riddlc",
display = "<options> <command> <args...> ; `riddlc help` for details"
) { (state, args) =>
val project = Project.extract(state)
val path = project.get(riddlcPath)
val minVersion = project.get(riddlcMinVersion)
runRiddlc(path, args, minVersion)
state
lazy val findRiddlcTask = taskKey[File]("Find the riddlc program locally")
}

def infoCommand = Command.args(
name = "info",
display = "prints out riddlc info"
) { (state, _) =>
val project = Project.extract(state)
val path = project.get(riddlcPath)
val minVersion = project.get(riddlcMinVersion)
val options = Seq("info")
runRiddlc(path, options, minVersion)
state

}
import autoImport.*

object V {
val scala = "3.3.1" // NOTE: Synchronize with Helpers.C.withScala3
Expand All @@ -69,7 +45,14 @@ object RiddlSbtPlugin extends AutoPlugin {
val riddl: String = SbtRiddlPluginBuildInfo.version
}

/*private def getLogger(project: Extracted, state: State): ManagedLogger = {
val (_, strms) = project.runTask(, state)
project.structure.streams(state).log
strms.log
}*/

override def projectSettings: Seq[Setting[_]] = Seq(
// Global / excludeLintKeys ++= Seq(riddlcConf, riddlcOptions),
scalaVersion := V.scala,
libraryDependencies ++= Seq(
"com.reactific" %% "riddlc" % V.riddl,
Expand All @@ -79,34 +62,97 @@ object RiddlSbtPlugin extends AutoPlugin {
"org.scalacheck" %% "scalacheck" % V.scalacheck % Test
),
Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaLibrary,
riddlcPath := file("riddlc"),
riddlcPath := None,
riddlcOptions := Seq("--show-times"),
riddlcConf := file("src/main/riddl/riddlc.conf"),
riddlcOptions := Seq("--show-times", "--hide-warnings"),
riddlcMinVersion := SbtRiddlPluginBuildInfo.version,
compileTask := {
val execPath = riddlcPath.value
val conf = riddlcConf.value.getAbsoluteFile.toString
val options = riddlcOptions.value
val version = riddlcMinVersion.value
val args = options ++ Seq("from", conf, "validate")
runRiddlc(execPath, args, version)
},
infoTask := {
val execPath = riddlcPath.value
val options = Seq("info")
val version = riddlcMinVersion.value
runRiddlc(execPath, options, version)
},
commands ++= Seq(riddlcCommand),
Compile / compile := Def.taskDyn {
val c = (Compile / compile).value
Def.task {
val _ = (Compile / compileTask).value
c
findRiddlcTask := {
val found: File = riddlcPath.value match {
case Some(path) =>
if (path.getAbsolutePath.endsWith("riddlc")) path else {
throw new IllegalStateException(s"Your riddlcPath setting is not the full path to the riddlc program ")
}
case None =>
val riddlc_path = System.getenv("RIDDLC_PATH")
if (riddlc_path.contains("riddlc")) {
new File(riddlc_path)
} else {
val user_path = System.getenv("PATH")
// FIXME: Won't work on Windoze, make it work
val parts = user_path.split(":")
val with_riddlc = parts.map { part: String =>
if (part.contains("riddlc")) part else part + "/riddlc"
}
with_riddlc.find { (potential: String) =>
Path(potential).exists
} match {
case Some(found) =>
new File(found)
case None =>
throw new IllegalStateException(
"Can't find the 'riddlc' program in your path. Please install.\n" +
parts.mkString("\n")
)
}
}
}
if (!found.exists) {
throw new IllegalStateException(s"riddlc in PATH environment var, but executable not found: $found")
}
}.value
found
},
commands ++= Seq(riddlcCommand, infoCommand, hugoCommand, validateCommand, statsCommand)
)

private def runRiddlcAction(state: State, args: Seq[String]): (State, Int) = {
val project = Project.extract(state)
val riddlcPath = project.runTask(findRiddlcTask, state)
val minimumVersion: String = project.get(riddlcMinVersion)
val options: Seq[String] = project.get(riddlcOptions)
val rc = runRiddlc(riddlcPath._2, minimumVersion, options, args)
state -> rc
}

// Allow riddlc to be run from inside an sbt shell
private def riddlcCommand: Command = {
Command.args(
name = "riddlc",
display = "<options> <command> <args...> ; `riddlc help` for details"
) { (state: State, args: Seq[String]) =>
runRiddlcAction(state, args)._1
}
}

def infoCommand: Command = {
Command.command("info") { (state: State) =>
runRiddlcAction(state, Seq("info"))._1
}
}

def hugoCommand: Command = {
Command.command("hugo") { (state: State) =>
val project = Project.extract(state)
val conf = project.get(riddlcConf).getAbsoluteFile.toString
runRiddlcAction(state, Seq("from", conf, "hugo"))._1
}
}

def validateCommand: Command = {
Command.command("validate") { (state: State) =>
val project = Project.extract(state)
val conf = project.get(riddlcConf).getAbsoluteFile.toString
runRiddlcAction(state, Seq("from", conf, "validate"))._1
}
}

def statsCommand: Command = {
Command.command("stats") { (state: State) =>
val project = Project.extract(state)
val conf = project.get(riddlcConf).getAbsoluteFile.toString
runRiddlcAction(state, Seq("from", conf, "stats"))._1
}
}

private def versionTriple(version: String): (Int, Int, Int) = {
val trimmed = version.indexOf('-') match {
case x: Int if x < 0 => version
Expand All @@ -129,30 +175,33 @@ object RiddlSbtPlugin extends AutoPlugin {
}

private def checkVersion(
riddlc: sbt.File,
riddlcPath: File,
minimumVersion: String
): Unit = {
import scala.sys.process.*
val check = riddlc.toString + " version"
val check = riddlcPath.getAbsolutePath + " version"
val actualVersion = check.!!<.trim
val minVersion = minimumVersion.trim
if (!versionSameOrLater(actualVersion, minVersion)) {
throw new IllegalArgumentException(
s"riddlc version $actualVersion is below minimum required: $minVersion"
)
} else { println(s"riddlc version = $actualVersion") }
} // else { println(s"riddlc version = $actualVersion") }
}

private def runRiddlc(
riddlc: sbt.File,
args: Seq[String],
minimumVersion: String
): Unit = {
checkVersion(riddlc, minimumVersion)
val command = riddlc.toString + " " + args.mkString(" ")
// streams: TaskStreams,
riddlcPath: File,
minimumVersion: String,
options: Seq[String],
args: Seq[String]
): Int = {
checkVersion(riddlcPath, minimumVersion)
// streams.log.info(s"Running: riddlc ${args.mkString(" ")}\n")
// println(s"Running: riddlc ${args.mkString(" ")}\n")
// FIXME: use sbt I/O
val logger = ProcessLogger(println(_))
println(s"RIDDLC: $command")
val rc = command.!(logger)
logger.out(s"RC=$rc")
val process = Process(riddlcPath.getAbsolutePath, options ++ args)
process.!(logger)
}
}
50 changes: 2 additions & 48 deletions sbt-riddl/src/sbt-test/sbt-riddl/simple/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,6 @@ lazy val root = (project in file("."))
.enablePlugins(RiddlSbtPlugin)
.settings(
version := "0.1",
riddlcOptions := Seq.empty[String],
riddlcConf := file("src/main/riddl/riddlc.conf"),
riddlcPath := file("/Users/reid/Code/reactific/riddl/riddlc/target/universal/stage/bin/riddlc"),
TaskKey[String]("checkInfoOutput") := {
val which_cmd = Process("/bin/zsh", Seq("-c", "which riddlc"))
val riddlc_path: String = {
val which_out = (which_cmd.lineStream_!).toSeq.mkString.trim
if (!which_out.startsWith("/")) {
"/Users/reid/Code/reactific/riddl/riddlc/target/universal/stage/bin/riddlc"
} else {
which_out
}
}
println(s"RIDDLC path is: $riddlc_path")
if (!riddlc_path.contains("riddlc")) {
sys.error(s"which command didn't return riddlc path but:\n$riddlc_path")
}
val args = Seq("--verbose", "info")
val p1 = Process(riddlc_path, args)
val out1 = (p1 !!).trim
println(out1)
if (!out1.contains("name: riddlc")) {
sys.error(s"wrong output from 'riddlc info' command:\n$out1")
}
val plugin_version = sys.props.get("plugin.version").getOrElse("0")
if (!out1.contains(s"version: ")) {
sys.error(s"output should contain 'version: $plugin_version")
}
val v = Seq(
"--verbose",
"--suppress-missing-warnings",
"from",
"src/main/riddl/riddlc.conf",
"validate"
)
val p2 = Process(riddlc_path, v)
val out2 = (p2 !!).trim
println(out2)
if (
!out2
.contains("Ran: from src/main/riddl/riddlc.conf validate: success=yes")
) {
sys.error(
"riddlc output did not contain 'Ran: from riddlc.conf validate: success=yes'"
)
}
riddlc_path
}
riddlcOptions := Seq("--show-times", "--verbose"),
riddlcConf := file("src/main/riddl/riddlc.conf")
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ class GenerateTestSiteSpec extends RunCommandSpecBase {
"validate RIDDL and generate Hugo" in {
val command = Array(
"--show-times",
"--suppress-style-warnings",
"--suppress-missing-warnings",
"--verbose",
"from",
"src/main/riddl/riddl.conf",
"hugo"
"validate"
)
runWith(command)
}
Expand Down
16 changes: 8 additions & 8 deletions sbt-riddl/src/sbt-test/sbt-riddl/simple/test
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Put in sbt-test scripted checks in this file
# See: https://www.scala-sbt.org/1.x/docs/Testing-sbt-plugins.html for options

# Check for basic sanity with info output
> checkInfoOutput

# now try the compile command
> compile
# See if the minimal info command works
> info

# Try a simple riddlc command
# Try that with the riddlc command
> riddlc info

# And we support a short form of that too
> info
# now try the validate command
> validate

# now try the stats command
> stats

# Compile the test code
> Test/compile
Expand Down
Loading