aboutsummaryrefslogblamecommitdiff
path: root/project/LocalPlugin.scala
blob: 61da0b664f0d7af9cf72b08c76d1347ee744d8bb (plain) (tree)





























































































































                                                                             
import java.nio.file.attribute.PosixFilePermissions
import java.nio.file.{Files, StandardCopyOption}
import sbt.Keys._
import sbt.{Def, _}
import sbtassembly.AssemblyPlugin

object LocalPlugin extends AutoPlugin {

  override def requires = plugins.JvmPlugin && AssemblyPlugin
  override def trigger = allRequirements

  object autoImport {
    val dbMigrate = taskKey[File]("Apply sqitch database migrations")
    val dbTables = taskKey[Seq[File]]("Generate database tables")
    val fhsDist = taskKey[File](
      "Copy application  to a directory structure according to the " +
        "Filesystem Hierarchy Standard, simplifying further packaging for " +
        "final platforms such as Debian or Docker.")
  }
  import autoImport._

  override def projectSettings: Seq[Def.Setting[_]] = Seq(
    scalacOptions ++= Seq("-deprecation", "-feature"),
    libraryDependencies ++= Seq(
      "com.typesafe.slick" %% "slick" % "3.2.3",
      "com.typesafe.slick" %% "slick-codegen" % "3.2.3",
      "org.slf4j" % "slf4j-nop" % "1.7.19",
      "org.xerial" % "sqlite-jdbc" % "3.25.2"
    ),
    dbMigrate := {
      import sys.process._
      val dbFile = target.value / "main.db"
      val cmd = s"sqitch deploy db:sqlite:${dbFile.getPath}"
      val status = cmd.run().exitValue()
      if (status != 0) {
        throw new MessageOnlyException(s"command '$cmd' exited with $status")
      }
      dbFile
    },
    dbTables := {
      val dbUrl = s"jdbc:sqlite:${dbMigrate.value.toPath}"
      val out = (scalaSource in Compile).value
      (runner in Compile).value.run(
        "slick.codegen.SourceCodeGenerator",
        (dependencyClasspath in Compile).value.files,
        Array(
          "slick.jdbc.SQLiteProfile", // slick driver
          "org.sqlite.JDBC", // JDBC driver
          dbUrl, // database connection
          out.toString, // file
          "byspel" // package
        ),
        streams.value.log
      )
      Seq(out / "Tables.scala")
    },
    fhsDist := {
      val root = (target in Compile).value / "dist"
      Files.createDirectories((root / "etc").toPath)
      Files.createDirectories((root / "usr" / "bin").toPath)
      Files.createDirectories((root / "usr" / "share" / "byspel").toPath)
      Files.createDirectories((root / "usr" / "lib" / "byspel").toPath)
      Files.createDirectories((root / "var" / "lib" / "byspel").toPath)
      Files.copy(
        AssemblyPlugin.autoImport.assembly.value.toPath,
        (root / "usr" / "share" / "byspel" / "main.jar").toPath,
        StandardCopyOption.REPLACE_EXISTING
      )
      Files.writeString(
        (root / "etc" / "byspel.toml").toPath,
        """|[http]
           |address = "0.0.0.0"
           |port = 8555
           |
           |[database]
           |file = "/var/lib/byspel/main.db"
           |sqitch_base = "/usr/share/byspel/sqitch"
           |""".stripMargin
      )
      import sys.process._
      require(
        s"sqitch bundle --dest-dir=$root/usr/share/byspel/sqitch"
          .run()
          .exitValue() == 0,
        "error bundling sqitch"
      )
      require(
        Process(
          Seq(
            "cc",
            "-g",
            "-O2",
            "-Wall",
            "-Werror",
            "-fPIC",
            "-shared",
            "-o",
            s"$root/usr/lib/byspel/libprocname.so",
            "launcher/procname.c"
          )
        ).run().exitValue() == 0,
        "error compiling launcher"
      )

      val exec = (root / "usr" / "bin" / "byspel").toPath
      Files.writeString(
        exec,
        s"""|#!/bin/bash
            |export LD_PRELOAD=/usr/lib/byspel/libprocname.so
            |export PROCNAME="byspel"
            |exec java -cp /usr/share/byspel/main.jar byspel.Main "$$@"
            |""".stripMargin
      )
      Files.setPosixFilePermissions(
        exec,
        PosixFilePermissions.fromString("rwxr-xr-x")
      )
      root
    }
  )

  override def buildSettings: Seq[Def.Setting[_]] =
    addCommandAlias("start", "reStart dev.toml") ++
      addCommandAlias("stop", "reStop")

}