summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-02-09 23:42:36 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-02-09 23:42:36 -0800
commit9fe80b1f7e45e9cf6dc1f2a6586c4285e3e6103e (patch)
tree86bff40a55e2eba6afe142af0a5840084a16cc7e
parent79ac10f8d8f093477e2f96e9624be40a1d894d53 (diff)
downloadmill-9fe80b1f7e45e9cf6dc1f2a6586c4285e3e6103e.tar.gz
mill-9fe80b1f7e45e9cf6dc1f2a6586c4285e3e6103e.tar.bz2
mill-9fe80b1f7e45e9cf6dc1f2a6586c4285e3e6103e.zip
- DRY up `Resolve.scala`
- Add a version of `Resolve` that resolves names only, but works on entrypoints/etc. without needing arguments - Fix tests to compile with new `multiSelect` parsing flag
-rwxr-xr-xbuild.sc5
-rw-r--r--core/src/mill/define/Module.scala6
-rw-r--r--main/src/mill/main/MainModule.scala28
-rw-r--r--main/src/mill/main/Resolve.scala268
-rw-r--r--main/src/mill/main/RunScript.scala37
-rw-r--r--main/test/src/mill/main/MainTests.scala2
-rw-r--r--main/test/src/mill/util/ParseArgsTest.scala67
-rw-r--r--main/test/src/mill/util/ScriptTestSuite.scala2
8 files changed, 242 insertions, 173 deletions
diff --git a/build.sc b/build.sc
index 07eb543b..a80c308a 100755
--- a/build.sc
+++ b/build.sc
@@ -223,6 +223,7 @@ def gitHead = T.input{
%%('git, "rev-parse", "head")(pwd).out.string.trim()
)
}
+
def publishVersion = T.input{
val tag =
try Option(
@@ -255,7 +256,3 @@ def uploadToGithub(assembly: Path, authKey: String, release: String, label: Stri
upload.apply(assembly, release, label, authKey)
}
-
-//def resolve(targets: mill.define.TargetScopt.Targets[Any]) = mill.T.command{
-// targets.items.foreach(println)
-//} \ No newline at end of file
diff --git a/core/src/mill/define/Module.scala b/core/src/mill/define/Module.scala
index bfc15191..93537f76 100644
--- a/core/src/mill/define/Module.scala
+++ b/core/src/mill/define/Module.scala
@@ -6,13 +6,15 @@ import ammonite.ops.Path
import scala.language.experimental.macros
import scala.reflect.ClassTag
+
/**
* `Module` is a class meant to be extended by `trait`s *only*, in order to
* propagate the implicit parameters forward to the final concrete
* instantiation site so they can capture the enclosing/line information of
* the concrete instance.
*/
-class Module(implicit outerCtx0: mill.define.Ctx) extends mill.moduledefs.Cacher{ outer =>
+class Module(implicit outerCtx0: mill.define.Ctx)
+ extends mill.moduledefs.Cacher{ outer =>
/**
* Miscellaneous machinery around traversing & querying the build hierarchy,
@@ -20,7 +22,7 @@ class Module(implicit outerCtx0: mill.define.Ctx) extends mill.moduledefs.Cacher
*/
object millInternal extends Module.Internal(this)
- lazy val millModuleDirectChildren = millInternal.reflectNestedObjects[Module]
+ lazy val millModuleDirectChildren = millInternal.reflectNestedObjects[Module].toSeq
def millOuterCtx = outerCtx0
def millSourcePath: Path = millOuterCtx.millSourcePath / millOuterCtx.segment.pathSegments
implicit def millModuleExternal: Ctx.External = Ctx.External(millOuterCtx.external)
diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala
index 07ba37a9..56e43f6f 100644
--- a/main/src/mill/main/MainModule.scala
+++ b/main/src/mill/main/MainModule.scala
@@ -2,7 +2,7 @@ package mill.main
import mill.define.NamedTask
import mill.eval.{Evaluator, Result}
-import mill.util.{PrintLogger, Watched}
+import mill.util.{EitherOps, ParseArgs, PrintLogger, Watched}
import pprint.{Renderer, Truncated}
import upickle.Js
object MainModule{
@@ -30,8 +30,30 @@ trait MainModule extends mill.Module{
implicit def millScoptEvaluatorReads[T] = new mill.main.EvaluatorScopt[T]()
def resolve(evaluator: Evaluator[Any], targets: String*) = mill.T.command{
- MainModule.resolveTasks(evaluator, targets, multiSelect = true){ tasks =>
- tasks.foreach(println)
+ val resolved = for {
+ parsed <- ParseArgs(targets, multiSelect = true)
+ (selectors, args) = parsed
+ taskss <- {
+ val selected = selectors.map { case (scopedSel, sel) =>
+ val (rootModule, discover, crossSelectors) =
+ mill.main.RunScript.prepareResolve(evaluator, scopedSel, sel)
+
+ try {
+ mill.eval.Evaluator.currentEvaluator.set(evaluator)
+ mill.main.ResolveMetadata.resolve(
+ sel.value.toList, rootModule, discover,
+ args, crossSelectors.toList, Nil
+ )
+ } finally{
+ mill.eval.Evaluator.currentEvaluator.set(null)
+ }
+ }
+ EitherOps.sequence(selected)
+ }
+ } yield taskss.flatten
+ resolved match{
+ case Left(err) => throw new Exception(err)
+ case Right(r) => r.foreach(println)
}
}
diff --git a/main/src/mill/main/Resolve.scala b/main/src/mill/main/Resolve.scala
index c134d70d..507b06a3 100644
--- a/main/src/mill/main/Resolve.scala
+++ b/main/src/mill/main/Resolve.scala
@@ -4,137 +4,171 @@ import mill.define._
import mill.define.TaskModule
import ammonite.util.Res
import mill.util.Router.EntryPoint
-import mill.util.Scripts
+import mill.util.{Router, Scripts}
+
+import scala.reflect.ClassTag
+
+object ResolveMetadata extends Resolve[String]{
+ def singleModuleMeta(obj: Module, discover: Discover[_], isRootModule: Boolean) = {
+ val modules = obj.millModuleDirectChildren.map(_.toString)
+ val targets =
+ obj
+ .millInternal
+ .reflect[Target[_]]
+ .map(_.toString)
+ val commands = for{
+ (cls, entryPoints) <- discover.value
+ if cls.isAssignableFrom(obj.getClass)
+ ep <- entryPoints
+ } yield {
+ if (isRootModule) ep._2.name
+ else obj + "." + ep._2.name
+ }
+
+ modules ++ targets ++ commands
+ }
+ def endResolve(obj: Module,
+ revSelectorsSoFar: List[Segment],
+ last: String,
+ discover: Discover[_],
+ rest: Seq[String]): Either[String, List[String]] = {
+
+ val direct = singleModuleMeta(obj, discover, revSelectorsSoFar.isEmpty)
+ if (last == "__") {
+ Right(direct.toList ++ obj.millInternal.modules.flatMap(singleModuleMeta(_, discover, false)))
+ } else if (last == "_") Right(direct.toList)
+ else direct.find(_.split('.').last == last) match{
+ case None =>
+ Left(
+ "Unable to resolve " +
+ Segments((Segment.Label(last) :: revSelectorsSoFar).reverse: _*).render
+ )
+ case Some(s) => Right(List(s))
+ }
+ }
+}
+object Resolve extends Resolve[NamedTask[Any]]{
+ def endResolve(obj: Module,
+ revSelectorsSoFar: List[Segment],
+ last: String,
+ discover: Discover[_],
+ rest: Seq[String]) = {
+ val target =
+ obj
+ .millInternal
+ .reflect[Target[_]]
+ .find(_.label == last)
+ .map(Right(_))
+
+ def shimArgsig[T](a: Router.ArgSig[T, _]) = {
+ ammonite.main.Router.ArgSig[T](
+ a.name,
+ a.typeString,
+ a.doc,
+ a.default
+ )
+ }
+
+ def invokeCommand(target: Module, name: String) = for {
+ (cls, entryPoints) <- discover.value
+ if cls.isAssignableFrom(target.getClass)
+ ep <- entryPoints
+ if ep._2.name == name
+ } yield Scripts.runMainMethod(
+ target,
+ ep._2.asInstanceOf[EntryPoint[Module]],
+ ammonite.main.Scripts.groupArgs(rest.toList)
+ ) match {
+ case Res.Success(v: Command[_]) => Right(v)
+ case Res.Failure(msg) => Left(msg)
+ case Res.Exception(ex, msg) =>
+ val sw = new java.io.StringWriter()
+ ex.printStackTrace(new java.io.PrintWriter(sw))
+ val prefix = if (msg.nonEmpty) msg + "\n" else msg
+ Left(prefix + sw.toString)
+
+ }
+
+ val runDefault = for {
+ child <- obj.millInternal.reflectNestedObjects[Module]
+ if child.millOuterCtx.segment == Segment.Label(last)
+ res <- child match {
+ case taskMod: TaskModule => Some(invokeCommand(child, taskMod.defaultCommandName()).headOption)
+ case _ => None
+ }
+ } yield res
+
+ val command = invokeCommand(obj, last).headOption
+
+ command orElse target orElse runDefault.flatten.headOption match {
+ case None => Left("Cannot resolve task " +
+ Segments((Segment.Label(last) :: revSelectorsSoFar).reverse: _*).render
+ )
+ // Contents of `either` *must* be a `Task`, because we only select
+ // methods returning `Task` in the discovery process
+ case Some(either) => either.right.map(Seq(_))
+ }
+ }
-object Resolve {
- def resolve[T, V](remainingSelector: List[Segment],
- obj: mill.Module,
- discover: Discover[_],
- rest: Seq[String],
- remainingCrossSelectors: List[List[String]],
- revSelectorsSoFar: List[Segment]): Either[String, Seq[NamedTask[Any]]] = {
+}
+abstract class Resolve[R: ClassTag] {
+ def endResolve(obj: Module,
+ revSelectorsSoFar: List[Segment],
+ last: String,
+ discover: Discover[_],
+ rest: Seq[String]): Either[String, Seq[R]]
+
+ def resolve(remainingSelector: List[Segment],
+ obj: mill.Module,
+ discover: Discover[_],
+ rest: Seq[String],
+ remainingCrossSelectors: List[List[String]],
+ revSelectorsSoFar: List[Segment]): Either[String, Seq[R]] = {
remainingSelector match{
case Segment.Cross(_) :: Nil => Left("Selector cannot start with a [cross] segment")
case Segment.Label(last) :: Nil =>
- val target =
- obj
- .millInternal
- .reflect[Target[_]]
- .find(_.label == last)
- .map(Right(_))
-
- def shimArgsig[T](a: mill.util.Router.ArgSig[T, _]) = {
- ammonite.main.Router.ArgSig[T](
- a.name,
- a.typeString,
- a.doc,
- a.default
- )
- }
- def invokeCommand(target: mill.Module, name: String) = for{
- (cls, entryPoints) <- discover.value
- if cls.isAssignableFrom(target.getClass)
- ep <- entryPoints
- if ep._2.name == name
- } yield Scripts.runMainMethod(
- target,
- ep._2.asInstanceOf[EntryPoint[mill.Module]],
- ammonite.main.Scripts.groupArgs(rest.toList)
- ) match{
- case Res.Success(v: Command[_]) => Right(v)
- case Res.Failure(msg) => Left(msg)
- case Res.Exception(ex, msg) =>
- val sw = new java.io.StringWriter()
- ex.printStackTrace(new java.io.PrintWriter(sw))
- val prefix = if (msg.nonEmpty) msg + "\n" else msg
- Left(prefix + sw.toString)
-
- }
-
- val runDefault = for{
- child <- obj.millInternal.reflectNestedObjects[mill.Module]
- if child.millOuterCtx.segment == Segment.Label(last)
- res <- child match{
- case taskMod: TaskModule => Some(invokeCommand(child, taskMod.defaultCommandName()).headOption)
- case _ => None
- }
- } yield res
-
- val command = invokeCommand(obj, last).headOption
-
- command orElse target orElse runDefault.flatten.headOption match{
- case None => Left("Cannot resolve task " +
- Segments((Segment.Label(last) :: revSelectorsSoFar).reverse:_*).render
- )
- // Contents of `either` *must* be a `Task`, because we only select
- // methods returning `Task` in the discovery process
- case Some(either) => either.right.map(Seq(_))
- }
+ endResolve(obj, revSelectorsSoFar, last, discover, rest)
case head :: tail =>
val newRevSelectorsSoFar = head :: revSelectorsSoFar
+ def resolveFailureMsg = Left(
+ "Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render
+ )
+ def recurse(searchModules: Seq[Module]) = {
+ val matching = searchModules
+ .map(resolve(tail, _, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar))
+ .collect{case Right(vs) => vs}.flatten
+
+ if (matching.nonEmpty)Right(matching)
+ else resolveFailureMsg
+ }
head match{
case Segment.Label(singleLabel) =>
- if (singleLabel == "__") {
-
- val matching =
- obj.millInternal.modules
- .map(resolve(tail, _, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar))
- .collect{case Right(vs) => vs}.flatten
-
- if (matching.nonEmpty)Right(matching)
- else Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- } else if (singleLabel == "_") {
-
- val matching =
- obj.millModuleDirectChildren
- .map(resolve(tail, _, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar))
- .collect{case Right(vs) => vs}.flatten
-
- if (matching.nonEmpty)Right(matching)
- else Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- }else{
-
- obj.millInternal.reflectNestedObjects[mill.Module].find{
- _.millOuterCtx.segment == Segment.Label(singleLabel)
- } match{
- case Some(child: mill.Module) => resolve(tail, child, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
- case None => Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render)
+ recurse(
+ if (singleLabel == "__") obj.millInternal.modules
+ else if (singleLabel == "_") obj.millModuleDirectChildren.toSeq
+ else{
+ obj.millInternal.reflectNestedObjects[mill.Module]
+ .find(_.millOuterCtx.segment == Segment.Label(singleLabel))
+ .toSeq
}
- }
-
+ )
case Segment.Cross(cross) =>
obj match{
- case c: Cross[_] =>
- if(cross == Seq("__")){
- val matching =
- for ((k, v) <- c.items)
- yield resolve(tail, v.asInstanceOf[mill.Module], discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
-
- val results = matching.collect{case Right(res) => res}.flatten
-
- if (results.isEmpty) Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- else Right(results)
- } else if (cross.contains("_")){
- val matching = for {
- (k, v) <- c.items
- if k.length == cross.length
- if k.zip(cross).forall { case (l, r) => l == r || r == "_" }
- } yield resolve(tail, v.asInstanceOf[mill.Module], discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
-
- val results = matching.collect{case Right(res) => res}.flatten
-
- if (results.isEmpty) Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- else Right(results)
- }else{
- c.itemMap.get(cross.toList) match{
- case Some(m: mill.Module) => resolve(tail, m, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
- case None => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- }
- }
- case _ => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
+ case c: Cross[Module] =>
+ recurse(
+ if(cross == Seq("__")) for ((k, v) <- c.items) yield v
+ else if (cross.contains("_")){
+ for {
+ (k, v) <- c.items
+ if k.length == cross.length
+ if k.zip(cross).forall { case (l, r) => l == r || r == "_" }
+ } yield v
+ }else c.itemMap.get(cross.toList).toSeq
+ )
+ case _ => resolveFailureMsg
}
}
diff --git a/main/src/mill/main/RunScript.scala b/main/src/mill/main/RunScript.scala
index 4ee16ac3..c9155551 100644
--- a/main/src/mill/main/RunScript.scala
+++ b/main/src/mill/main/RunScript.scala
@@ -8,7 +8,7 @@ import ammonite.runtime.SpecialClassLoader
import ammonite.util.Util.CodeSource
import ammonite.util.{Name, Res, Util}
import mill.define
-import mill.define.{Discover, ExternalModule, Segment, Task}
+import mill.define._
import mill.eval.{Evaluator, PathRef, Result}
import mill.util.{EitherOps, Logger, ParseArgs, Watched}
import mill.util.Strict.Agg
@@ -137,19 +137,8 @@ object RunScript{
(selectors, args) = parsed
taskss <- {
val selected = selectors.map { case (scopedSel, sel) =>
- val (rootModule, discover) = scopedSel match{
- case None => (evaluator.rootModule, evaluator.discover)
- case Some(scoping) =>
- val moduleCls =
- evaluator.rootModule.getClass.getClassLoader.loadClass(scoping.render + "$")
-
- val rootModule = moduleCls.getField("MODULE$").get(moduleCls).asInstanceOf[ExternalModule]
- (rootModule, rootModule.millDiscover)
- }
- val crossSelectors = sel.value.map {
- case Segment.Cross(x) => x.toList.map(_.toString)
- case _ => Nil
- }
+ val (rootModule, discover, crossSelectors) =
+ prepareResolve(evaluator, scopedSel, sel)
try {
// We inject the `evaluator.rootModule` into the TargetScopt, rather
@@ -159,8 +148,7 @@ object RunScript{
// is not currently supported
mill.eval.Evaluator.currentEvaluator.set(evaluator)
mill.main.Resolve.resolve(
- sel.value.toList, rootModule,
- discover,
+ sel.value.toList, rootModule, discover,
args, crossSelectors.toList, Nil
)
} finally{
@@ -172,6 +160,23 @@ object RunScript{
} yield taskss.flatten
}
+ def prepareResolve[T](evaluator: Evaluator[T], scopedSel: Option[Segments], sel: Segments) = {
+ val (rootModule, discover) = scopedSel match {
+ case None => (evaluator.rootModule, evaluator.discover)
+ case Some(scoping) =>
+ val moduleCls =
+ evaluator.rootModule.getClass.getClassLoader.loadClass(scoping.render + "$")
+
+ val rootModule = moduleCls.getField("MODULE$").get(moduleCls).asInstanceOf[ExternalModule]
+ (rootModule, rootModule.millDiscover)
+ }
+ val crossSelectors = sel.value.map {
+ case Segment.Cross(x) => x.toList.map(_.toString)
+ case _ => Nil
+ }
+ (rootModule, discover, crossSelectors)
+ }
+
def evaluateTasks[T](evaluator: Evaluator[T],
scriptArgs: Seq[String],
multiSelect: Boolean) = {
diff --git a/main/test/src/mill/main/MainTests.scala b/main/test/src/mill/main/MainTests.scala
index 157fff6f..d4b90b2f 100644
--- a/main/test/src/mill/main/MainTests.scala
+++ b/main/test/src/mill/main/MainTests.scala
@@ -13,7 +13,7 @@ object MainTests extends TestSuite{
val expected = expected0.map(_.map(_(module)))
val resolved = for{
- selectors <- mill.util.ParseArgs(Seq(selectorString)).map(_._1.head)
+ selectors <- mill.util.ParseArgs(Seq(selectorString), multiSelect = false).map(_._1.head)
val crossSelectors = selectors._2.value.map{case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil}
task <- mill.main.Resolve.resolve(
selectors._2.value.toList, module, discover, Nil, crossSelectors.toList, Nil
diff --git a/main/test/src/mill/util/ParseArgsTest.scala b/main/test/src/mill/util/ParseArgsTest.scala
index 9121bca5..3c12525e 100644
--- a/main/test/src/mill/util/ParseArgsTest.scala
+++ b/main/test/src/mill/util/ParseArgsTest.scala
@@ -11,49 +11,48 @@ object ParseArgsTest extends TestSuite {
def check(input: Seq[String],
expectedSelectors: Seq[String],
expectedArgs: Seq[String],
- expectedIsMulti: Boolean) = {
- val (selectors, args, isMulti) = ParseArgs.extractSelsAndArgs(input)
+ multiSelect: Boolean) = {
+ val (selectors, args) = ParseArgs.extractSelsAndArgs(input, multiSelect)
assert(
selectors == expectedSelectors,
- args == expectedArgs,
- isMulti == expectedIsMulti
+ args == expectedArgs
)
}
'empty - check(input = Seq.empty,
expectedSelectors = Seq.empty,
expectedArgs = Seq.empty,
- expectedIsMulti = false)
+ multiSelect = false)
'singleSelector - check(
input = Seq("core.compile"),
expectedSelectors = Seq("core.compile"),
expectedArgs = Seq.empty,
- expectedIsMulti = false
+ multiSelect = false
)
'singleSelectorWithArgs - check(
input = Seq("application.run", "hello", "world"),
expectedSelectors = Seq("application.run"),
expectedArgs = Seq("hello", "world"),
- expectedIsMulti = false
+ multiSelect = false
)
'singleSelectorWithAllInArgs - check(
input = Seq("application.run", "hello", "world", "--all"),
expectedSelectors = Seq("application.run"),
expectedArgs = Seq("hello", "world", "--all"),
- expectedIsMulti = false
+ multiSelect = false
)
'multiSelectors - check(
input = Seq("--all", "core.jar", "core.docsJar", "core.sourcesJar"),
expectedSelectors = Seq("core.jar", "core.docsJar", "core.sourcesJar"),
expectedArgs = Seq.empty,
- expectedIsMulti = true
+ multiSelect = true
)
'multiSelectorsSeq - check(
input = Seq("--seq", "core.jar", "core.docsJar", "core.sourcesJar"),
expectedSelectors = Seq("core.jar", "core.docsJar", "core.sourcesJar"),
expectedArgs = Seq.empty,
- expectedIsMulti = true
+ multiSelect = true
)
'multiSelectorsWithArgs - check(
input = Seq("--all",
@@ -65,7 +64,7 @@ object ParseArgsTest extends TestSuite {
"world"),
expectedSelectors = Seq("core.compile", "application.runMain"),
expectedArgs = Seq("Main", "hello", "world"),
- expectedIsMulti = true
+ multiSelect = true
)
'multiSelectorsWithArgsWithAllInArgs - check(
input = Seq("--all",
@@ -77,7 +76,7 @@ object ParseArgsTest extends TestSuite {
"world"),
expectedSelectors = Seq("core.compile", "application.runMain"),
expectedArgs = Seq("Main", "--all", "world"),
- expectedIsMulti = true
+ multiSelect = true
)
}
'expandBraces - {
@@ -145,8 +144,9 @@ object ParseArgsTest extends TestSuite {
'apply - {
def check(input: Seq[String],
expectedSelectors: List[(Option[List[Segment]], List[Segment])],
- expectedArgs: Seq[String]) = {
- val Right((selectors0, args)) = ParseArgs(input)
+ expectedArgs: Seq[String],
+ multiSelect: Boolean) = {
+ val Right((selectors0, args)) = ParseArgs(input, multiSelect)
val selectors = selectors0.map{
case (Some(v1), v2) => (Some(v1.value), v2.value)
@@ -159,71 +159,79 @@ object ParseArgsTest extends TestSuite {
}
'rejectEmpty {
- assert(ParseArgs(Seq.empty) == Left("Selector cannot be empty"))
+ assert(ParseArgs(Seq.empty, multiSelect = false) == Left("Selector cannot be empty"))
}
'singleSelector - check(
input = Seq("core.compile"),
expectedSelectors = List(
None -> List(Label("core"), Label("compile"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = false
)
'externalSelector - check(
input = Seq("foo.bar/core.compile"),
expectedSelectors = List(
Some(List(Label("foo"), Label("bar"))) -> List(Label("core"), Label("compile"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = false
)
'singleSelectorWithArgs - check(
input = Seq("application.run", "hello", "world"),
expectedSelectors = List(
None -> List(Label("application"), Label("run"))
),
- expectedArgs = Seq("hello", "world")
+ expectedArgs = Seq("hello", "world"),
+ multiSelect = false
)
'singleSelectorWithCross - check(
input = Seq("bridges[2.12.4,jvm].compile"),
expectedSelectors = List(
None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("compile"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = false
)
'multiSelectorsBraceExpansion - check(
- input = Seq("--all", "{core,application}.compile"),
+ input = Seq("{core,application}.compile"),
expectedSelectors = List(
None -> List(Label("core"), Label("compile")),
None -> List(Label("application"), Label("compile"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = true
)
'multiSelectorsBraceExpansionWithArgs - check(
- input = Seq("--all", "{core,application}.run", "--", "hello", "world"),
+ input = Seq("{core,application}.run", "--", "hello", "world"),
expectedSelectors = List(
None -> List(Label("core"), Label("run")),
None -> List(Label("application"), Label("run"))
),
- expectedArgs = Seq("hello", "world")
+ expectedArgs = Seq("hello", "world"),
+ multiSelect = true
)
'multiSelectorsBraceExpansionWithCross - check(
- input = Seq("--all", "bridges[2.12.4,jvm].{test,jar}"),
+ input = Seq("bridges[2.12.4,jvm].{test,jar}"),
expectedSelectors = List(
None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("test")),
None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("jar"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = true
)
'multiSelectorsBraceExpansionInsideCross - check(
- input = Seq("--all", "bridges[{2.11.11,2.11.8}].jar"),
+ input = Seq("bridges[{2.11.11,2.11.8}].jar"),
expectedSelectors = List(
None -> List(Label("bridges"), Cross(Seq("2.11.11")), Label("jar")),
None -> List(Label("bridges"), Cross(Seq("2.11.8")), Label("jar"))
),
- expectedArgs = Seq.empty
+ expectedArgs = Seq.empty,
+ multiSelect = true
)
'multiSelectorsBraceExpansionWithoutAll - {
assert(
- ParseArgs(Seq("{core,application}.compile")) == Left(
+ ParseArgs(Seq("{core,application}.compile"), multiSelect = false) == Left(
"Please use --all flag to run multiple tasks")
)
}
@@ -233,7 +241,8 @@ object ParseArgsTest extends TestSuite {
expectedSelectors = List(
None -> List(Label("core"), Label("compile"))
),
- expectedArgs = Seq("application.compile")
+ expectedArgs = Seq("application.compile"),
+ multiSelect = false
)
}
}
diff --git a/main/test/src/mill/util/ScriptTestSuite.scala b/main/test/src/mill/util/ScriptTestSuite.scala
index 292c09be..a613d1dc 100644
--- a/main/test/src/mill/util/ScriptTestSuite.scala
+++ b/main/test/src/mill/util/ScriptTestSuite.scala
@@ -20,7 +20,7 @@ abstract class ScriptTestSuite extends TestSuite{
)
def eval(s: String*) = runner.runScript(workspacePath / "build.sc", s.toList)
def meta(s: String) = {
- val (List(selector), args) = ParseArgs.apply(Seq(s)).right.get
+ val (List(selector), args) = ParseArgs.apply(Seq(s), multiSelect = false).right.get
read(workspacePath / "out" / selector._2.value.flatMap(_.pathSegments) / "meta.json")
}