summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-12 11:28:52 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-12 11:28:52 -0800
commitb12c3f0f040a2b6caf1f94ad789d80b91313e381 (patch)
tree977a108a79d4b512e86680d058b411d919e04c6b /core/src
parentde3f16918dc5b5af6cb8bf226f3aa80ef8879bba (diff)
downloadmill-b12c3f0f040a2b6caf1f94ad789d80b91313e381.tar.gz
mill-b12c3f0f040a2b6caf1f94ad789d80b91313e381.tar.bz2
mill-b12c3f0f040a2b6caf1f94ad789d80b91313e381.zip
Rename out `Task.path` to `Task.source`, use it more aggressively to get `amm -w` watch-n-rebuild functionality working on `build.sc`
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/mill/Main.scala14
-rw-r--r--core/src/main/scala/mill/define/Task.scala42
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala21
-rw-r--r--core/src/main/scala/mill/modules/Jvm.scala2
-rw-r--r--core/src/test/scala/mill/EvaluationTests.scala8
-rw-r--r--core/src/test/scala/mill/GraphTests.scala6
-rw-r--r--core/src/test/scala/mill/JavaCompileJarTests.scala30
7 files changed, 67 insertions, 56 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala
index 3112ec27..2b33fb78 100644
--- a/core/src/main/scala/mill/Main.scala
+++ b/core/src/main/scala/mill/Main.scala
@@ -10,7 +10,7 @@ import play.api.libs.json.Format
object Main {
- def apply[T: Discovered](args: Seq[String], obj: T) = {
+ def apply[T: Discovered](args: Seq[String], obj: T, watch: Path => Unit) = {
val Seq(selectorString, rest @_*) = args
val selector = selectorString.split('.')
val discovered = implicitly[Discovered[T]]
@@ -36,7 +36,13 @@ object Main {
case mill.discover.Router.Result.Success(target) =>
println("Found target! " + target)
val evaluated = evaluator.evaluate(OSet(target))
- pprint.log(evaluated)
+
+ evaluated.transitive.foreach{
+ case t: define.Source =>
+ println("Watching " + t.handle.path)
+ watch(t.handle.path)
+ case _ => // do nothing
+ }
}
case Some(labelled: LabelInfo[T, _]) =>
@@ -46,8 +52,8 @@ object Main {
case None => println("Unknown selector: " + selector)
}
}
-
}
+
def main(args: Array[String]): Unit = {
val List(buildFile, rest @_*) = args.toList
@@ -60,7 +66,7 @@ object Main {
if (!result.isSuccess) println(result)
else{
val (obj, discovered) = result.asInstanceOf[Res.Success[(Any, Discovered[Any])]].s
- apply(rest, obj)(discovered)
+ apply(rest, obj, _ => ())(discovered)
}
}
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index c1568a8f..ea197039 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -34,10 +34,22 @@ class Command[+T](t: Task[T]) extends Task[T] {
val inputs = Seq(t)
def evaluate(args: Args) = args[T](0)
}
+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: Args) = handle
+ override def sideHash = handle.hashCode()
+ val inputs = Nil
+}
+
object Task extends Applicative.Applyer[Task, Task, Args]{
def underlying[A](v: Task[A]) = v
+ def source(path: ammonite.ops.Path) = new Source(path)
+
trait Cacher extends mill.define.Cacher[Task, Target]{
def wrapCached[T](t: Task[T], enclosing: String): Target[T] = new TargetImpl(t, enclosing)
}
@@ -47,42 +59,32 @@ object Task extends Applicative.Applyer[Task, Task, Args]{
def evaluate(args: Args) = t0
}
- implicit def apply[T](t: T): Target[T] = macro targetCachedImpl[T]
+ 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 command[T](t: T): Command[T] = macro targetCommandImpl[T]
+ def command[T](t: T): Command[T] = macro commandImpl[T]
+
def command[T](t: Task[T]): Command[T] = new Command(t)
def task[T](t: T): Task[T] = macro Applicative.impl[Task, T, Args]
def task[T](t: Task[T]): Task[T] = t
-
- def targetCommandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Command[T]] = {
+ def commandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Command[T]] = {
import c.universe._
c.Expr[Command[T]](
q"new ${weakTypeOf[Command[T]]}(${Applicative.impl[Task, T, Args](c)(t).tree})"
)
}
- def targetCachedImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Target[T]] = {
+
+ def targetImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Target[T]] = {
c.Expr[Target[T]](
mill.define.Cacher.wrapCached(c)(
Applicative.impl[Task, T, Args](c)(t).tree
)
)
}
- def targetCachedImpl2[T: c.WeakTypeTag, V: c.WeakTypeTag]
- (c: Context)
- (t: c.Expr[T])
- (f: c.Expr[T => V]): c.Expr[Target[V]] = {
- import c.universe._
- c.Expr[Target[V]](
- mill.define.Cacher.wrapCached(c)(
- q"""${Applicative.impl[Task, T, Args](c)(t).tree}.map($f)"""
- )
- )
- }
abstract class Ops[+T]{ this: Task[T] =>
def map[V](f: T => V) = new Task.Mapped(this, f)
@@ -118,13 +120,7 @@ object Task extends Applicative.Applyer[Task, Task, Args]{
val inputs = List(source1, source2)
}
- def path(path: ammonite.ops.Path) = new Path(path)
- class Path(path: ammonite.ops.Path) extends Task[PathRef]{
- def handle = PathRef(path)
- def evaluate(args: Args) = handle
- override def sideHash = handle.hashCode()
- val inputs = Nil
- }
+
def mapCtx[A, B](t: Task[A])(f: (A, Args) => B) = t.mapDest(f)
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index 54339591..e0c13044 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -13,7 +13,8 @@ class Evaluator(workspacePath: Path,
def evaluate(targets: OSet[Task[_]]): Evaluator.Results = {
mkdir(workspacePath)
- val topoSorted = Evaluator.topoSortedTransitiveTargets(targets)
+ val transitive = Evaluator.transitiveTargets(targets)
+ val topoSorted = Evaluator.topoSorted(transitive)
val sortedGroups = Evaluator.groupAroundNamedTargets(topoSorted, labeling)
val evaluated = new OSet.Mutable[Task[_]]
@@ -32,7 +33,7 @@ class Evaluator(workspacePath: Path,
}
- Evaluator.Results(targets.items.map(results), evaluated)
+ Evaluator.Results(targets.items.map(results), evaluated, transitive)
}
def evaluateGroupCached(group: OSet[Task[_]],
@@ -128,7 +129,7 @@ class Evaluator(workspacePath: Path,
object Evaluator{
class TopoSorted private[Evaluator](val values: OSet[Task[_]])
- case class Results(values: Seq[Any], targets: OSet[Task[_]])
+ case class Results(values: Seq[Any], evaluated: OSet[Task[_]], transitive: OSet[Task[_]])
def groupAroundNamedTargets(topoSortedTargets: TopoSorted,
labeling: Map[Task[_], Labelled[_]]): MultiBiMap[Int, Task[_]] = {
@@ -179,11 +180,7 @@ object Evaluator{
output
}
- /**
- * Takes the given targets, finds all the targets they transitively depend
- * on, and sort them topologically. Fails if there are dependency cycles
- */
- def topoSortedTransitiveTargets(sourceTargets: OSet[Task[_]]): TopoSorted = {
+ def transitiveTargets(sourceTargets: OSet[Task[_]]): OSet[Task[_]] = {
val transitiveTargets = new OSet.Mutable[Task[_]]
def rec(t: Task[_]): Unit = {
if (transitiveTargets.contains(t)) () // do nothing
@@ -194,6 +191,14 @@ object Evaluator{
}
sourceTargets.items.foreach(rec)
+ transitiveTargets
+ }
+ /**
+ * Takes the given targets, finds all the targets they transitively depend
+ * on, and sort them topologically. Fails if there are dependency cycles
+ */
+ def topoSorted(transitiveTargets: OSet[Task[_]]): TopoSorted = {
+
val targetIndices = transitiveTargets.items.zipWithIndex.toMap
val numberedEdges =
diff --git a/core/src/main/scala/mill/modules/Jvm.scala b/core/src/main/scala/mill/modules/Jvm.scala
index bfb7defe..f18e2d96 100644
--- a/core/src/main/scala/mill/modules/Jvm.scala
+++ b/core/src/main/scala/mill/modules/Jvm.scala
@@ -59,7 +59,7 @@ object Jvm {
Some(outputPath)
}
}
- case class jarUp(roots: Task[PathRef]*) extends Task[PathRef]{
+ def jarUp(roots: Task[PathRef]*) = new Task[PathRef]{
val inputs = roots
def evaluate(args: Args): PathRef = {
diff --git a/core/src/test/scala/mill/EvaluationTests.scala b/core/src/test/scala/mill/EvaluationTests.scala
index 0face75e..1cfc93fa 100644
--- a/core/src/test/scala/mill/EvaluationTests.scala
+++ b/core/src/test/scala/mill/EvaluationTests.scala
@@ -27,7 +27,7 @@ object EvaluationTests extends TestSuite{
// are directly evaluating tasks which need to re-evaluate every time
secondRunNoOp: Boolean = true) = {
- val Evaluator.Results(returnedValues, returnedEvaluated) = evaluator.evaluate(OSet(target))
+ val Evaluator.Results(returnedValues, returnedEvaluated, _) = evaluator.evaluate(OSet(target))
val (matchingReturnedEvaled, extra) = returnedEvaluated.items.partition(expEvaled.contains)
@@ -39,7 +39,7 @@ object EvaluationTests extends TestSuite{
// Second time the value is already cached, so no evaluation needed
if (secondRunNoOp){
- val Evaluator.Results(returnedValues2, returnedEvaluated2) = evaluator.evaluate(OSet(target))
+ val Evaluator.Results(returnedValues2, returnedEvaluated2, _) = evaluator.evaluate(OSet(target))
val expecteSecondRunEvaluated = OSet()
assert(
returnedValues2 == returnedValues,
@@ -50,7 +50,9 @@ object EvaluationTests extends TestSuite{
}
def countGroups[T: Discovered](t: T, terminals: Task[_]*) = {
val labeling = Discovered.mapping(t)
- val topoSorted = Evaluator.topoSortedTransitiveTargets(OSet.from(terminals))
+ val topoSorted = Evaluator.topoSorted(
+ Evaluator.transitiveTargets(OSet.from(terminals))
+ )
val grouped = Evaluator.groupAroundNamedTargets(topoSorted, labeling)
grouped.keyCount
}
diff --git a/core/src/test/scala/mill/GraphTests.scala b/core/src/test/scala/mill/GraphTests.scala
index 575b4a89..60895c71 100644
--- a/core/src/test/scala/mill/GraphTests.scala
+++ b/core/src/test/scala/mill/GraphTests.scala
@@ -84,7 +84,7 @@ object GraphTests extends TestSuite{
'topoSortedTransitiveTargets - {
def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = {
- val result = Evaluator.topoSortedTransitiveTargets(targets).values
+ val result = Evaluator.topoSorted(Evaluator.transitiveTargets(targets)).values
TestUtil.checkTopological(result)
assert(result == expected)
}
@@ -128,7 +128,7 @@ object GraphTests extends TestSuite{
)
)
'bigSingleTerminal - {
- val result = Evaluator.topoSortedTransitiveTargets(OSet(bigSingleTerminal.j)).values
+ val result = Evaluator.topoSorted(Evaluator.transitiveTargets(OSet(bigSingleTerminal.j))).values
TestUtil.checkTopological(result)
assert(result.size == 28)
}
@@ -140,7 +140,7 @@ object GraphTests extends TestSuite{
expected: OSet[(OSet[R], Int)]) = {
val mapping = Discovered.mapping(base)
- val topoSortedTransitive = Evaluator.topoSortedTransitiveTargets(OSet(target))
+ val topoSortedTransitive = Evaluator.topoSorted(Evaluator.transitiveTargets(OSet(target)))
val grouped = Evaluator.groupAroundNamedTargets(topoSortedTransitive, mapping)
val flattened = OSet.from(grouped.values().flatMap(_.items))
diff --git a/core/src/test/scala/mill/JavaCompileJarTests.scala b/core/src/test/scala/mill/JavaCompileJarTests.scala
index 6e398540..8272ed71 100644
--- a/core/src/test/scala/mill/JavaCompileJarTests.scala
+++ b/core/src/test/scala/mill/JavaCompileJarTests.scala
@@ -5,7 +5,7 @@ import ammonite.ops._
import ImplicitWd._
import mill.define.Task
import mill.discover.Discovered
-import mill.eval.{Evaluator, PathRef}
+import mill.eval.Evaluator
import mill.modules.Jvm.jarUp
import mill.util.OSet
import utest._
@@ -38,8 +38,8 @@ object JavaCompileJarTests extends TestSuite{
// |
// v
// resourceRoot ----> jar
- def sourceRoot = T{ Task.path(sourceRootPath) }
- def resourceRoot = T{ Task.path(resourceRootPath) }
+ def sourceRoot = T.source{ sourceRootPath }
+ def resourceRoot = T.source{ resourceRootPath }
def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) }
def classFiles = T{ compileAll(Task.ctx().dest, allSources()) }
def jar = T{ jarUp(resourceRoot, classFiles) }
@@ -56,13 +56,13 @@ object JavaCompileJarTests extends TestSuite{
val evaluated = evaluator.evaluate(OSet(t))
Tuple2(
evaluated.values(0).asInstanceOf[T],
- evaluated.targets.filter(x => mapping.contains(x) || x.isInstanceOf[mill.define.Command[_]]).size
+ evaluated.evaluated.filter(x => mapping.contains(x) || x.isInstanceOf[mill.define.Command[_]]).size
)
}
def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = {
val evaluator = new Evaluator(workspacePath, mapping)
- val evaluated = evaluator.evaluate(targets).targets.filter(mapping.contains)
+ val evaluated = evaluator.evaluate(targets).evaluated.filter(mapping.contains)
assert(evaluated == expected)
}
@@ -71,7 +71,7 @@ object JavaCompileJarTests extends TestSuite{
check(
targets = OSet(jar),
- expected = OSet(resourceRoot, sourceRoot, allSources, classFiles, jar)
+ expected = OSet(allSources, classFiles, jar)
)
// Re-running with no changes results in nothing being evaluated
@@ -84,30 +84,32 @@ object JavaCompileJarTests extends TestSuite{
// Appending whitespace forces a recompile, but the classfilesend up
// exactly the same so no re-jarring.
append(sourceRootPath / "Foo.java", " ")
- check(targets = OSet(jar), expected = OSet(sourceRoot, allSources, classFiles))
+ // Note that `sourceRoot` and `resourceRoot` never turn up in the `expected`
+ // list, because they are `Source`s not `Target`s
+ check(targets = OSet(jar), expected = OSet(/*sourceRoot, */allSources, classFiles))
// Appending a new class changes the classfiles, which forces us to
// re-create the final jar
append(sourceRootPath / "Foo.java", "\nclass FooTwo{}")
- check(targets = OSet(jar), expected = OSet(sourceRoot, allSources, classFiles, jar))
+ check(targets = OSet(jar), expected = OSet(allSources, classFiles, jar))
// Tweaking the resources forces rebuild of the final jar, without
// recompiling classfiles
append(resourceRootPath / "hello.txt", " ")
- check(targets = OSet(jar), expected = OSet(resourceRoot, jar))
+ check(targets = OSet(jar), expected = OSet(jar))
// Asking for an intermediate target forces things to be build up to that
// target only; these are re-used for any downstream targets requested
append(sourceRootPath / "Bar.java", "\nclass BarTwo{}")
append(resourceRootPath / "hello.txt", " ")
- check(targets = OSet(classFiles), expected = OSet(sourceRoot, allSources, classFiles))
- check(targets = OSet(jar), expected = OSet(resourceRoot, jar))
+ check(targets = OSet(classFiles), expected = OSet(allSources, classFiles))
+ check(targets = OSet(jar), expected = OSet(jar))
check(targets = OSet(allSources), expected = OSet())
append(sourceRootPath / "Bar.java", "\nclass BarThree{}")
append(resourceRootPath / "hello.txt", " ")
- check(targets = OSet(resourceRoot), expected = OSet(resourceRoot))
- check(targets = OSet(allSources), expected = OSet(sourceRoot, allSources))
+ check(targets = OSet(resourceRoot), expected = OSet())
+ check(targets = OSet(allSources), expected = OSet(allSources))
check(targets = OSet(jar), expected = OSet(classFiles, jar))
val jarContents = %%('jar, "-tf", workspacePath/'jar)(workspacePath).out.string
@@ -154,7 +156,7 @@ object JavaCompileJarTests extends TestSuite{
val (runOutput2, evalCount2) = eval(Build.run("test.BarFour"))
assert(
runOutput2.out.string == "New Cls!\n",
- evalCount2 == 4
+ evalCount2 == 3
)
val (runOutput3, evalCount3) = eval(Build.run("test.BarFour"))
assert(