summaryrefslogtreecommitdiff
path: root/core/src/main/scala
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-18 05:37:11 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-18 05:51:12 -0800
commit933a3df121e49cff240b5e29d9dab763562c44ef (patch)
tree5e84cfb714c3e2e19e7651ead4068af6b3df9c54 /core/src/main/scala
parent7b9c6526965d997d5a7d2cb38a206b9c4af105c8 (diff)
downloadmill-933a3df121e49cff240b5e29d9dab763562c44ef.tar.gz
mill-933a3df121e49cff240b5e29d9dab763562c44ef.tar.bz2
mill-933a3df121e49cff240b5e29d9dab763562c44ef.zip
Implement `T.persistent{}` targets, which have their dest directory persist between runs so the task implementation can use it as a cache
Diffstat (limited to 'core/src/main/scala')
-rw-r--r--core/src/main/scala/mill/Main.scala2
-rw-r--r--core/src/main/scala/mill/define/Cacher.scala11
-rw-r--r--core/src/main/scala/mill/define/Task.scala34
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala3
4 files changed, 40 insertions, 10 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala
index f4042ae8..c4df0ee5 100644
--- a/core/src/main/scala/mill/Main.scala
+++ b/core/src/main/scala/mill/Main.scala
@@ -12,6 +12,7 @@ import ammonite.main.Scripts.pathScoptRead
import ammonite.repl.Repl
object Main {
+
def apply[T: Discovered](args: Seq[String], obj: T, watch: Path => Unit) = {
val Seq(selectorString, rest @_*) = args
@@ -131,6 +132,7 @@ class Main(config: Main.Config){
case Res.Failure(msg) =>
printError(msg)
false
+
case Res.Exception(ex, s) =>
printError(
Repl.showException(ex, fansi.Color.Red, fansi.Attr.Reset, fansi.Color.Green)
diff --git a/core/src/main/scala/mill/define/Cacher.scala b/core/src/main/scala/mill/define/Cacher.scala
index 224704ce..09200203 100644
--- a/core/src/main/scala/mill/define/Cacher.scala
+++ b/core/src/main/scala/mill/define/Cacher.scala
@@ -4,12 +4,12 @@ import scala.collection.mutable
import scala.reflect.macros.blackbox.Context
-trait Cacher[C[_], V[_]]{
- private[this] val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, V[_]]
- def wrapCached[T](in: C[T], enclosing: String): V[T]
+trait Cacher[C[_]]{
+ private[this] 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): V[T] = synchronized{
- cacherLazyMap.getOrElseUpdate(c, wrapCached(t, c.value)).asInstanceOf[V[T]]
+ (implicit c: sourcecode.Enclosing): C[T] = synchronized{
+ cacherLazyMap.getOrElseUpdate(c, wrapCached(t, c.value)).asInstanceOf[C[T]]
}
}
object Cacher{
@@ -17,6 +17,7 @@ object Cacher{
c.Expr[M[T]](wrapCached(c)(t.tree))
}
def wrapCached(c: Context)(t: c.Tree) = {
+
import c.universe._
val owner = c.internal.enclosingOwner
val ownerIsCacherClass =
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index 0e2591c6..70f93d35 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -24,6 +24,8 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[T]{
* anyway?
*/
def sideHash: Int = 0
+
+ def flushDest: Boolean = true
}
trait Target[+T] extends Task[T]
@@ -31,7 +33,7 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
implicit def apply[T](t: T): Target[T] = macro targetImpl[T]
- def apply[T](t: Task[T]): Target[T] = macro Cacher.impl0[Task, T]
+ def apply[T](t: Task[T]): Target[T] = macro targetTaskImpl[T]
def command[T](t: T): Command[T] = macro commandImpl[T]
@@ -42,6 +44,16 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
def task[T](t: T): Task[T] = macro Applicative.impl[Task, T, Args]
def task[T](t: Task[T]): Task[T] = t
+ def persistent[T](t: T): Target[T] = macro persistentImpl[T]
+ def persistentImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Persistent[T]] = {
+ import c.universe._
+
+ c.Expr[Persistent[T]](
+ mill.define.Cacher.wrapCached(c)(
+ q"new ${weakTypeOf[Persistent[T]]}(${Applicative.impl[Task, T, Args](c)(t).tree})"
+ )
+ )
+ }
def commandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Command[T]] = {
import c.universe._
@@ -50,10 +62,19 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
)
}
+ def targetTaskImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[Task[T]]): c.Expr[Target[T]] = {
+ import c.universe._
+ c.Expr[Target[T]](
+ mill.define.Cacher.wrapCached(c)(
+ q"new ${weakTypeOf[TargetImpl[T]]}($t, _root_.sourcecode.Enclosing())"
+ )
+ )
+ }
def targetImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Target[T]] = {
+ import c.universe._
c.Expr[Target[T]](
mill.define.Cacher.wrapCached(c)(
- Applicative.impl[Task, T, Args](c)(t).tree
+ q"new ${weakTypeOf[TargetImpl[T]]}(${Applicative.impl[Task, T, Args](c)(t).tree}, _root_.sourcecode.Enclosing())"
)
)
}
@@ -93,6 +114,11 @@ class Command[+T](t: Task[T]) extends Task[T] {
val inputs = Seq(t)
def evaluate(args: Args) = args[T](0)
}
+class Persistent[+T](t: Task[T]) extends Target[T] {
+ val inputs = Seq(t)
+ def evaluate(args: Args) = args[T](0)
+ override def flushDest = false
+}
object Source{
implicit def apply(p: ammonite.ops.Path) = new Source(p)
}
@@ -107,8 +133,8 @@ object Task {
- trait Module extends mill.define.Cacher[Task, Target]{
- def wrapCached[T](t: Task[T], enclosing: String): Target[T] = new TargetImpl(t, enclosing)
+ trait Module extends mill.define.Cacher[Target]{
+ def wrapCached[T](t: Target[T], enclosing: String): Target[T] = t
}
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 22861847..ef81515c 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -77,6 +77,7 @@ class Evaluator(workspacePath: Path,
if (labeled.nonEmpty){
println(fansi.Color.Blue("Running " + labeled.map(_.segments.mkString(".")).mkString(", ")))
}
+ if (terminal.flushDest) targetDestPath.foreach(rm)
val (newResults, newEvaluated, terminalResult) = evaluateGroup(group, results, targetDestPath)
metadataPath.foreach(
@@ -95,7 +96,7 @@ class Evaluator(workspacePath: Path,
results: collection.Map[Task[_], Any],
targetDestPath: Option[Path]) = {
- targetDestPath.foreach(rm)
+
var terminalResult: upickle.Js.Value = null
val newEvaluated = mutable.Buffer.empty[Task[_]]
val newResults = mutable.LinkedHashMap.empty[Task[_], Any]