summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorandrea <andrea.peruffo1982@gmail.com>2017-11-24 18:28:16 +0000
committerandrea <andrea.peruffo1982@gmail.com>2017-11-24 18:28:16 +0000
commit407f8545636b2afd4a0495ccc5edee53f8118569 (patch)
treefde2847281cec2346bf76018759bccd1020bc355 /core
parent78ccc6b5d9973aa2cd268b7e98ba0393798a5eb4 (diff)
downloadmill-407f8545636b2afd4a0495ccc5edee53f8118569.tar.gz
mill-407f8545636b2afd4a0495ccc5edee53f8118569.tar.bz2
mill-407f8545636b2afd4a0495ccc5edee53f8118569.zip
first attempt to refactor Main.apply()
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/mill/Main.scala190
-rw-r--r--core/src/main/scala/mill/define/Cross.scala6
2 files changed, 119 insertions, 77 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala
index ef4a78a6..66034e81 100644
--- a/core/src/main/scala/mill/Main.scala
+++ b/core/src/main/scala/mill/Main.scala
@@ -22,93 +22,133 @@ object Main {
}
query.parse(input)
}
- def apply[T: Discovered](args: Seq[String],
- obj: T,
- watch: Path => Unit,
- coloredOutput: Boolean): Int = {
- val log = new Logger(coloredOutput)
+ def parseArgs(args: Seq[String]): Either[Throwable, List[scala.util.Either[String,Seq[String]]]] = {
+ import fastparse.all.Parsed
val Seq(selectorString, rest @_*) = args
- parseSelector(selectorString) match{
- case f: fastparse.all.Parsed.Failure =>
- log.error(f.msg)
- 1
- case fastparse.all.Parsed.Success(selector, idx) =>
- val discovered = implicitly[Discovered[T]]
- val consistencyErrors = Discovered.consistencyCheck(obj, discovered)
- if (consistencyErrors.nonEmpty) {
- log.error("Failed Discovered.consistencyCheck: " + consistencyErrors)
- 1
- } else {
- val mapping = Discovered.mapping(obj)(discovered)
- val workspacePath = pwd / 'out
-
- val crossSelectors = selector.collect{case Right(x) => x.toList}
- def resolve[V](selector: List[Either[String, Seq[String]]],
- hierarchy: Mirror[T, V]): Option[Task[Any]] = {
- selector match{
- case Right(_) :: Nil => ???
- case Left(last) :: Nil =>
- def target: Option[Task[Any]] =
- hierarchy.targets.find(_.label == last).map(_.run(hierarchy.node(obj, crossSelectors)))
- def command: Option[Task[Any]] = hierarchy.commands.find(_.name == last).flatMap(
- _.invoke(hierarchy.node(obj, crossSelectors), ammonite.main.Scripts.groupArgs(rest.toList)) match{
- case Router.Result.Success(v) => Some(v)
- case _ => None
- }
- )
- target orElse command
- case head :: tail =>
- head match{
- case Left(singleLabel) =>
- hierarchy.children
- .collectFirst{ case (label, child) if label == singleLabel => resolve(tail, child) }
- .flatten
- case Right(cross) =>
- resolve(tail, hierarchy.crossChildren.get._2)
- }
-
- case Nil => ???
- }
- }
- resolve(selector, discovered.mirror) match{
- case Some(target) =>
- val evaluator = new Evaluator(workspacePath, mapping, log.info)
- val evaluated = evaluator.evaluate(OSet(target))
- evaluated.transitive.foreach{
- case t: define.Source => watch(t.handle.path)
- case _ => // do nothing
- }
- val failing = evaluated.failing.items
- evaluated.failing.keyCount match{
- case 0 => // do nothing
- case n => log.error(n + " targets failed")
+ parseSelector(selectorString) match {
+ case f: Parsed.Failure =>
+ Left(new Exception("Parsing exception"+f.msg))
+ case Parsed.Success(selector, _) =>
+ Right(selector)
+ }
+ }
+
+ def resolve[T, V](
+ selector: List[Either[String, Seq[String]]],
+ hierarchy: Mirror[T, V])(implicit
+ obj: T,
+ rest: Seq[String],
+ crossSelectors: List[List[String]]): Either[Throwable, Task[Any]] = {
+
+ selector match{
+ case Right(_) :: Nil =>
+ Left(new Exception("No target or command selected"))
+ case Left(last) :: Nil =>
+ def target: Option[Task[Any]] =
+ hierarchy.targets.find(_.label == last).map(_.run(hierarchy.node(obj, crossSelectors)))
+
+ def command: Either[Throwable, Task[Any]] =
+ hierarchy.commands.find(_.name == last).map{ x =>
+ Option(hierarchy.node(obj, crossSelectors)).map(inst =>
+ x.invoke(inst, ammonite.main.Scripts.groupArgs(rest.toList)) match {
+ case Router.Result.Success(v) =>
+ Right(v)
+ case _ =>
+ Left(new Exception(s"Method not found $last"))
}
+ ).getOrElse(
+ Left(new Exception(s"Instance not found for calling $last"))
+ )
+ }.getOrElse(Left(new Exception(s"Command not found last")))
+
+ target.map(Right(_)) getOrElse command
+ case head :: tail =>
+ head match{
+ case Left(singleLabel) =>
+ hierarchy.children
+ .find{ case (label, child) => label == singleLabel }
+ .map{ case (label, child) => resolve(tail, child) }
+ .getOrElse(
+ Left(new Exception(s"Single label not found $singleLabel"))
+ )
+ case Right(cross) =>
+ resolve(tail, hierarchy.crossChildren.get._2)
+ }
+ case Nil => Left(new Exception("Nothing to run"))
+ }
+ }
- for((k, fs) <- failing){
- val ks = k match{
- case Left(t) => t.toString
- case Right(t) => t.segments.mkString(".")
- }
- val fss = fs.map{
- case Result.Exception(t) => t.toString
- case Result.Failure(t) => t
- }
- log.error(ks + " " + fss.mkString(", "))
- }
+ def discoverMirror[T: Discovered](obj: T): Either[Throwable, Discovered[T]] = {
+ val discovered = implicitly[Discovered[T]]
+ val consistencyErrors = Discovered.consistencyCheck(obj, discovered)
+ if (consistencyErrors.nonEmpty) {
+ Left(new Exception(s"Failed Discovered.consistencyCheck: $consistencyErrors"))
+ } else {
+ Right(discovered)
+ }
+ }
+
+ def evaluate(evaluator: Evaluator,
+ target: Task[Any],
+ watch: Path => Unit): Either[Throwable, Int] = {
+ val evaluated = evaluator.evaluate(OSet(target))
+ evaluated.transitive.foreach {
+ case t: define.Source => watch(t.handle.path)
+ case _ => // do nothing
+ }
- if (evaluated.failing.keyCount == 0) 0 else 1
- case None =>
- log.error("Unknown selector: " + selector.mkString("."))
- 1
- }
+ val errorStr =
+ (for((k, fs) <- evaluated.failing.items) yield {
+ val ks = k match{
+ case Left(t) => t.toString
+ case Right(t) => t.segments.mkString(".")
}
+ val fss = fs.map{
+ case Result.Exception(t) => t.toString
+ case Result.Failure(t) => t
+ }
+ s"$ks ${fss.mkString(", ")}"
+ }).mkString("\n")
+
+ evaluated.failing.keyCount match {
+ case 0 =>
+ Right(0)
+ case n =>
+ Left(new Exception(s"$n targets failed\n$errorStr"))
}
+ }
+ def apply[T: Discovered](args: Seq[String],
+ obj: T,
+ watch: Path => Unit,
+ coloredOutput: Boolean): Int = {
+
+ val log = new Logger(coloredOutput)
+ val Seq(_, rest @_*) = args
+
+ (for {
+ sel <- parseArgs(args)
+ disc <- discoverMirror(obj)
+ val crossSelectors = sel.collect{case Right(x) => x.toList}
+ target <- resolve(sel, disc.mirror)(obj, rest, crossSelectors)
+ val mapping = Discovered.mapping(obj)(disc)
+ val workspacePath = pwd / 'out
+ val evaluator = new Evaluator(workspacePath, mapping, log.info)
+ r <- evaluate(evaluator, target, watch)
+ } yield {
+ r
+ }) match {
+ case Left(err) =>
+ log.error(err.getMessage)
+ 1
+ case Right(n) =>
+ n
+ }
}
case class Config(home: ammonite.ops.Path = pwd/'out/'ammonite,
diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala
index 0ab87802..ccee459c 100644
--- a/core/src/main/scala/mill/define/Cross.scala
+++ b/core/src/main/scala/mill/define/Cross.scala
@@ -9,8 +9,10 @@ case class Cross[+T](items: List[(List[Any], T)]){
def map[V](f: T => V): Cross[V] = new Cross(items.map{case (l, v) => (l, f(v))})
def withFilter(f: T => Boolean): Cross[T] = new Cross(items.filter(t => f(t._2)))
- def apply(input: List[Any]): T = items.find(_._1 == input).get._2
+ def apply(input: List[Any]): T =
+ items.find(_._1 == input).map(_._2)
+ .getOrElse(null.asInstanceOf[T])
}
object Cross{
def apply[T](t: T*) = new Cross(t.map(i => List(i) -> i).toList)
-} \ No newline at end of file
+}