diff options
-rw-r--r-- | core/src/mill/define/Task.scala | 12 | ||||
-rw-r--r-- | core/src/mill/util/EnclosingClass.scala | 15 | ||||
-rw-r--r-- | core/src/mill/util/ParseArgs.scala | 33 | ||||
-rw-r--r-- | main/src/mill/main/MainModule.scala | 86 | ||||
-rw-r--r-- | main/src/mill/main/MainScopts.scala | 35 | ||||
-rw-r--r-- | main/src/mill/main/RunScript.scala | 23 |
6 files changed, 96 insertions, 108 deletions
diff --git a/core/src/mill/define/Task.scala b/core/src/mill/define/Task.scala index 230089bf..33f94453 100644 --- a/core/src/mill/define/Task.scala +++ b/core/src/mill/define/Task.scala @@ -3,23 +3,13 @@ package mill.define import ammonite.main.Router.Overrides import mill.define.Applicative.Applyable import mill.eval.{PathRef, Result} +import mill.util.EnclosingClass import sourcecode.Compat.Context import upickle.default.{ReadWriter => RW, Reader => R, Writer => W} import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context -case class EnclosingClass(value: Class[_]) -object EnclosingClass{ - def apply()(implicit c: EnclosingClass) = c.value - implicit def generate: EnclosingClass = macro impl - def impl(c: Context): c.Tree = { - import c.universe._ - val cls = c.internal.enclosingOwner.owner.asType.asClass -// q"new _root_.mill.define.EnclosingClass(classOf[$cls])" - q"new _root_.mill.define.EnclosingClass(this.getClass)" - } -} /** * Models a single node in the Mill build graph, with a list of inputs and a diff --git a/core/src/mill/util/EnclosingClass.scala b/core/src/mill/util/EnclosingClass.scala new file mode 100644 index 00000000..a69cc525 --- /dev/null +++ b/core/src/mill/util/EnclosingClass.scala @@ -0,0 +1,15 @@ +package mill.util + +import sourcecode.Compat.Context +import language.experimental.macros +case class EnclosingClass(value: Class[_]) +object EnclosingClass{ + def apply()(implicit c: EnclosingClass) = c.value + implicit def generate: EnclosingClass = macro impl + def impl(c: Context): c.Tree = { + import c.universe._ + val cls = c.internal.enclosingOwner.owner.asType.asClass + // q"new _root_.mill.define.EnclosingClass(classOf[$cls])" + q"new _root_.mill.util.EnclosingClass(this.getClass)" + } +} diff --git a/core/src/mill/util/ParseArgs.scala b/core/src/mill/util/ParseArgs.scala index 315edabc..9137923a 100644 --- a/core/src/mill/util/ParseArgs.scala +++ b/core/src/mill/util/ParseArgs.scala @@ -5,50 +5,38 @@ import mill.define.{Segment, Segments} object ParseArgs { - def apply(scriptArgs: Seq[String]) - : Either[String, (List[(Option[Segments], Segments)], Seq[String])] = { - val (selectors, args, isMultiSelectors) = extractSelsAndArgs(scriptArgs) + def apply(scriptArgs: Seq[String], + multiSelect: Boolean): Either[String, (List[(Option[Segments], Segments)], Seq[String])] = { + val (selectors, args) = extractSelsAndArgs(scriptArgs, multiSelect) for { _ <- validateSelectors(selectors) expandedSelectors <- EitherOps .sequence(selectors.map(expandBraces)) .map(_.flatten) - _ <- validateExpanded(expandedSelectors, isMultiSelectors) selectors <- EitherOps.sequence(expandedSelectors.map(extractSegments)) } yield (selectors.toList, args) } - def extractSelsAndArgs( - scriptArgs: Seq[String]): (Seq[String], Seq[String], Boolean) = { - val multiFlags = Seq("--all", "--seq") - val isMultiSelectors = scriptArgs.headOption.exists(multiFlags.contains) + def extractSelsAndArgs(scriptArgs: Seq[String], + multiSelect: Boolean): (Seq[String], Seq[String]) = { - if (isMultiSelectors) { + if (multiSelect) { val dd = scriptArgs.indexOf("--") - val selectors = (if (dd == -1) scriptArgs - else scriptArgs.take(dd)).filterNot(multiFlags.contains) + val selectors = if (dd == -1) scriptArgs else scriptArgs.take(dd) val args = if (dd == -1) Seq.empty else scriptArgs.drop(dd + 1) - (selectors, args, isMultiSelectors) + (selectors, args) } else { - (scriptArgs.take(1), scriptArgs.drop(1), isMultiSelectors) + (scriptArgs.take(1), scriptArgs.drop(1)) } } - private def validateSelectors( - selectors: Seq[String]): Either[String, Unit] = { + private def validateSelectors(selectors: Seq[String]): Either[String, Unit] = { if (selectors.isEmpty || selectors.exists(_.isEmpty)) Left("Selector cannot be empty") else Right(()) } - private def validateExpanded(expanded: Seq[String], - isMulti: Boolean): Either[String, Unit] = { - if (!isMulti && expanded.length > 1) - Left("Please use --all flag to run multiple tasks") - else Right(()) - } - def expandBraces(selectorString: String): Either[String, List[String]] = { parseBraceExpansion(selectorString) match { case f: Parsed.Failure => Left(s"Parsing exception ${f.msg}") @@ -139,5 +127,4 @@ object ParseArgs { } query.parse(input) } - } diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala index bd8befb3..3ec99f12 100644 --- a/main/src/mill/main/MainModule.scala +++ b/main/src/mill/main/MainModule.scala @@ -6,56 +6,70 @@ import pprint.{Renderer, Truncated} trait MainModule extends mill.Module{ implicit def millDiscover: mill.define.Discover[_] - implicit def millScoptTargetReads[T] = new mill.main.Tasks.Scopt[T]() + implicit def millScoptTasksReads[T] = new mill.main.Tasks.Scopt[T]() implicit def millScoptEvaluatorReads[T] = new mill.main.EvaluatorScopt[T]() - def resolve(targets: mill.main.Tasks[Any]*) = mill.T.command{ - targets.flatMap(_.value).foreach(println) + def resolve(evaluator: mill.eval.Evaluator[Any], targets: String*) = mill.T.command{ + RunScript.resolveTargets(evaluator, targets, multiSelect = true) match{ + case Left(err) => mill.eval.Result.Failure(err) + case Right(tasks) => mill.eval.Result.Success(tasks.foreach(println)) + } } - def describe(evaluator: mill.eval.Evaluator[Any], - targets: mill.main.Tasks[Any]*) = mill.T.command{ - for{ - t <- targets - target <- t.value - tree = ReplApplyHandler.pprintTask(target, evaluator) - val defaults = pprint.PPrinter() - val renderer = new Renderer( - defaults.defaultWidth, - defaults.colorApplyPrefix, - defaults.colorLiteral, - defaults.defaultIndent - ) - val rendered = renderer.rec(tree, 0, 0).iter - val truncated = new Truncated(rendered, defaults.defaultWidth, defaults.defaultHeight) - str <- truncated ++ Iterator("\n") - } { - print(str) + + def describe(evaluator: mill.eval.Evaluator[Any], targets: String*) = mill.T.command{ + RunScript.resolveTargets(evaluator, targets, multiSelect = true) match{ + case Left(err) => mill.eval.Result.Failure(err) + case Right(tasks) => + for{ + task <- tasks + tree = ReplApplyHandler.pprintTask(task, evaluator) + val defaults = pprint.PPrinter() + val renderer = new Renderer( + defaults.defaultWidth, + defaults.colorApplyPrefix, + defaults.colorLiteral, + defaults.defaultIndent + ) + val rendered = renderer.rec(tree, 0, 0).iter + val truncated = new Truncated(rendered, defaults.defaultWidth, defaults.defaultHeight) + str <- truncated ++ Iterator("\n") + } { + print(str) + } + mill.eval.Result.Success(()) } } + def all(evaluator: mill.eval.Evaluator[Any], - targets: mill.main.Tasks[Any]*) = mill.T.command{ - val (watched, res) = RunScript.evaluate( - evaluator, - mill.util.Strict.Agg.from(targets.flatMap(_.value)) - ) - Watched((), watched) + targets: String*) = mill.T.command{ + RunScript.evaluateTarget(evaluator, targets, multiSelect = true) match{ + case Left(err) => mill.eval.Result.Failure(err) + case Right((watched, Left(err))) => mill.eval.Result.Failure(err, Some(Watched((), watched))) + case Right((watched, Right(res))) => mill.eval.Result.Success(Watched((), watched)) + } } + def show(evaluator: mill.eval.Evaluator[Any], - targets: mill.main.Tasks[Any]*) = mill.T.command{ - val (watched, res) = mill.main.RunScript.evaluate( - // When using `show`, redirect all stdout of the evaluated tasks so the - // printed JSON is the only thing printed to stdout. + targets: String*) = mill.T.command{ + RunScript.evaluateTarget( evaluator.copy( + // When using `show`, redirect all stdout of the evaluated tasks so the + // printed JSON is the only thing printed to stdout. log = evaluator.log match{ case PrintLogger(c1, c2, o, i, e) => PrintLogger(c1, c2, e, i, e) case l => l } ), - mill.util.Strict.Agg.from(targets.flatMap(_.value)) - ) - for(json <- res.right.get.flatMap(_._2)){ - println(json) + targets, + multiSelect = false + ) match{ + case Left(err) => mill.eval.Result.Failure(err) + case Right((watched, Left(err))) => mill.eval.Result.Failure(err, Some(Watched((), watched))) + case Right((watched, Right(res))) => + for(json <- res.flatMap(_._2)){ + println(json) + } + mill.eval.Result.Success(Watched((), watched)) } - Watched((), watched) } } diff --git a/main/src/mill/main/MainScopts.scala b/main/src/mill/main/MainScopts.scala index acf48d05..f8f99c88 100644 --- a/main/src/mill/main/MainScopts.scala +++ b/main/src/mill/main/MainScopts.scala @@ -1,43 +1,20 @@ package mill.main -import mill.define.ExternalModule -import mill.eval.{Evaluator, PathRef} -import mill.util.ParseArgs +import mill.eval.{Evaluator} case class Tasks[T](value: Seq[mill.define.NamedTask[T]]) object Tasks{ - class Scopt[T]() - extends scopt.Read[Tasks[T]] { - def arity = 0 + class Scopt[T]() extends scopt.Read[Tasks[T]] { + def arity = 1 def reads = s => { - val rootModule = Evaluator.currentEvaluator.get.rootModule - val d = rootModule.millDiscover - val (expanded, leftover) = ParseArgs(Seq(s)).fold(e => throw new Exception(e), identity) - val resolved = expanded.map { - case (Some(scoping), segments) => - val moduleCls = rootModule.getClass.getClassLoader.loadClass(scoping.render + "$") - val externalRootModule = moduleCls.getField("MODULE$").get(moduleCls).asInstanceOf[ExternalModule] - val crossSelectors = segments.value.map { - case mill.define.Segment.Cross(x) => x.toList.map(_.toString) - case _ => Nil - } - mill.main.Resolve.resolve(segments.value.toList, externalRootModule, d, leftover, crossSelectors.toList, Nil) - case (None, segments) => - val crossSelectors = segments.value.map { - case mill.define.Segment.Cross(x) => x.toList.map(_.toString) - case _ => Nil - } - mill.main.Resolve.resolve(segments.value.toList, rootModule, d, leftover, crossSelectors.toList, Nil) - } - mill.util.EitherOps.sequence(resolved) match { - case Left(s) => throw new Exception(s) - case Right(ts) => Tasks(ts.flatten).asInstanceOf[Tasks[T]] + RunScript.resolveTargets(Evaluator.currentEvaluator.get, Seq(s), multiSelect = false) match{ + case Left(err) => throw new Exception(err) + case Right(tasks) => Tasks(tasks).asInstanceOf[Tasks[T]] } } } - } class EvaluatorScopt[T]() diff --git a/main/src/mill/main/RunScript.scala b/main/src/mill/main/RunScript.scala index bd21a821..5b5eb429 100644 --- a/main/src/mill/main/RunScript.scala +++ b/main/src/mill/main/RunScript.scala @@ -52,7 +52,7 @@ object RunScript{ val evaluated = for{ evaluator <- evalRes - (evalWatches, res) <- Res(evaluateTarget(evaluator, scriptArgs)) + (evalWatches, res) <- Res(evaluateTarget(evaluator, scriptArgs, multiSelect = false)) } yield { val alreadyStale = evalWatches.exists(p => p.sig != new PathRef(p.path, p.quick).sig) // If the file changed between the creation of the original @@ -129,11 +129,13 @@ object RunScript{ } yield (module, discover) } - def evaluateTarget[T](evaluator: Evaluator[T], scriptArgs: Seq[String]) = { + def resolveTargets[T](evaluator: Evaluator[T], + scriptArgs: Seq[String], + multiSelect: Boolean) = { for { - parsed <- ParseArgs(scriptArgs) + parsed <- ParseArgs(scriptArgs, multiSelect = multiSelect) (selectors, args) = parsed - targets <- { + taskss <- { val selected = selectors.map { case (scopedSel, sel) => val (rootModule, discover) = scopedSel match{ case None => (evaluator.rootModule, evaluator.discover) @@ -167,11 +169,14 @@ object RunScript{ } EitherOps.sequence(selected) } - } yield { - val (watched, res) = evaluate( - evaluator, - Agg.from(targets.flatten.distinct) - ) + } yield taskss.flatten + } + + def evaluateTarget[T](evaluator: Evaluator[T], + scriptArgs: Seq[String], + multiSelect: Boolean) = { + for (targets <- resolveTargets(evaluator, scriptArgs, multiSelect)) yield { + val (watched, res) = evaluate(evaluator, Agg.from(targets.distinct)) val watched2 = for{ x <- res.right.toSeq |