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") }