summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-12-31 00:04:49 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-12-31 00:50:11 -0800
commit13f896a36eb275de9784ce3400dde09311afd6bd (patch)
treeb4effd6451be0b1c1d74bfbb380b668950b522d1
parent982b1e07cb512d6a48c859950b7aa8ce9746dd25 (diff)
downloadmill-13f896a36eb275de9784ce3400dde09311afd6bd.tar.gz
mill-13f896a36eb275de9784ce3400dde09311afd6bd.tar.bz2
mill-13f896a36eb275de9784ce3400dde09311afd6bd.zip
- Convert `T.source` into a generic `Target` that flushes the cache every time
- Prepare `T.ctx().base: Path` that `Task`s (including `T.source`) can use to find a "default" path for source files. - Simplify `Cacher`
-rwxr-xr-xbuild.sc2
-rw-r--r--core/src/main/scala/mill/define/Task.scala61
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala42
-rw-r--r--core/src/main/scala/mill/main/MainRunner.scala19
-rw-r--r--core/src/main/scala/mill/main/ReplApplyHandler.scala1
-rw-r--r--core/src/main/scala/mill/main/RunScript.scala40
-rw-r--r--core/src/main/scala/mill/util/Ctx.scala18
-rw-r--r--core/src/test/scala/mill/define/CacherTests.scala2
-rw-r--r--core/src/test/scala/mill/eval/EvaluationTests.scala2
-rw-r--r--core/src/test/scala/mill/eval/FailureTests.scala2
-rw-r--r--core/src/test/scala/mill/eval/JavaCompileJarTests.scala17
-rw-r--r--core/src/test/scala/mill/util/TestEvaluator.scala10
-rw-r--r--moduledefs/src/main/scala/mill/moduledefs/Cacher.scala22
-rw-r--r--scalajslib/src/test/scala/mill/scalajslib/HelloJSWorldTests.scala3
-rw-r--r--scalalib/src/main/scala/mill/scalalib/GenIdea.scala5
-rw-r--r--scalalib/src/main/scala/mill/scalalib/Module.scala12
-rw-r--r--scalalib/src/main/scala/mill/scalalib/TestRunner.scala4
-rw-r--r--scalalib/src/test/scala/mill/scalalib/AcyclicTests.scala2
-rw-r--r--scalalib/src/test/scala/mill/scalalib/BetterFilesTests.scala2
-rw-r--r--scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala49
-rw-r--r--scalalib/src/test/scala/mill/scalalib/JawnTests.scala2
21 files changed, 193 insertions, 124 deletions
diff --git a/build.sc b/build.sc
index dfc0e46f..b9f909fb 100755
--- a/build.sc
+++ b/build.sc
@@ -108,7 +108,7 @@ val bridges = for{
def sources = T.source {
val path = basePath / 'src
mkdir(path)
- path
+ PathRef(path)
}
def allSources = T{
Seq(PathRef(shared.downloadBridgeSource(T.ctx().dest, crossVersion)))
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index b96e80c6..39ecb896 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -66,7 +66,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
import c.universe._
val lhs = Applicative.impl0[Task, T, Ctx](c)(reify(Result.Success(t.splice)).tree)
- mill.moduledefs.Cacher.impl0[TargetImpl, T](c)(
+ mill.moduledefs.Cacher.impl0[TargetImpl[T]](c)(
reify(
new TargetImpl[T](
lhs.splice,
@@ -96,7 +96,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
cl: c.Expr[Caller[mill.define.Task.Module]],
o: c.Expr[Overrides]): c.Expr[Target[T]] = {
import c.universe._
- mill.moduledefs.Cacher.impl0[Target, T](c)(
+ mill.moduledefs.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
Applicative.impl0[Task, T, Ctx](c)(t.tree).splice,
@@ -127,7 +127,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
cl: c.Expr[Caller[mill.define.Task.Module]],
o: c.Expr[Overrides]): c.Expr[Target[T]] = {
import c.universe._
- mill.moduledefs.Cacher.impl0[Target, T](c)(
+ mill.moduledefs.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
t.splice,
@@ -148,7 +148,37 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
cl: Caller[mill.define.Task.Module],
o: Overrides): Command[T] = macro commandImpl[T]
- def source(path: ammonite.ops.Path) = new Source(path)
+ def source[T](value: Result[T])
+ (implicit r: R[T],
+ w: W[T],
+ e: sourcecode.Enclosing,
+ n: sourcecode.Name,
+ cl: Caller[mill.define.Task.Module],
+ o: Overrides): Source[T] = macro sourceImpl[T]
+
+ def sourceImpl[T: c.WeakTypeTag](c: Context)
+ (value: c.Expr[T])
+ (r: c.Expr[R[T]],
+ w: c.Expr[W[T]],
+ e: c.Expr[sourcecode.Enclosing],
+ n: c.Expr[sourcecode.Name],
+ cl: c.Expr[Caller[mill.define.Task.Module]],
+ o: c.Expr[Overrides]): c.Expr[Source[T]] = {
+ import c.universe._
+
+ mill.moduledefs.Cacher.impl0[Source[T]](c)(
+ reify(
+ new Source[T](
+ Applicative.impl[Task, T, Ctx](c)(value).splice,
+ e.splice.value,
+ cl.splice.value,
+ n.splice.value,
+ upickle.default.ReadWriter(w.splice.write, r.splice.read),
+ o.splice.value
+ )
+ )
+ )
+ }
def command[T](t: Task[T])
(implicit c: Caller[Task.Module],
@@ -197,7 +227,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
import c.universe._
- mill.moduledefs.Cacher.impl0[Persistent, T](c)(
+ mill.moduledefs.Cacher.impl0[Persistent[T]](c)(
reify(
new Persistent[T](
Applicative.impl[Task, T, Ctx](c)(t).splice,
@@ -264,14 +294,15 @@ class Persistent[+T](t: Task[T],
override def flushDest = false
override def asPersistent = Some(this)
}
-object Source{
- implicit def apply(p: ammonite.ops.Path) = new Source(p)
-}
-class Source(path: ammonite.ops.Path) extends Task[PathRef]{
- def handle = PathRef(path)
- def evaluate(args: Ctx) = handle
- override def sideHash = handle.hashCode()
- val inputs = Nil
+class Source[T](t: Task[T],
+ val enclosing: String,
+ val owner: Task.Module,
+ val name: String,
+ val readWrite: RW[_],
+ val overrides: Int) extends Target[T]{
+ val inputs = Seq(t)
+ def evaluate(args: Ctx) = args[T](0)
+ override def sideHash = util.Random.nextInt()
}
object Task {
@@ -280,9 +311,7 @@ object Task {
trait TaskModule extends Module {
def defaultCommandName(): String
}
- trait Module extends mill.moduledefs.Cacher[Target]{
- def wrapCached[T](t: Target[T], enclosing: String): Target[T] = t
- }
+ trait Module extends mill.moduledefs.Cacher
class Task0[T](t: T) extends Task[T]{
lazy val t0 = t
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index 6fc0661a..4d94d3d9 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -24,6 +24,7 @@ case class Labelled[T](target: NamedTask[T],
}
}
class Evaluator[T](val workspacePath: Path,
+ val basePath: Path,
val mapping: Discovered.Mapping[T],
log: Logger,
val classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){
@@ -69,7 +70,13 @@ class Evaluator[T](val workspacePath: Path,
for((k, vs) <- sortedGroups.items()){
failing.addAll(k, vs.items.flatMap(results.get).collect{case f: Result.Failing => f})
}
- Evaluator.Results(goals.indexed.map(results), evaluated, transitive, failing)
+ Evaluator.Results(
+ goals.indexed.map(results),
+ evaluated,
+ transitive,
+ failing,
+ results
+ )
}
@@ -87,10 +94,11 @@ class Evaluator[T](val workspacePath: Path,
terminal match{
case Left(task) =>
- evaluateGroup(group, results, paths = None, maybeTargetLabel = None)
+ evaluateGroup(group, results, groupBasePath = None, paths = None, maybeTargetLabel = None)
case Right(labelledTarget) =>
- val paths = Evaluator.resolveDestPaths(workspacePath, labelledTarget)
- mkdir(paths.base)
+ val paths = Evaluator.resolveDestPaths(workspacePath, labelledTarget.segments)
+ val groupBasePath = basePath / Evaluator.makeSegmentStrings(labelledTarget.segments)
+ mkdir(paths.out)
val cached = for{
json <- scala.util.Try(upickle.json.read(read(paths.meta))).toOption
(cachedHash, terminalResult) <- scala.util.Try(upickle.default.readJs[(Int, upickle.Js.Value)](json)).toOption
@@ -117,8 +125,10 @@ class Evaluator[T](val workspacePath: Path,
val (newResults, newEvaluated) = evaluateGroup(
group,
results,
- Some(paths),
- maybeTargetLabel = Some(msgParts.mkString))
+ groupBasePath = Some(groupBasePath),
+ paths = Some(paths),
+ maybeTargetLabel = Some(msgParts.mkString)
+ )
newResults(labelledTarget.target) match{
case Result.Success(v) =>
@@ -148,6 +158,7 @@ class Evaluator[T](val workspacePath: Path,
def evaluateGroup(group: OSet[Task[_]],
results: collection.Map[Task[_], Result[Any]],
+ groupBasePath: Option[Path],
paths: Option[Evaluator.Paths],
maybeTargetLabel: Option[String]) = {
@@ -183,6 +194,7 @@ class Evaluator[T](val workspacePath: Path,
val args = new Ctx(
targetInputValues.toArray[Any],
paths.map(_.dest).orNull,
+ groupBasePath.orNull,
multiLogger,
new Ctx.LoaderCtx{
def load[T](x: Ctx.Loader[T]): T = {
@@ -225,15 +237,16 @@ class Evaluator[T](val workspacePath: Path,
object Evaluator{
- case class Paths(base: Path, dest: Path, meta: Path, log: Path)
- def resolveDestPaths(workspacePath: Path, t: Labelled[_]): Paths = {
- resolveDestPaths(workspacePath, t.segments)
+ case class Paths(out: Path,
+ dest: Path,
+ meta: Path,
+ log: Path)
+ def makeSegmentStrings(segments: Seq[Segment]) = segments.flatMap{
+ case Mirror.Segment.Label(s) => Seq(s)
+ case Mirror.Segment.Cross(values) => values.map(_.toString)
}
def resolveDestPaths(workspacePath: Path, segments: Seq[Segment]): Paths = {
- val segmentStrings = segments.flatMap{
- case Mirror.Segment.Label(s) => Seq(s)
- case Mirror.Segment.Cross(values) => values.map(_.toString)
- }
+ val segmentStrings = makeSegmentStrings(segments)
val targetPath = workspacePath / segmentStrings
Paths(targetPath, targetPath / 'dest, targetPath / "meta.json", targetPath / 'log)
}
@@ -248,7 +261,8 @@ object Evaluator{
case class Results(rawValues: Seq[Result[Any]],
evaluated: OSet[Task[_]],
transitive: OSet[Task[_]],
- failing: MultiBiMap[Either[Task[_], Labelled[_]], Result.Failing]){
+ failing: MultiBiMap[Either[Task[_], Labelled[_]], Result.Failing],
+ results: collection.Map[Task[_], Result[Any]]){
def values = rawValues.collect{case Result.Success(v) => v}
}
}
diff --git a/core/src/main/scala/mill/main/MainRunner.scala b/core/src/main/scala/mill/main/MainRunner.scala
index f354e838..8f58f114 100644
--- a/core/src/main/scala/mill/main/MainRunner.scala
+++ b/core/src/main/scala/mill/main/MainRunner.scala
@@ -1,9 +1,9 @@
package mill.main
-import ammonite.interp.Preprocessor
+import ammonite.interp.{Interpreter, Preprocessor}
import ammonite.ops.Path
import ammonite.util.{Imports, Name, Res, Util}
import mill.discover.Discovered
-import mill.eval.Evaluator
+import mill.eval.{Evaluator, PathRef}
import upickle.Js
/**
@@ -33,9 +33,20 @@ class MainRunner(config: ammonite.main.Cli.Config,
)
result match{
case Res.Success(data) =>
- val (eval, evaluationWatches, res) = data
+ val (eval, evaluationWatches0, res) = data
+ val alreadyStale = evaluationWatches0.exists(p => p.sig != PathRef(p.path, p.quick).sig)
+ // If the file changed between the creation of the original
+ // `PathRef` and the current moment, use random junk .sig values
+ // to force an immediate re-run. Otherwise calculate the
+ // pathSignatures the same way Ammonite would and hand over the
+ // values, so Ammonite can watch them and only re-run if they
+ // subsequently change
+ val evaluationWatches =
+ if (alreadyStale) evaluationWatches0.map(_.path -> util.Random.nextLong())
+ else evaluationWatches0.map(p => p.path -> Interpreter.pathSignature(p.path))
+
lastEvaluator = Some((interpWatched, eval))
- (Res.Success(res.flatMap(_._2)), interpWatched ++ evaluationWatches)
+ (Res(res.map(_.flatMap(_._2))), interpWatched ++ evaluationWatches)
case _ =>
(result, interpWatched)
}
diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala
index d0c8365a..3832da68 100644
--- a/core/src/main/scala/mill/main/ReplApplyHandler.scala
+++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala
@@ -11,6 +11,7 @@ object ReplApplyHandler{
new ReplApplyHandler(
new mill.eval.Evaluator(
ammonite.ops.pwd / 'out,
+ ammonite.ops.pwd,
mapping,
new mill.util.PrintLogger(true)
)
diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala
index ad813026..dc7b74d6 100644
--- a/core/src/main/scala/mill/main/RunScript.scala
+++ b/core/src/main/scala/mill/main/RunScript.scala
@@ -6,7 +6,7 @@ import ammonite.interp.Interpreter
import ammonite.ops.{Path, pwd, read}
import ammonite.util.Util.CodeSource
import ammonite.util.{Name, Res, Util}
-import mill.define
+import mill.{PathRef, define}
import mill.define.Task
import mill.discover.Mirror.Segment
import mill.discover.{Discovered, Mirror}
@@ -27,8 +27,7 @@ object RunScript{
path: Path,
interp: ammonite.interp.Interpreter,
scriptArgs: Seq[String],
- lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_])])
- : Res[(Evaluator[_], Seq[(Path, Long)], Seq[(Any, Option[Js.Value])])] = {
+ lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_])]) = {
val log = new PrintLogger(true)
for{
@@ -40,15 +39,10 @@ object RunScript{
case _ =>
interp.watch(path)
for(mapping <- evaluateMapping(wd, path, interp))
- yield new Evaluator(pwd / 'out, mapping, log)
+ yield new Evaluator(pwd / 'out, pwd, mapping, log)
}
- evaluationWatches = mutable.Buffer.empty[(Path, Long)]
- res <- Res(evaluateTarget(
- evaluator,
- scriptArgs,
- p => evaluationWatches.append((p, Interpreter.pathSignature(p)))
- ))
- } yield (evaluator, evaluationWatches, res)
+ (watches, res) <- Res(evaluateTarget(evaluator, scriptArgs))
+ } yield (evaluator, watches, res)
}
def watchedSigUnchanged(sig: Seq[(Path, Long)]) = {
@@ -98,8 +92,7 @@ object RunScript{
} yield mapping
}
def evaluateTarget[T](evaluator: Evaluator[_],
- scriptArgs: Seq[String],
- watch: Path => Unit) = {
+ scriptArgs: Seq[String]) = {
val Seq(selectorString, rest @_*) = scriptArgs
for {
@@ -112,17 +105,18 @@ object RunScript{
sel, evaluator.mapping.mirror, evaluator.mapping.base,
rest, crossSelectors, Nil
)
- res <- evaluate(evaluator, target, watch)
- } yield res
+ (watched, res) = evaluate(evaluator, target)
+ } yield (watched, res)
}
def evaluate(evaluator: Evaluator[_],
- target: Task[Any],
- watch: Path => Unit): Either[String, Seq[(Any, Option[upickle.Js.Value])]] = {
+ target: Task[Any]): (Seq[PathRef], Either[String, Seq[(Any, Option[upickle.Js.Value])]]) = {
val evaluated = evaluator.evaluate(OSet(target))
- evaluated.transitive.foreach {
- case t: define.Source => watch(t.handle.path)
- case _ => // do nothing
- }
+ val watched = evaluated.results
+ .iterator
+ .collect {
+ case (t: define.Source[_], Result.Success(p: PathRef)) => p
+ }
+ .toSeq
val errorStr =
(for((k, fs) <- evaluated.failing.items()) yield {
@@ -151,8 +145,8 @@ object RunScript{
}
}
- Right(evaluated.values.zip(json))
- case n => Left(s"$n targets failed\n$errorStr")
+ watched -> Right(evaluated.values.zip(json))
+ case n => watched -> Left(s"$n targets failed\n$errorStr")
}
}
diff --git a/core/src/main/scala/mill/util/Ctx.scala b/core/src/main/scala/mill/util/Ctx.scala
index 9604021a..60e6bdbf 100644
--- a/core/src/main/scala/mill/util/Ctx.scala
+++ b/core/src/main/scala/mill/util/Ctx.scala
@@ -2,7 +2,7 @@ package mill.util
import ammonite.ops.Path
import mill.define.Applicative.ImplicitStub
-import mill.util.Ctx.{ArgCtx, DestCtx, LoaderCtx, LogCtx}
+import mill.util.Ctx.{ArgCtx, BaseCtx, DestCtx, LoaderCtx, LogCtx}
import scala.annotation.compileTimeOnly
import scala.language.implicitConversions
@@ -13,15 +13,23 @@ object Ctx{
implicit def taskCtx: Ctx = ???
object DestCtx {
- implicit def pathToCtx(path: Path): DestCtx =
- new DestCtx { def dest: Path = path }
+ implicit def pathToCtx(path: Path): DestCtx = new DestCtx { def dest = path }
}
trait DestCtx{
def dest: Path
}
+ trait BaseCtx{
+ def base: Path
+ }
+ object BaseCtx {
+ implicit def pathToCtx(path: Path): BaseCtx = new BaseCtx { def base = path }
+ }
trait LogCtx{
def log: Logger
}
+ object LogCtx{
+ implicit def logToCtx(l: Logger): LogCtx = new LogCtx { def log = l }
+ }
trait ArgCtx{
def args: IndexedSeq[_]
}
@@ -34,12 +42,14 @@ object Ctx{
}
class Ctx(val args: IndexedSeq[_],
val dest: Path,
+ val base: Path,
val log: Logger,
workerCtx0: Ctx.LoaderCtx)
extends DestCtx
with LogCtx
with ArgCtx
- with LoaderCtx{
+ with LoaderCtx
+ with BaseCtx{
def load[T](x: Ctx.Loader[T]): T = workerCtx0.load(x)
def length = args.length
diff --git a/core/src/test/scala/mill/define/CacherTests.scala b/core/src/test/scala/mill/define/CacherTests.scala
index d85e9e6b..e46c0390 100644
--- a/core/src/test/scala/mill/define/CacherTests.scala
+++ b/core/src/test/scala/mill/define/CacherTests.scala
@@ -29,7 +29,7 @@ object CacherTests extends TestSuite{
def eval[V](mapping: Discovered.Mapping[_], v: Task[V])(implicit tp: TestPath) = {
val workspace = ammonite.ops.pwd / 'target / 'workspace / tp.value
- val evaluator = new Evaluator(workspace, mapping, DummyLogger)
+ val evaluator = new Evaluator(workspace, ammonite.ops.pwd, mapping, DummyLogger)
evaluator.evaluate(OSet(v)).values(0)
}
diff --git a/core/src/test/scala/mill/eval/EvaluationTests.scala b/core/src/test/scala/mill/eval/EvaluationTests.scala
index 75a6cc52..fb3f6b97 100644
--- a/core/src/test/scala/mill/eval/EvaluationTests.scala
+++ b/core/src/test/scala/mill/eval/EvaluationTests.scala
@@ -15,7 +15,7 @@ object EvaluationTests extends TestSuite{
val workspace = ammonite.ops.pwd / 'target / 'workspace / tp.value
ammonite.ops.rm(ammonite.ops.Path(workspace, ammonite.ops.pwd))
// Make sure data is persisted even if we re-create the evaluator each time
- def evaluator = new Evaluator(workspace, mapping, DummyLogger)
+ def evaluator = new Evaluator(workspace, ammonite.ops.pwd, mapping, DummyLogger)
def apply(target: Task[_], expValue: Any,
expEvaled: OSet[Task[_]],
diff --git a/core/src/test/scala/mill/eval/FailureTests.scala b/core/src/test/scala/mill/eval/FailureTests.scala
index 42331a74..c77ad74b 100644
--- a/core/src/test/scala/mill/eval/FailureTests.scala
+++ b/core/src/test/scala/mill/eval/FailureTests.scala
@@ -14,7 +14,7 @@ object FailureTests extends TestSuite{
}
class Checker(mapping: Discovered.Mapping[_])(implicit tp: TestPath){
- val evaluator = new Evaluator(workspace, mapping, DummyLogger)
+ val evaluator = new Evaluator(workspace, ammonite.ops.pwd, mapping, DummyLogger)
def apply(target: Target[_], expectedFailCount: Int, expectedRawValues: Seq[Result[_]]) = {
diff --git a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala
index 0efd0bf1..667aaa22 100644
--- a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala
+++ b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala
@@ -2,7 +2,7 @@ package mill.eval
import ammonite.ops.ImplicitWd._
import ammonite.ops._
-import mill.define.{Target, Task}
+import mill.define.{Source, Target, Task}
import mill.discover.Discovered
import mill.modules.Jvm
import mill.util.Ctx.DestCtx
@@ -36,8 +36,8 @@ object JavaCompileJarTests extends TestSuite{
// |
// v
// resourceRoot ----> jar
- def sourceRoot = T.source{ sourceRootPath }
- def resourceRoot = T.source{ resourceRootPath }
+ def sourceRoot = T.source{ PathRef(sourceRootPath) }
+ def resourceRoot = T.source{ PathRef(resourceRootPath) }
def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) }
def classFiles = T{ compileAll(allSources()) }
def jar = T{ Jvm.createJar(Seq(resourceRoot().path, classFiles().path)) }
@@ -51,7 +51,7 @@ object JavaCompileJarTests extends TestSuite{
val mapping = Discovered.mapping(Build)
def eval[T](t: Task[T]) = {
- val evaluator = new Evaluator(workspacePath, mapping, DummyLogger)
+ val evaluator = new Evaluator(workspacePath, pwd, mapping, DummyLogger)
val evaluated = evaluator.evaluate(OSet(t))
if (evaluated.failing.keyCount == 0){
@@ -68,12 +68,13 @@ object JavaCompileJarTests extends TestSuite{
}
def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = {
- val evaluator = new Evaluator(workspacePath, mapping, DummyLogger)
+ val evaluator = new Evaluator(workspacePath, pwd, mapping, DummyLogger)
val evaluated = evaluator.evaluate(targets)
.evaluated
.flatMap(_.asTarget)
.filter(mapping.targets.contains)
+ .filter(!_.isInstanceOf[Source[_]])
assert(evaluated == expected)
}
@@ -144,7 +145,7 @@ object JavaCompileJarTests extends TestSuite{
val Right((runOutput, evalCount)) = eval(Build.run("test.Foo"))
assert(
runOutput.out.string == (31337 + 271828) + "\n",
- evalCount == 1
+ evalCount == 2
)
}
@@ -165,12 +166,12 @@ object JavaCompileJarTests extends TestSuite{
val Right((runOutput2, evalCount2)) = eval(Build.run("test.BarFour"))
assert(
runOutput2.out.string == "New Cls!\n",
- evalCount2 == 3
+ evalCount2 == 4
)
val Right((runOutput3, evalCount3)) = eval(Build.run("test.BarFour"))
assert(
runOutput3.out.string == "New Cls!\n",
- evalCount3 == 1
+ evalCount3 == 2
)
}
}
diff --git a/core/src/test/scala/mill/util/TestEvaluator.scala b/core/src/test/scala/mill/util/TestEvaluator.scala
index 5d16de43..6ae90167 100644
--- a/core/src/test/scala/mill/util/TestEvaluator.scala
+++ b/core/src/test/scala/mill/util/TestEvaluator.scala
@@ -1,12 +1,14 @@
package mill.util
import ammonite.ops.Path
-import mill.define.{Target, Task}
+import mill.define.{Source, Target, Task}
import mill.discover.{Discovered, Mirror}
import mill.eval.{Evaluator, Result}
-class TestEvaluator(mapping: Discovered.Mapping[_], workspacePath: Path){
- val evaluator = new Evaluator(workspacePath, mapping, DummyLogger)
+class TestEvaluator(mapping: Discovered.Mapping[_],
+ workspacePath: Path,
+ basePath: Path){
+ val evaluator = new Evaluator(workspacePath, basePath, mapping, DummyLogger)
def apply[T](t: Task[T]): Either[Result.Failing, (T, Int)] = {
val evaluated = evaluator.evaluate(OSet(t))
@@ -16,7 +18,7 @@ class TestEvaluator(mapping: Discovered.Mapping[_], workspacePath: Path){
Tuple2(
evaluated.rawValues.head.asInstanceOf[Result.Success[T]].value,
evaluated.evaluated.collect {
- case t: Target[_] if mapping.targets.contains(t) => t
+ case t: Target[_] if mapping.targets.contains(t) && !t.isInstanceOf[Source[_]] => t
case t: mill.define.Command[_] => t
}.size
))
diff --git a/moduledefs/src/main/scala/mill/moduledefs/Cacher.scala b/moduledefs/src/main/scala/mill/moduledefs/Cacher.scala
index cea2ca41..023f03be 100644
--- a/moduledefs/src/main/scala/mill/moduledefs/Cacher.scala
+++ b/moduledefs/src/main/scala/mill/moduledefs/Cacher.scala
@@ -4,19 +4,21 @@ import scala.collection.mutable
import scala.reflect.macros.blackbox.Context
-trait Cacher[C[_]]{
- private[this] lazy val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, C[_]]
- def wrapCached[T](in: C[T], enclosing: String): C[T]
- protected[this] def cachedTarget[T](t: => C[T])
- (implicit c: sourcecode.Enclosing): C[T] = synchronized{
- cacherLazyMap.getOrElseUpdate(c, wrapCached(t, c.value)).asInstanceOf[C[T]]
+trait Cacher{
+ private[this] lazy val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, Any]
+
+ protected[this] def cachedTarget[T](t: => T)
+ (implicit c: sourcecode.Enclosing): T = synchronized{
+ cacherLazyMap.getOrElseUpdate(c, t).asInstanceOf[T]
}
}
+
object Cacher{
- def impl0[M[_], T: c.WeakTypeTag](c: Context)(t: c.Expr[M[T]]): c.Expr[M[T]] = {
- c.Expr[M[T]](wrapCached(c)(t.tree))
+ def impl0[T: c.WeakTypeTag](c: Context)
+ (t: c.Expr[T]): c.Expr[T] = {
+ c.Expr[T](wrapCached[T](c)(t.tree))
}
- def wrapCached(c: Context)(t: c.Tree) = {
+ def wrapCached[R: c.WeakTypeTag](c: Context)(t: c.Tree) = {
import c.universe._
val owner = c.internal.enclosingOwner
@@ -24,7 +26,7 @@ object Cacher{
owner.owner.isClass &&
owner.owner.asClass.baseClasses.exists(_.fullName == "mill.moduledefs.Cacher")
- if (ownerIsCacherClass && owner.isMethod) q"this.cachedTarget($t)"
+ if (ownerIsCacherClass && owner.isMethod) q"this.cachedTarget[${weakTypeTag[R]}]($t)"
else c.abort(
c.enclosingPosition,
"T{} members must be defs defined in a Cacher class/trait/object body"
diff --git a/scalajslib/src/test/scala/mill/scalajslib/HelloJSWorldTests.scala b/scalajslib/src/test/scala/mill/scalajslib/HelloJSWorldTests.scala
index ad392c42..85052a04 100644
--- a/scalajslib/src/test/scala/mill/scalajslib/HelloJSWorldTests.scala
+++ b/scalajslib/src/test/scala/mill/scalajslib/HelloJSWorldTests.scala
@@ -54,7 +54,8 @@ object HelloJSWorldTests extends TestSuite {
val helloWorldEvaluator = new TestEvaluator(
Discovered.mapping(HelloJSWorld),
- workspacePath
+ workspacePath,
+ srcPath
)
class Console {
diff --git a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala
index 6fd5031a..8b89fa9a 100644
--- a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala
+++ b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala
@@ -16,9 +16,8 @@ object GenIdea {
rm! pwd/".idea"
rm! pwd/".idea_modules"
- val workspacePath = pwd / 'out
- val evaluator = new Evaluator(workspacePath, mapping, new PrintLogger(true))
+ val evaluator = new Evaluator(pwd / 'out, pwd, mapping, new PrintLogger(true))
for((relPath, xml) <- xmlFileLayout(evaluator)){
write.over(pwd/relPath, pp.format(xml))
@@ -85,7 +84,7 @@ object GenIdea {
val elem = moduleXmlTemplate(
sourcePath.path,
- Seq(paths.base),
+ Seq(paths.out),
resolvedDeps.map(pathToLibName),
for(m <- mod.projectDeps)
yield moduleName(moduleLabels(m))
diff --git a/scalalib/src/main/scala/mill/scalalib/Module.scala b/scalalib/src/main/scala/mill/scalalib/Module.scala
index 1ff4c240..76c50aed 100644
--- a/scalalib/src/main/scala/mill/scalalib/Module.scala
+++ b/scalalib/src/main/scala/mill/scalalib/Module.scala
@@ -191,8 +191,8 @@ trait Module extends mill.Module with TaskModule { outer =>
def prependShellScript: T[String] = T{ "" }
- def sources = T.source{ basePath / 'src }
- def resources = T.source{ basePath / 'resources }
+ def sources = T.source{ PathRef(basePath / 'src) }
+ def resources = T.source{ PathRef(basePath / 'resources) }
def allSources = T{ Seq(sources()) }
def compile: T[CompilationResult] = T.persistent{
compileScala(
@@ -346,11 +346,11 @@ trait PublishModule extends Module { outer =>
trait SbtModule extends Module { outer =>
def basePath: Path
- override def sources = T.source{ basePath / 'src / 'main / 'scala }
- override def resources = T.source{ basePath / 'src / 'main / 'resources }
+ override def sources = T.source{ PathRef(basePath / 'src / 'main / 'scala) }
+ override def resources = T.source{ PathRef(basePath / 'src / 'main / 'resources) }
trait Tests extends super.Tests{
def basePath = outer.basePath
- override def sources = T.source{ basePath / 'src / 'test / 'scala }
- override def resources = T.source{ basePath / 'src / 'test / 'resources }
+ override def sources = T.source{ PathRef(basePath / 'src / 'test / 'scala) }
+ override def resources = T.source{ PathRef(basePath / 'src / 'test / 'resources) }
}
}
diff --git a/scalalib/src/main/scala/mill/scalalib/TestRunner.scala b/scalalib/src/main/scala/mill/scalalib/TestRunner.scala
index 7d42bdea..d92a9deb 100644
--- a/scalalib/src/main/scala/mill/scalalib/TestRunner.scala
+++ b/scalalib/src/main/scala/mill/scalalib/TestRunner.scala
@@ -46,9 +46,7 @@ object TestRunner {
entireClasspath = args(1).split(" ").map(Path(_)),
testClassfilePath = args(2).split(" ").map(Path(_)),
args = args(3) match{ case "" => Nil case x => x.split(" ").toList }
- )(new LogCtx {
- def log = new PrintLogger(true)
- })
+ )(new PrintLogger(true))
val outputPath = args(4)
ammonite.ops.write(Path(outputPath), upickle.default.write(result))
diff --git a/scalalib/src/test/scala/mill/scalalib/AcyclicTests.scala b/scalalib/src/test/scala/mill/scalalib/AcyclicTests.scala
index 9b68ea70..44a43702 100644
--- a/scalalib/src/test/scala/mill/scalalib/AcyclicTests.scala
+++ b/scalalib/src/test/scala/mill/scalalib/AcyclicTests.scala
@@ -53,7 +53,7 @@ object AcyclicTests extends TestSuite{
mkdir(workspacePath/up)
cp(srcPath, workspacePath)
val mapping = Discovered.mapping(AcyclicBuild)
- val eval = new TestEvaluator(mapping, workspacePath)
+ val eval = new TestEvaluator(mapping, workspacePath, srcPath)
def check(scalaVersion: String) = {
// We can compile
diff --git a/scalalib/src/test/scala/mill/scalalib/BetterFilesTests.scala b/scalalib/src/test/scala/mill/scalalib/BetterFilesTests.scala
index c3004f7b..1f0a3d70 100644
--- a/scalalib/src/test/scala/mill/scalalib/BetterFilesTests.scala
+++ b/scalalib/src/test/scala/mill/scalalib/BetterFilesTests.scala
@@ -96,7 +96,7 @@ object BetterFilesTests extends TestSuite{
mkdir(workspacePath/up)
cp(srcPath, workspacePath)
val mapping = Discovered.mapping(BetterFilesBuild)
- val eval = new TestEvaluator(mapping, workspacePath)
+ val eval = new TestEvaluator(mapping, workspacePath, srcPath)
'test - {
diff --git a/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala b/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala
index aafd980a..0b6ac62b 100644
--- a/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala
+++ b/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala
@@ -17,7 +17,7 @@ import scala.collection.JavaConverters._
trait HelloWorldModule extends scalalib.Module {
def scalaVersion = "2.12.4"
- def basePath = HelloWorldTests.workspacePath
+ def basePath = HelloWorldTests.workingSrcPath
}
object HelloWorld extends HelloWorldModule
@@ -66,31 +66,38 @@ object HelloWorldScalaOverride extends HelloWorldModule {
object HelloWorldTests extends TestSuite {
val srcPath = pwd / 'scalalib / 'src / 'test / 'resource / "hello-world"
- val workspacePath = pwd / 'target / 'workspace / "hello-world"
- val mainObject = workspacePath / 'src / 'main / 'scala / "Main.scala"
+ val basePath = pwd / 'target / 'workspace / "hello-world"
+ val workingSrcPath = basePath / 'src
+ val outPath = basePath / 'out
+ val mainObject = workingSrcPath / 'src / 'main / 'scala / "Main.scala"
val helloWorldEvaluator = new TestEvaluator(
Discovered.mapping(HelloWorld),
- workspacePath
+ outPath,
+ workingSrcPath
)
val helloWorldWithMainEvaluator = new TestEvaluator(
Discovered.mapping(HelloWorldWithMain),
- workspacePath
+ outPath,
+ workingSrcPath
)
val helloWorldFatalEvaluator = new TestEvaluator(
Discovered.mapping(HelloWorldFatalWarnings),
- workspacePath
+ outPath,
+ workingSrcPath
)
val helloWorldOverrideEvaluator = new TestEvaluator(
Discovered.mapping(HelloWorldScalaOverride),
- workspacePath
+ outPath,
+ workingSrcPath
)
val helloWorldCrossEvaluator = new TestEvaluator(
Discovered.mapping(CrossHelloWorld),
- workspacePath
+ outPath,
+ workingSrcPath
)
@@ -136,12 +143,11 @@ object HelloWorldTests extends TestSuite {
'fromScratch - {
val Right((result, evalCount)) = helloWorldEvaluator(HelloWorld.compile)
- val outPath = result.classes.path
val analysisFile = result.analysisFile
- val outputFiles = ls.rec(outPath)
- val expectedClassfiles = compileClassfiles.map(workspacePath / 'compile / 'dest / 'classes / _)
+ val outputFiles = ls.rec(result.classes.path)
+ val expectedClassfiles = compileClassfiles.map(outPath / 'compile / 'dest / 'classes / _)
assert(
- outPath == workspacePath / 'compile / 'dest / 'classes,
+ result.classes.path == outPath / 'compile / 'dest / 'classes,
exists(analysisFile),
outputFiles.nonEmpty,
outputFiles.forall(expectedClassfiles.contains),
@@ -169,7 +175,7 @@ object HelloWorldTests extends TestSuite {
assert(err.isInstanceOf[CompileFailed])
val paths = Evaluator.resolveDestPaths(
- workspacePath,
+ outPath,
helloWorldEvaluator.evaluator.mapping.targets(HelloWorld.compile)
)
@@ -195,7 +201,7 @@ object HelloWorldTests extends TestSuite {
assert(evalCount > 0)
- val runResult = workspacePath / "hello-mill"
+ val runResult = basePath / "hello-mill"
assert(
exists(runResult),
read(runResult) == "hello rockjam, your age is: 25"
@@ -210,7 +216,7 @@ object HelloWorldTests extends TestSuite {
assert(evalCount > 0)
- val runResult = workspacePath / "hello-mill"
+ val runResult = basePath / "hello-mill"
assert(
exists(runResult),
read(runResult) == "hello rockjam, your age is: 25"
@@ -246,7 +252,7 @@ object HelloWorldTests extends TestSuite {
assert(evalCount > 0)
- val runResult = workspacePath / "hello-mill"
+ val runResult = basePath / "hello-mill"
assert(
exists(runResult),
read(runResult) == "hello rockjam, your age is: 25"
@@ -291,7 +297,7 @@ object HelloWorldTests extends TestSuite {
%("scala", result.path)
- val runResult = workspacePath / "hello-mill"
+ val runResult = basePath / "hello-mill"
assert(
exists(runResult),
read(runResult) == "hello rockjam, your age is: 25"
@@ -300,7 +306,7 @@ object HelloWorldTests extends TestSuite {
'logOutputToFile {
helloWorldEvaluator(HelloWorld.compile)
- val logFile = workspacePath / 'compile / 'log
+ val logFile = outPath / 'compile / 'log
assert(exists(logFile))
}
}
@@ -315,9 +321,10 @@ object HelloWorldTests extends TestSuite {
)
def prepareWorkspace(): Unit = {
- rm(workspacePath)
- mkdir(workspacePath / up)
- cp(srcPath, workspacePath)
+ rm(outPath)
+ rm(workingSrcPath)
+ mkdir(outPath)
+ cp(srcPath, workingSrcPath)
}
}
diff --git a/scalalib/src/test/scala/mill/scalalib/JawnTests.scala b/scalalib/src/test/scala/mill/scalalib/JawnTests.scala
index 71e4d506..8449cc02 100644
--- a/scalalib/src/test/scala/mill/scalalib/JawnTests.scala
+++ b/scalalib/src/test/scala/mill/scalalib/JawnTests.scala
@@ -75,7 +75,7 @@ object JawnTests extends TestSuite{
mkdir(workspacePath/up)
cp(srcPath, workspacePath)
val mapping = Discovered.mapping(JawnBuild)
- val eval = new TestEvaluator(mapping, workspacePath)
+ val eval = new TestEvaluator(mapping, workspacePath, srcPath)
'test - {
def compileOutput = workspacePath / 'jawn / "2.12.3" / 'Parser / 'compile