-
Notifications
You must be signed in to change notification settings - Fork 88
/
Plugin.scala
103 lines (93 loc) · 3.6 KB
/
Plugin.scala
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
package sbtbuildinfo
import sbt._
object Plugin extends sbt.Plugin {
import Keys._
import Project.Initialize
lazy val buildInfo = TaskKey[Seq[File]]("buildinfo")
lazy val buildInfoObject = SettingKey[String]("buildinfo-object")
lazy val buildInfoPackage = SettingKey[String]("buildinfo-package")
lazy val buildInfoKeys = SettingKey[Seq[Scoped]]("buildinfo-keys")
lazy val buildInfoBuildNumber = TaskKey[Int]("buildinfo-buildnumber")
case class BuildInfo(dir: File, obj: String, pkg: String, keys: Seq[Scoped],
proj: ProjectRef, state0: State) {
private var _state: State = state0
private def extracted = Project.extract(_state)
def file: File = {
val f = dir / ("%s.scala" format obj)
val lines =
List("package %s" format pkg,
"",
"object %s {" format obj) :::
(keys.toList.distinct map { line(_) }).flatten :::
List("}")
IO.write(f, lines.mkString("\n"))
f
}
private def line(key: Scoped): Option[String] =
value(key) map { x => " val %s = %s" format (ident(key), quote(x)) }
private def value(scoped: Scoped): Option[Any] = {
val scope = if (scoped.scope.project == This) scoped.scope in (proj)
else scoped.scope
scoped match {
case key: SettingKey[_] => extracted getOpt (key in scope)
case key: TaskKey[_] =>
val (s, x) = extracted runTask (key in scope, _state)
Some(x)
case _ => None
}
}
private def ident(key: Scoped): String =
(key.scope.config.toOption match {
case None => ""
case Some(ConfigKey("compile")) => ""
case Some(ConfigKey(x)) => x + "_"
}) +
(key.scope.task.toOption match {
case None => ""
case Some(x) => x.label + "_"
}) +
(key.key.label.split("-").toList match {
case Nil => ""
case x :: xs => x + (xs map {_.capitalize}).mkString("")
})
private def quote(v: Any): String = v match {
case x: Int => x.toString
case x: Long => x.toString + "L"
case x: Double => x.toString
case x: Boolean => x.toString
case node: scala.xml.NodeSeq => node.toString
case (k, v) => "(%s -> %s)" format(quote(k), quote(v))
case mp: Map[_, _] => mp.toList.map(quote(_)).mkString("Map(", ", ", ")")
case seq: Seq[_] => seq.map(quote(_)).mkString("Seq(", ", ", ")")
case op: Option[_] => op map { x => "Some(" + quote(x) + ")" } getOrElse {"None"}
case s => "\"%s\"" format s.toString
}
}
private[this] def buildNumberTask(dir: File): Int = {
val file: File = dir / "buildinfo.properties"
val prop = new java.util.Properties
def readProp: Int = {
prop.load(new java.io.FileInputStream(file))
prop.getProperty("buildnumber", "0").toInt
}
def writeProp(value: Int) {
prop.setProperty("buildnumber", value.toString)
prop.store(new java.io.FileOutputStream(file), null)
}
val current = if (file.exists) readProp
else 0
writeProp(current + 1)
current
}
lazy val buildInfoSettings: Seq[Project.Setting[_]] = Seq(
buildInfo <<= (sourceManaged in Compile,
buildInfoObject, buildInfoPackage, buildInfoKeys, thisProjectRef, state) map {
(dir, obj, pkg, keys, ref, state) =>
Seq(BuildInfo(dir, obj, pkg, keys, ref, state).file)
},
buildInfoObject := "BuildInfo",
buildInfoPackage := "buildinfo",
buildInfoKeys := Seq[Scoped](name, version, scalaVersion, sbtVersion),
buildInfoBuildNumber <<= (baseDirectory) map { (dir) => buildNumberTask(dir) }
)
}