summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sc1
-rw-r--r--core/src/mill/define/Module.scala3
-rw-r--r--core/src/mill/main/Resolve.scala2
-rw-r--r--core/src/mill/modules/Jvm.scala37
-rw-r--r--integration/test/resources/ammonite/build.sc13
-rw-r--r--scalalib/src/mill/scalalib/ScalaModule.scala65
-rw-r--r--scalalib/test/src/mill/scalalib/HelloWorldTests.scala8
7 files changed, 86 insertions, 43 deletions
diff --git a/build.sc b/build.sc
index ad916f91..1033fc48 100755
--- a/build.sc
+++ b/build.sc
@@ -30,7 +30,6 @@ trait MillModule extends ScalaModule{ outer =>
val test = new Tests(implicitly)
class Tests(ctx0: mill.define.Ctx) extends mill.Module()(ctx0) with super.Tests{
- def defaultCommandName() = "forkTest"
def forkArgs = T{ testArgs() }
def moduleDeps =
if (this == core.test) Seq(core)
diff --git a/core/src/mill/define/Module.scala b/core/src/mill/define/Module.scala
index 1be75e1d..222bb7ec 100644
--- a/core/src/mill/define/Module.scala
+++ b/core/src/mill/define/Module.scala
@@ -76,12 +76,13 @@ object Module{
// another top-level concrete `object`. This is fine for now, since Mill's Ammonite
// script/REPL runner always wraps user code in a wrapper object/trait
def reflectNestedObjects[T: ClassTag] = {
- reflect[T] ++
+ (reflect[T] ++
outer
.getClass
.getClasses
.filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _)
.flatMap(c => c.getFields.find(_.getName == "MODULE$").map(_.get(c).asInstanceOf[T]))
+ ).distinct
}
}
}
diff --git a/core/src/mill/main/Resolve.scala b/core/src/mill/main/Resolve.scala
index d836a1a1..b01391d0 100644
--- a/core/src/mill/main/Resolve.scala
+++ b/core/src/mill/main/Resolve.scala
@@ -46,7 +46,7 @@ object Resolve {
val command = invokeCommand(obj, last).headOption
- command orElse target orElse runDefault.headOption.flatten match{
+ command orElse target orElse runDefault.flatten.headOption match{
case None => Left("Cannot resolve task " +
Segments((Segment.Label(last) :: revSelectorsSoFar).reverse:_*).render
)
diff --git a/core/src/mill/modules/Jvm.scala b/core/src/mill/modules/Jvm.scala
index fdd928d7..7f2ca4dd 100644
--- a/core/src/mill/modules/Jvm.scala
+++ b/core/src/mill/modules/Jvm.scala
@@ -33,17 +33,26 @@ object Jvm {
def interactiveSubprocess(mainClass: String,
classPath: Agg[Path],
- options: Seq[String] = Seq.empty): Unit = {
+ jvmArgs: Seq[String] = Seq.empty,
+ envArgs: Map[String, String] = Map.empty,
+ mainArgs: Seq[String] = Seq.empty,
+ workingDir: Path = null): Unit = {
import ammonite.ops.ImplicitWd._
- %("java", "-cp", classPath.mkString(":"), mainClass, options)
+ val commandArgs =
+ Vector("java") ++
+ jvmArgs ++
+ Vector("-cp", classPath.mkString(":"), mainClass) ++
+ mainArgs
+
+ %.copy(envArgs = envArgs)(commandArgs)(workingDir)
}
- def inprocess(mainClass: String,
- classPath: Agg[Path],
- options: Seq[String] = Seq.empty)
- (implicit ctx: Ctx): Unit = {
+ def runLocal(mainClass: String,
+ classPath: Agg[Path],
+ mainArgs: Seq[String] = Seq.empty)
+ (implicit ctx: Ctx): Unit = {
inprocess(classPath, classLoaderOverrideSbtTesting = false, cl => {
- getMainMethod(mainClass, cl).invoke(null, options.toArray)
+ getMainMethod(mainClass, cl).invoke(null, mainArgs.toArray)
})
}
@@ -95,27 +104,29 @@ object Jvm {
def subprocess(mainClass: String,
classPath: Agg[Path],
- jvmOptions: Seq[String] = Seq.empty,
- options: Seq[String] = Seq.empty,
+ jvmArgs: Seq[String] = Seq.empty,
+ envArgs: Map[String, String] = Map.empty,
+ mainArgs: Seq[String] = Seq.empty,
workingDir: Path = null)
(implicit ctx: Ctx) = {
val commandArgs =
Vector("java") ++
- jvmOptions ++
+ jvmArgs ++
Vector("-cp", classPath.mkString(":"), mainClass) ++
- options
+ mainArgs
val workingDir1 = Option(workingDir).getOrElse(ctx.dest)
mkdir(workingDir1)
- val proc =
+ val builder =
new java.lang.ProcessBuilder()
.directory(workingDir1.toIO)
.command(commandArgs:_*)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
- .start()
+ for((k, v) <- envArgs) builder.environment().put(k, v)
+ val proc = builder.start()
val stdout = proc.getInputStream
val stderr = proc.getErrorStream
val sources = Seq(
diff --git a/integration/test/resources/ammonite/build.sc b/integration/test/resources/ammonite/build.sc
index cb8d32ab..ebc264d4 100644
--- a/integration/test/resources/ammonite/build.sc
+++ b/integration/test/resources/ammonite/build.sc
@@ -26,7 +26,7 @@ object terminal extends Cross[TerminalModule](binCrossScalaVersions:_*)
class TerminalModule(val crossScalaVersion: String) extends AmmModule{
def ivyDeps = Agg(
ivy"com.lihaoyi::sourcecode:0.1.3",
- ivy"com.lihaoyi::fansi:0.2.3"
+ ivy"com.lihaoyi::fansi:0.2.4"
)
def compileIvyDeps = Agg(
ivy"org.scala-lang:scala-reflect:$crossScalaVersion"
@@ -141,9 +141,10 @@ class ShellModule(val crossScalaVersion: String) extends AmmModule{
def moduleDeps = Seq(ops(), amm())
object test extends Tests{
def moduleDeps = super.moduleDeps ++ Seq(amm.repl().test)
- // (test in Test) := (test in Test).dependsOn(packageBin in Compile).value,
- // (run in Test) := (run in Test).dependsOn(packageBin in Compile).evaluated,
- // (testOnly in Test) := (testOnly in Test).dependsOn(packageBin in Compile).evaluated
+ def forkEnv = super.forkEnv() ++ Seq(
+ "AMMONITE_TEST_SHELL" -> shell().jar().path.toString,
+ "AMMONITE_TEST_ASSEMBLY" -> amm().assembly().path.toString
+ )
}
}
object integration extends Cross[IntegrationModule](fullCrossScalaVersions:_*)
@@ -155,6 +156,10 @@ class IntegrationModule(val crossScalaVersion: String) extends AmmModule{
// (console in Test) := (console in Test).dependsOn(integrationTasks:_*).value,
// initialCommands in (Test, console) := "ammonite.integration.Main.main(null)"
object test extends Tests {
+ def forkEnv = super.forkEnv() ++ Seq(
+ "AMMONITE_TEST_SHELL" -> shell().jar().path.toString,
+ "AMMONITE_TEST_ASSEMBLY" -> amm().assembly().path.toString
+ )
}
}
diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala
index 975a5972..87bf119c 100644
--- a/scalalib/src/mill/scalalib/ScalaModule.scala
+++ b/scalalib/src/mill/scalalib/ScalaModule.scala
@@ -7,7 +7,7 @@ import mill.define.{Cross, Task}
import mill.define.TaskModule
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
-import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess, inprocess}
+import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess, runLocal}
import Lib._
import mill.define.Cross.Resolver
import mill.util.Loose.Agg
@@ -205,7 +205,7 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
if (files.nonEmpty) subprocess(
"scala.tools.nsc.ScalaDoc",
compileDepClasspath().filter(_.path.ext != "pom").map(_.path),
- options = (files ++ options).toSeq
+ mainArgs = (files ++ options).toSeq
)
createJar(Agg(javadocDir))(outDir / "javadoc.jar")
@@ -217,38 +217,51 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
def forkArgs = T{ Seq.empty[String] }
+ def forkEnv = T{ sys.env.toMap }
- def run(args: String*) = T.command {
- inprocess(
+ def runLocal(args: String*) = T.command {
+ Jvm.runLocal(
mainClass().getOrElse(throw new RuntimeException("No mainClass provided!")),
runClasspath().map(_.path),
- args)
+ args
+ )
}
- def forkRun(args: String*) = T.command{
- subprocess(
+ def run(args: String*) = T.command{
+ Jvm.interactiveSubprocess(
mainClass().getOrElse(throw new RuntimeException("No mainClass provided!")),
runClasspath().map(_.path),
forkArgs(),
+ forkEnv(),
args,
workingDir = ammonite.ops.pwd)
}
+
+ def runMainLocal(mainClass: String, args: String*) = T.command {
+ Jvm.runLocal(
+ mainClass,
+ runClasspath().map(_.path),
+ args
+ )
+ }
+
def runMain(mainClass: String, args: String*) = T.command{
- subprocess(
+ Jvm.interactiveSubprocess(
mainClass,
runClasspath().map(_.path),
forkArgs(),
+ forkEnv(),
args,
workingDir = ammonite.ops.pwd
)
}
def console() = T.command{
- interactiveSubprocess(
+ Jvm.interactiveSubprocess(
mainClass = "scala.tools.nsc.MainGenericRunner",
classPath = runClasspath().map(_.path),
- options = Seq("-usejavacp")
+ mainArgs = Seq("-usejavacp")
)
}
@@ -282,15 +295,16 @@ trait TestModule extends ScalaModule with TaskModule {
def forkWorkingDir = ammonite.ops.pwd
- def forkTest(args: String*) = T.command{
+ def test(args: String*) = T.command{
mkdir(T.ctx().dest)
val outputPath = T.ctx().dest/"out.json"
Jvm.subprocess(
mainClass = "mill.scalalib.TestRunner",
classPath = Jvm.gatherClassloaderJars(),
- jvmOptions = forkArgs(),
- options = Seq(
+ jvmArgs = forkArgs(),
+ envArgs = forkEnv(),
+ mainArgs = Seq(
testFramework(),
runClasspath().map(_.path).mkString(" "),
Seq(compile().classes.path).mkString(" "),
@@ -306,13 +320,26 @@ trait TestModule extends ScalaModule with TaskModule {
TestModule.handleResults(doneMsg, results)
}
- def test(args: String*) = T.command{
- val (doneMsg, results) = TestRunner(
- testFramework(),
- runClasspath().map(_.path),
- Agg(compile().classes.path),
- args
+ def testLocal(args: String*) = T.command{
+ mkdir(T.ctx().dest)
+ val outputPath = T.ctx().dest/"out.json"
+
+ Jvm.runLocal(
+ mainClass = "mill.scalalib.TestRunner",
+ classPath = Jvm.gatherClassloaderJars(),
+ mainArgs = Seq(
+ testFramework(),
+ runClasspath().map(_.path).mkString(" "),
+ Seq(compile().classes.path).mkString(" "),
+ args.mkString(" "),
+ outputPath.toString,
+ T.ctx().log.colored.toString
+ )
)
+
+ val jsonOutput = upickle.json.read(outputPath.toIO)
+ val (doneMsg, results) = upickle.default.readJs[(String, Seq[TestRunner.Result])](jsonOutput)
TestModule.handleResults(doneMsg, results)
+
}
} \ No newline at end of file
diff --git a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
index 8ac45bf3..1c22c578 100644
--- a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
+++ b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
@@ -267,7 +267,7 @@ object HelloWorldTests extends TestSuite {
'runIfMainClassProvided - {
val runResult = basePath / 'out / 'run / 'dest / "hello-mill"
val Right((_, evalCount)) = helloWorldWithMainEvaluator(
- HelloWorldWithMain.forkRun(runResult.toString)
+ HelloWorldWithMain.run(runResult.toString)
)
assert(evalCount > 0)
@@ -279,7 +279,7 @@ object HelloWorldTests extends TestSuite {
)
}
'notRunWithoutMainClass - {
- val Left(Result.Exception(err, _)) = helloWorldEvaluator(HelloWorld.forkRun())
+ val Left(Result.Exception(err, _)) = helloWorldEvaluator(HelloWorld.run())
assert(
err.isInstanceOf[RuntimeException]
@@ -290,7 +290,7 @@ object HelloWorldTests extends TestSuite {
'runIfMainClassProvided - {
val runResult = basePath / 'out / 'run / 'dest / "hello-mill"
val Right((_, evalCount)) = helloWorldWithMainEvaluator(
- HelloWorldWithMain.run(runResult.toString)
+ HelloWorldWithMain.runLocal(runResult.toString)
)
assert(evalCount > 0)
@@ -302,7 +302,7 @@ object HelloWorldTests extends TestSuite {
)
}
'notRunWithoutMainClass - {
- val Left(Result.Exception(err, _)) = helloWorldEvaluator(HelloWorld.run())
+ val Left(Result.Exception(err, _)) = helloWorldEvaluator(HelloWorld.runLocal())
assert(
err.isInstanceOf[RuntimeException]