diff options
-rwxr-xr-x[-rw-r--r--] | build.sc | 34 | ||||
-rw-r--r-- | core/src/main/scala/mill/Main.scala | 81 | ||||
-rw-r--r-- | core/src/main/scala/mill/discover/Discovered.scala | 25 | ||||
-rw-r--r-- | scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala | 64 | ||||
-rw-r--r-- | scalaplugin/src/test/scala/mill/scalaplugin/MetacircularTests.scala | 16 |
5 files changed, 123 insertions, 97 deletions
@@ -1,13 +1,13 @@ -import $cp.scalaplugin.target.`scala-2.12`.classes +#!/usr/bin/env amm +import $cp.scalaplugin.target.`scala-2.12`.`mill-scalaplugin-assembly-0.1-SNAPSHOT.jar` import ammonite.ops.pwd -import coursier.{Dependency => Dep, Module => Mod} import mill.discover.Discovered import mill.eval.{Evaluator, PathRef} -import mill.scalaplugin.Subproject.ScalaDep +import mill.scalaplugin.Subproject.Dep import mill.util.OSet import mill.{T, _} import mill.scalaplugin.{TestRunner, _} - +@main def main(args: String*) = mill.Main(args, Build) object Build{ trait MillSubproject extends Subproject{ def scalaVersion = T{ "2.12.4" } @@ -16,19 +16,19 @@ object Build{ object Core extends MillSubproject { override def compileIvyDeps = T{ - Seq[ScalaDep]( - Dep(Mod("org.scala-lang", "scala-reflect"), scalaVersion(), configuration = "provided") + Seq( + Dep.Java("org.scala-lang", "scala-reflect", scalaVersion()) ) } override def ivyDeps = T{ - Seq[ScalaDep]( - ScalaDep(Dep(Mod("com.lihaoyi", "sourcecode"), "0.1.4")), - ScalaDep(Dep(Mod("com.lihaoyi", "pprint"), "0.5.3")), - ScalaDep.Point(Dep(Mod("com.lihaoyi", "ammonite"), "1.0.3")), - ScalaDep(Dep(Mod("com.typesafe.play", "play-json"), "2.6.6")), - ScalaDep(Dep(Mod("org.scala-sbt", "zinc"), "1.0.3")), - Dep(Mod("org.scala-sbt", "test-interface"), "1.0") + Seq( + Dep("com.lihaoyi", "sourcecode", "0.1.4"), + Dep("com.lihaoyi", "pprint", "0.5.3"), + Dep.Point("com.lihaoyi", "ammonite", "1.0.3"), + Dep("com.typesafe.play", "play-json", "2.6.6"), + Dep("org.scala-sbt", "zinc", "1.0.3"), + Dep.Java("org.scala-sbt", "test-interface", "1.0") ) } @@ -40,12 +40,11 @@ object Build{ def basePath = T{ pwd / 'scalaplugin } override def sources = T{ pwd/'core/'src/'test/'scala } override def ivyDeps = T{ - Seq[ScalaDep]( - ScalaDep(Dep(Mod("com.lihaoyi", "utest"), "0.6.0")) + Seq[Dep]( + Dep("com.lihaoyi", "utest", "0.6.0") ) } def test() = T.command{ - pprint.log(runDepClasspath().map(_.path.toString), height=999) TestRunner.apply( "mill.UTestFramework", runDepClasspath().map(_.path) :+ compiled().path, @@ -60,4 +59,5 @@ object Build{ override def sources = T{ pwd/'scalaplugin/'src/'main/'scala } } } -@main def main(): Any = Build -> mill.discover.Discovered[Build.type] + + diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala index 0d316530..3112ec27 100644 --- a/core/src/main/scala/mill/Main.scala +++ b/core/src/main/scala/mill/Main.scala @@ -3,18 +3,55 @@ package mill import ammonite.ops._ import ammonite.util.{Name, Res} import mill.define.Task -import mill.discover.{Discovered, NestedEntry} +import mill.discover.{CommandInfo, Discovered, Info, LabelInfo} import mill.eval.Evaluator import mill.util.OSet import play.api.libs.json.Format object Main { + def apply[T: Discovered](args: Seq[String], obj: T) = { + val Seq(selectorString, rest @_*) = args + val selector = selectorString.split('.') + val discovered = implicitly[Discovered[T]] + val consistencyErrors = Discovered.consistencyCheck(obj, discovered) + pprint.log(consistencyErrors) + if (consistencyErrors.nonEmpty) println("Failed Discovered.consistencyCheck: " + consistencyErrors) + else { + val mapping = Discovered.mapping(obj)(discovered) + val workspacePath = pwd / 'out + val evaluator = new Evaluator(workspacePath, mapping) + val mainRoutes = discovered.mains.map(x => (x.path :+ x.entryPoint.name, x: Info[T, _])) + val targetRoutes = discovered.targets.map(x => (x.path, x: Info[T, _])) + val routeList: Seq[(Seq[String], Info[T, _])] = mainRoutes ++ targetRoutes + val allRoutes = routeList.toMap[Seq[String], Info[_, _]] + allRoutes.get(selector) match{ + case Some(nestedEntryPoint: CommandInfo[T, _]) => + nestedEntryPoint.invoke( + obj, + ammonite.main.Scripts.groupArgs(rest.toList) + ) match{ + case error: mill.discover.Router.Result.Error => + println("Failed to evaluate main method: " + error) + case mill.discover.Router.Result.Success(target) => + println("Found target! " + target) + val evaluated = evaluator.evaluate(OSet(target)) + pprint.log(evaluated) + } + + case Some(labelled: LabelInfo[T, _]) => + val target = labelled.run(obj) + val evaluated = evaluator.evaluate(OSet(target)) + pprint.log(evaluated) + case None => println("Unknown selector: " + selector) + } + } + + } def main(args: Array[String]): Unit = { - val List(buildFile, selector0, rest @_*) = args.toList - pprint.log((buildFile, selector0, rest)) - val selector = selector0.split('.').toList + val List(buildFile, rest @_*) = args.toList + ammonite.Main().instantiateInterpreter() match{ case Left(problems) => pprint.log(problems) case Right(interp) => @@ -22,42 +59,8 @@ object Main { if (!result.isSuccess) println(result) else{ - val (obj, discovered) = result.asInstanceOf[Res.Success[(Any, Discovered[Any])]].s - val consistencyErrors = Discovered.consistencyCheck(obj, discovered) - pprint.log(consistencyErrors) - if (consistencyErrors.nonEmpty) println("Failed Discovered.consistencyCheck: " + consistencyErrors) - else { - val mapping = Discovered.mapping(obj)(discovered) - val workspacePath = pwd / 'out - val evaluator = new Evaluator(workspacePath, mapping) - val mainRoutes = discovered.mains.map(x => (x.path :+ x.entryPoint.name, Left(x))) - val targetRoutes = discovered.targets.map(x => x._1 -> Right(x)) - val allRoutes = (mainRoutes ++ targetRoutes).toMap[ - Seq[String], - Either[NestedEntry[Any, _], (Seq[String], Format[_], Any => Task[_])] - ] - allRoutes.get(selector) match{ - case Some(Left(nestedEntryPoint)) => - nestedEntryPoint.invoke( - obj, - ammonite.main.Scripts.groupArgs(rest.toList) - ) match{ - case error: mill.discover.Router.Result.Error => - println("Failed to evaluate main method: " + error) - case mill.discover.Router.Result.Success(target) => - println("Found target! " + target) - val evaluated = evaluator.evaluate(OSet(target)) - pprint.log(evaluated) - } - - case None => println("Unknown selector: " + selector) - case Some(Right((_, _, targetFunc))) => - val target = targetFunc(obj) - val evaluated = evaluator.evaluate(OSet(target)) - pprint.log(evaluated) - } - } + apply(rest, obj)(discovered) } } diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index 0a17dcba..3c89fbc2 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -6,36 +6,41 @@ import play.api.libs.json.Format import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context - -class Discovered[T](val targets: Seq[(Seq[String], Format[_], T => Task[_])], - val mains: Seq[NestedEntry[T, _]]){ - def apply(t: T) = targets.map{case (a, f, b) => (a, f, b(t)) } +sealed trait Info[T, V] +class Discovered[T](val targets: Seq[LabelInfo[T, _]], + val mains: Seq[CommandInfo[T, _]]){ + def apply(t: T) = targets.map{case LabelInfo(a, f, b) => (a, f, b(t)) } } case class Labelled[T](target: Task[T], format: Format[T], segments: Seq[String]) +case class LabelInfo[T, V](path: Seq[String], + format: Format[V], + run: T => Task[V]) extends Info[T, V] -case class NestedEntry[T, V](path: Seq[String], resolve: T => V, entryPoint: EntryPoint[V]){ +case class CommandInfo[T, V](path: Seq[String], + resolve: T => V, + entryPoint: EntryPoint[V]) extends Info[T, V]{ def invoke(target: T, groupedArgs: Seq[(String, Option[String])]): Result[Task[Any]] = { entryPoint.invoke(resolve(target),groupedArgs) } } -object NestedEntry{ +object CommandInfo{ def make[T, V](path: Seq[String], resolve: T => V) - (entryPoint: EntryPoint[V]) = NestedEntry(path, resolve, entryPoint) + (entryPoint: EntryPoint[V]) = CommandInfo(path, resolve, entryPoint) } object Discovered { def consistencyCheck[T](base: T, d: Discovered[T]) = { val inconsistent = for{ - (path, formatter, targetGen) <- d.targets + LabelInfo(path, formatter, targetGen) <- d.targets if targetGen(base) ne targetGen(base) } yield path inconsistent } def makeTuple[T, V](path: Seq[String], func: T => Task[V])(implicit f: Format[V]) = { - (path, f, func) + LabelInfo(path, f, func) } @@ -102,7 +107,7 @@ object Discovered { val select = segments.foldLeft[Tree](Ident(arg)) { (prefix, name) => q"$prefix.${TermName(name)}" } - q"mill.discover.NestedEntry.make(Seq(..$segments), ($arg: $tpe) => $select)($entry)" + q"mill.discover.CommandInfo.make(Seq(..$segments), ($arg: $tpe) => $select)($entry)" } c.Expr[Discovered[T]](q""" diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala b/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala index 0408833a..2dcbbe04 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala @@ -116,11 +116,11 @@ object Subproject{ def resolveDependencies(repositories: Seq[Repository], scalaVersion: String, scalaBinaryVersion: String, - deps: Seq[ScalaDep]): Seq[PathRef] = { + deps: Seq[Dep]): Seq[PathRef] = { val flattened = deps.map{ - case ScalaDep.Java(dep) => dep - case ScalaDep.Scala(dep) => dep.copy(module = dep.module.copy(name = dep.module.name + "_" + scalaBinaryVersion)) - case ScalaDep.Point(dep) => dep.copy(module = dep.module.copy(name = dep.module.name + "_" + scalaVersion)) + case Dep.Java(dep) => dep + case Dep.Scala(dep) => dep.copy(module = dep.module.copy(name = dep.module.name + "_" + scalaBinaryVersion)) + case Dep.Point(dep) => dep.copy(module = dep.module.copy(name = dep.module.name + "_" + scalaVersion)) }.toSet val start = Resolution(flattened) @@ -133,22 +133,40 @@ object Subproject{ localArtifacts.map(p => PathRef(Path(p))) } - def scalaCompilerIvyDeps(scalaVersion: String) = Seq[ScalaDep]( - Dependency(Module("org.scala-lang", "scala-compiler"), scalaVersion), - ScalaDep.Scala(Dependency(Module("org.scala-sbt", s"compiler-bridge"), "1.0.3")) + def scalaCompilerIvyDeps(scalaVersion: String) = Seq( + Dep.Java("org.scala-lang", "scala-compiler", scalaVersion), + Dep("org.scala-sbt", s"compiler-bridge", "1.0.3") ) - def scalaRuntimeIvyDeps(scalaVersion: String) = Seq[ScalaDep]( - Dependency(Module("org.scala-lang", "scala-library"), scalaVersion) + def scalaRuntimeIvyDeps(scalaVersion: String) = Seq[Dep]( + Dep.Java("org.scala-lang", "scala-library", scalaVersion) ) - sealed trait ScalaDep - object ScalaDep{ - case class Java(dep: coursier.Dependency) extends ScalaDep - implicit def default(dep: coursier.Dependency): ScalaDep = new Java(dep) + sealed trait Dep + object Dep{ + def apply(org: String, name: String, version: String): Dep = { + this(coursier.Dependency(coursier.Module(org, name), version)) + } + case class Java(dep: coursier.Dependency) extends Dep + object Java{ + def apply(org: String, name: String, version: String): Dep = { + Java(coursier.Dependency(coursier.Module(org, name), version)) + } + } + implicit def default(dep: coursier.Dependency): Dep = new Java(dep) def apply(dep: coursier.Dependency) = Scala(dep) - case class Scala(dep: coursier.Dependency) extends ScalaDep - case class Point(dep: coursier.Dependency) extends ScalaDep - implicit def formatter: Format[ScalaDep] = new Format[ScalaDep]{ - def writes(o: ScalaDep) = o match{ + case class Scala(dep: coursier.Dependency) extends Dep + object Scala{ + def apply(org: String, name: String, version: String): Dep = { + Scala(coursier.Dependency(coursier.Module(org, name), version)) + } + } + case class Point(dep: coursier.Dependency) extends Dep + object Point{ + def apply(org: String, name: String, version: String): Dep = { + Point(coursier.Dependency(coursier.Module(org, name), version)) + } + } + implicit def formatter: Format[Dep] = new Format[Dep]{ + def writes(o: Dep) = o match{ case Java(dep) => Json.obj("Java" -> Json.toJson(dep)) case Scala(dep) => Json.obj("Scala" -> Json.toJson(dep)) case Point(dep) => Json.obj("PointScala" -> Json.toJson(dep)) @@ -157,9 +175,9 @@ object Subproject{ def reads(json: JsValue) = json match{ case obj: JsObject => obj.fields match{ - case Seq(("Java", dep)) => Json.fromJson[coursier.Dependency](dep).map(Java) - case Seq(("Scala", dep)) => Json.fromJson[coursier.Dependency](dep).map(Scala) - case Seq(("PointScala", dep)) => Json.fromJson[coursier.Dependency](dep).map(Point) + case Seq(("Java", dep)) => Json.fromJson[coursier.Dependency](dep).map(Java(_)) + case Seq(("Scala", dep)) => Json.fromJson[coursier.Dependency](dep).map(Scala(_)) + case Seq(("PointScala", dep)) => Json.fromJson[coursier.Dependency](dep).map(Point(_)) case _ => JsError("Invalid JSON object to parse ScalaDep") } @@ -175,9 +193,9 @@ trait Subproject extends Cacher{ def scalaVersion: T[String] def scalaBinaryVersion = T{ scalaVersion().split('.').dropRight(1).mkString(".") } - def ivyDeps = T{ Seq[ScalaDep]() } - def compileIvyDeps = T{ Seq[ScalaDep]() } - def runIvyDeps = T{ Seq[ScalaDep]() } + def ivyDeps = T{ Seq[Dep]() } + def compileIvyDeps = T{ Seq[Dep]() } + def runIvyDeps = T{ Seq[Dep]() } def basePath: T[Path] val repositories: Seq[Repository] = Seq( diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/MetacircularTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/MetacircularTests.scala index 21640e6b..8159b8ce 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/MetacircularTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/MetacircularTests.scala @@ -5,7 +5,7 @@ import ammonite.ops.pwd import coursier.{Dependency => Dep, Module => Mod} import mill.discover.Discovered import mill.eval.{Evaluator, PathRef} -import mill.scalaplugin.Subproject.ScalaDep +import mill.scalaplugin.Subproject.Dep import mill.util.OSet import utest._ @@ -13,18 +13,18 @@ object MetacircularTests extends TestSuite{ object Core extends Subproject { def scalaVersion = T{ "2.12.4" } override def compileIvyDeps = T{ - super.compileIvyDeps() ++ Seq[ScalaDep]( + super.compileIvyDeps() ++ Seq[Dep]( Dep(Mod("org.scala-lang", "scala-reflect"), scalaVersion(), configuration = "provided") ) } override def ivyDeps = T{ - super.ivyDeps() ++ Seq[ScalaDep]( - ScalaDep(Dep(Mod("com.lihaoyi", "sourcecode"), "0.1.4")), - ScalaDep(Dep(Mod("com.lihaoyi", "pprint"), "0.5.3")), - ScalaDep.Point(Dep(Mod("com.lihaoyi", "ammonite"), "1.0.3")), - ScalaDep(Dep(Mod("com.typesafe.play", "play-json"), "2.6.6")), - ScalaDep(Dep(Mod("org.scala-sbt", "zinc"), "1.0.3")) + super.ivyDeps() ++ Seq[Dep]( + Dep(Dep(Mod("com.lihaoyi", "sourcecode"), "0.1.4")), + Dep(Dep(Mod("com.lihaoyi", "pprint"), "0.5.3")), + Dep.Point(Dep(Mod("com.lihaoyi", "ammonite"), "1.0.3")), + Dep(Dep(Mod("com.typesafe.play", "play-json"), "2.6.6")), + Dep(Dep(Mod("org.scala-sbt", "zinc"), "1.0.3")) ) } |