aboutsummaryrefslogtreecommitdiff
path: root/project/LocalPlugin.scala
blob: 61da0b664f0d7af9cf72b08c76d1347ee744d8bb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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")

}