-
Notifications
You must be signed in to change notification settings - Fork 929
/
ScriptedPlugin.scala
128 lines (113 loc) · 5.38 KB
/
ScriptedPlugin.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* sbt -- Simple Build Tool
* Copyright 2011 Artyom Olshevskiy
*/
package sbt
import Def.Initialize
import Keys._
import complete.{ Parser, DefaultParsers }
import classpath.ClasspathUtilities
import java.lang.reflect.{ InvocationTargetException, Method }
import java.util.Properties
import CrossVersion.partialVersion
object ScriptedPlugin extends Plugin {
def scriptedConf = config("scripted-sbt") hide
def scriptedLaunchConf = config("scripted-sbt-launch") hide
val scriptedSbt = SettingKey[String]("scripted-sbt")
val sbtLauncher = TaskKey[File]("sbt-launcher")
val sbtTestDirectory = SettingKey[File]("sbt-test-directory")
val scriptedBufferLog = SettingKey[Boolean]("scripted-buffer-log")
val scriptedClasspath = TaskKey[PathFinder]("scripted-classpath")
val scriptedTests = TaskKey[AnyRef]("scripted-tests")
val scriptedRun = TaskKey[Method]("scripted-run")
val scriptedLaunchOpts = SettingKey[Seq[String]]("scripted-launch-opts", "options to pass to jvm launching scripted tasks")
val scriptedDependencies = TaskKey[Unit]("scripted-dependencies")
val scripted = InputKey[Unit]("scripted")
def scriptedTestsTask: Initialize[Task[AnyRef]] = (scriptedClasspath, scalaInstance) map {
(classpath, scala) =>
val loader = ClasspathUtilities.toLoader(classpath, scala.loader)
ModuleUtilities.getObject("sbt.test.ScriptedTests", loader)
}
def scriptedRunTask: Initialize[Task[Method]] = (scriptedTests) map {
(m) =>
m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[Array[String]], classOf[File], classOf[Array[String]])
}
import DefaultParsers._
case class ScriptedTestPage(page: Int, total: Int)
private[sbt] def scriptedParser(scriptedBase: File): Parser[Seq[String]] =
{
val scriptedFiles: NameFilter = ("test": NameFilter) | "pending"
val pairs = (scriptedBase * AllPassFilter * AllPassFilter * scriptedFiles).get map { (f: File) =>
val p = f.getParentFile
(p.getParentFile.getName, p.getName)
}
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet);
val id = charClass(c => !c.isWhitespace && c != '/').+.string
val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/')
// A parser for page definitions
val pageP: Parser[ScriptedTestPage] = ("*" ~ NatBasic ~ "of" ~ NatBasic) map {
case _ ~ page ~ _ ~ total => ScriptedTestPage(page, total)
}
// Grabs the filenames from a given test group in the current page definition.
def pagedFilenames(group: String, page: ScriptedTestPage): Seq[String] = {
val files = pairMap(group).toSeq.sortBy(_.toLowerCase)
val pageSize = files.size / page.total
// The last page may loose some values, so we explicitly keep them
val dropped = files.drop(pageSize * (page.page - 1))
if (page.page == page.total) dropped
else dropped.take(pageSize)
}
def nameP(group: String) = {
token("*".id | id.examples(pairMap(group)))
}
val PagedIds: Parser[Seq[String]] =
for {
group <- groupP
page <- pageP
files = pagedFilenames(group, page)
// TODO - Fail the parser if we don't have enough files for the given page size
//if !files.isEmpty
} yield files map (f => group + '/' + f)
val testID = (for (group <- groupP; name <- nameP(group)) yield (group, name))
val testIdAsGroup = matched(testID) map (test => Seq(test))
//(token(Space) ~> matched(testID)).*
(token(Space) ~> (PagedIds | testIdAsGroup)).* map (_.flatten)
}
def scriptedTask: Initialize[InputTask[Unit]] = Def.inputTask {
val args = scriptedParser(sbtTestDirectory.value).parsed
val prereq: Unit = scriptedDependencies.value
try {
scriptedRun.value.invoke(
scriptedTests.value, sbtTestDirectory.value, scriptedBufferLog.value: java.lang.Boolean,
args.toArray, sbtLauncher.value, scriptedLaunchOpts.value.toArray)
} catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
}
val scriptedSettings = Seq(
ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf),
scriptedSbt := (sbtVersion in pluginCrossBuild).value,
sbtLauncher := getJars(scriptedLaunchConf).value.get.head,
sbtTestDirectory := sourceDirectory.value / "sbt-test",
libraryDependencies ++= (partialVersion(scriptedSbt.value) match {
case Some((0, 13)) =>
Seq(
"org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
)
case Some((1, _)) =>
Seq(
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
)
}),
scriptedBufferLog := true,
scriptedClasspath := getJars(scriptedConf).value,
scriptedTests := scriptedTestsTask.value,
scriptedRun := scriptedRunTask.value,
scriptedDependencies := (()),
scriptedDependencies := (scriptedDependencies dependsOn (compile in Test, publishLocal)).value,
scriptedLaunchOpts := Seq(),
scripted := scriptedTask.evaluated
)
private[this] def getJars(config: Configuration): Initialize[Task[PathFinder]] = Def.task {
PathFinder(Classpaths.managedJars(config, classpathTypes.value, update.value).map(_.data))
}
}