summaryrefslogtreecommitdiff
path: root/core/src/main/scala
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-20 03:49:17 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-20 03:49:17 -0800
commitd14f56a3fd881f809e58783c49866d1491a5f3fe (patch)
tree4a9f93d3d7f69211aa444ce15837fe6e79b9db7f /core/src/main/scala
parentaebd7a144fab5bdb95f6ee4f4bc170be65cd0549 (diff)
downloadmill-d14f56a3fd881f809e58783c49866d1491a5f3fe.tar.gz
mill-d14f56a3fd881f809e58783c49866d1491a5f3fe.tar.bz2
mill-d14f56a3fd881f809e58783c49866d1491a5f3fe.zip
Swap over to simplified Mill module/source layout from SBT's
Removes a lot of useless folders and gives us a chance to exercise this simplified layout. Support for the SBT layout is still verified by our integration tests
Diffstat (limited to 'core/src/main/scala')
-rw-r--r--core/src/main/scala/mill/Main.scala83
-rw-r--r--core/src/main/scala/mill/define/Applicative.scala108
-rw-r--r--core/src/main/scala/mill/define/Cross.scala90
-rw-r--r--core/src/main/scala/mill/define/Ctx.scala69
-rw-r--r--core/src/main/scala/mill/define/Discover.scala57
-rw-r--r--core/src/main/scala/mill/define/Graph.scala61
-rw-r--r--core/src/main/scala/mill/define/Module.scala104
-rw-r--r--core/src/main/scala/mill/define/Task.scala308
-rw-r--r--core/src/main/scala/mill/define/Worker.scala32
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala285
-rw-r--r--core/src/main/scala/mill/eval/PathRef.scala70
-rw-r--r--core/src/main/scala/mill/eval/Result.scala14
-rw-r--r--core/src/main/scala/mill/eval/Tarjans.scala51
-rw-r--r--core/src/main/scala/mill/main/MainRunner.scala116
-rw-r--r--core/src/main/scala/mill/main/ParseArgs.scala142
-rw-r--r--core/src/main/scala/mill/main/ReplApplyHandler.scala124
-rw-r--r--core/src/main/scala/mill/main/Resolve.scala81
-rw-r--r--core/src/main/scala/mill/main/RunScript.scala210
-rw-r--r--core/src/main/scala/mill/modules/Jvm.scala259
-rw-r--r--core/src/main/scala/mill/modules/Util.scala26
-rw-r--r--core/src/main/scala/mill/package.scala12
-rw-r--r--core/src/main/scala/mill/util/AggWrapper.scala116
-rw-r--r--core/src/main/scala/mill/util/Ctx.scala60
-rw-r--r--core/src/main/scala/mill/util/EitherOps.scala18
-rw-r--r--core/src/main/scala/mill/util/JsonFormatters.scala42
-rw-r--r--core/src/main/scala/mill/util/Logger.scala138
-rw-r--r--core/src/main/scala/mill/util/MultiBiMap.scala55
27 files changed, 0 insertions, 2731 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala
deleted file mode 100644
index 3025994c..00000000
--- a/core/src/main/scala/mill/Main.scala
+++ /dev/null
@@ -1,83 +0,0 @@
-package mill
-
-import ammonite.main.Cli.{formatBlock, genericSignature, replSignature}
-import ammonite.ops._
-import ammonite.util.Util
-
-object Main {
- case class Config(home: ammonite.ops.Path = pwd/'out/'ammonite,
- colored: Option[Boolean] = None,
- help: Boolean = false,
- repl: Boolean = false,
- watch: Boolean = false)
-
- def main(args: Array[String]): Unit = {
-
- import ammonite.main.Cli
-
- var show = false
- val showCliArg = Cli.Arg[Cli.Config, Unit](
- "show",
- None,
- "Display the json-formatted value of the given target, if any",
- (x, _) => {
- show = true
- x
- }
- )
- val removed = Set("predef-code", "home", "no-home-predef")
- val millArgSignature = (Cli.genericSignature :+ showCliArg).filter(a => !removed(a.name))
- Cli.groupArgs(
- args.toList,
- millArgSignature,
- Cli.Config(remoteLogging = false)
- ) match{
- case Left(msg) =>
- System.err.println(msg)
- System.exit(1)
- case Right((cliConfig, _)) if cliConfig.help =>
- val leftMargin = millArgSignature.map(ammonite.main.Cli.showArg(_).length).max + 2
- System.out.println(
- s"""Mill Build Tool
- |usage: mill [mill-options] [target [target-options]]
- |
- |${formatBlock(millArgSignature, leftMargin).mkString(Util.newLine)}""".stripMargin
- )
- System.exit(0)
- case Right((cliConfig, leftoverArgs)) =>
-
- val repl = leftoverArgs.isEmpty
- val config =
- if(!repl) cliConfig
- else cliConfig.copy(
- predefCode =
- """import $file.build, build._
- |implicit val replApplyHandler = mill.main.ReplApplyHandler(
- | interp.colors(),
- | repl.pprinter(),
- | build.millSelf.get,
- | build.millDiscover
- |)
- |repl.pprinter() = replApplyHandler.pprinter
- |import replApplyHandler.generatedEval._
- |
- """.stripMargin,
- welcomeBanner = None
- )
-
- val runner = new mill.main.MainRunner(
- config, show,
- System.out, System.err, System.in
- )
- if (repl){
- runner.printInfo("Loading...")
- runner.runRepl()
- } else {
- val result = runner.runScript(pwd / "build.sc", leftoverArgs)
- System.exit(if(result) 0 else 1)
- }
- }
- }
-}
-
-
diff --git a/core/src/main/scala/mill/define/Applicative.scala b/core/src/main/scala/mill/define/Applicative.scala
deleted file mode 100644
index 69c506f7..00000000
--- a/core/src/main/scala/mill/define/Applicative.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-package mill.define
-
-import scala.annotation.{StaticAnnotation, compileTimeOnly}
-import scala.language.higherKinds
-import scala.reflect.macros.blackbox.Context
-
-/**
- * A generic Applicative-functor macro: translates calls to
- *
- * Applier.apply{ ... applyable1.apply() ... applyable2.apply() ... }
- *
- * into
- *
- * Applier.zipMap(applyable1, applyable2){ (a1, a2, ctx) => ... a1 ... a2 ... }
- */
-object Applicative {
- trait ApplyHandler[M[+_]]{
- def apply[T](t: M[T]): T
- }
- object ApplyHandler{
- @compileTimeOnly("Target#apply() can only be used with a T{...} block")
- implicit def defaultApplyHandler[M[+_]]: ApplyHandler[M] = ???
- }
- trait Applyable[M[+_], +T]{
- def self: M[T]
- def apply()(implicit handler: ApplyHandler[M]): T = handler(self)
- }
- class ImplicitStub extends StaticAnnotation
- type Id[+T] = T
-
- trait Applyer[W[_], T[_], Z[_], Ctx] extends ApplyerGenerated[T, Z, Ctx] {
- def ctx()(implicit c: Ctx) = c
- def underlying[A](v: W[A]): T[_]
-
- def zipMap[R]()(cb: Ctx => Z[R]) = mapCtx(zip()){ (_, ctx) => cb(ctx)}
- def zipMap[A, R](a: T[A])(f: (A, Ctx) => Z[R]) = mapCtx(a)(f)
- def zip(): T[Unit]
- def zip[A](a: T[A]): T[Tuple1[A]]
- }
-
- def impl[M[_], T: c.WeakTypeTag, Ctx: c.WeakTypeTag](c: Context)
- (t: c.Expr[T]): c.Expr[M[T]] = {
- impl0(c)(t.tree)(implicitly[c.WeakTypeTag[T]], implicitly[c.WeakTypeTag[Ctx]])
- }
- def impl0[M[_], T: c.WeakTypeTag, Ctx: c.WeakTypeTag](c: Context)
- (t: c.Tree): c.Expr[M[T]] = {
- import c.universe._
- def rec(t: Tree): Iterator[c.Tree] = Iterator(t) ++ t.children.flatMap(rec(_))
-
- val bound = collection.mutable.Buffer.empty[(c.Tree, ValDef)]
- val targetApplySym = typeOf[Applyable[Nothing, _]].member(TermName("apply"))
-
- // Derived from @olafurpg's
- // https://gist.github.com/olafurpg/596d62f87bf3360a29488b725fbc7608
- val defs = rec(t).filter(_.isDef).map(_.symbol).toSet
-
- val ctxName = TermName(c.freshName("ctx"))
- val ctxSym = c.internal.newTermSymbol(c.internal.enclosingOwner, ctxName)
- c.internal.setInfo(ctxSym, weakTypeOf[Ctx])
-
- val transformed = c.internal.typingTransform(t) {
- case (t @ q"$fun.apply()($handler)", api) if t.symbol == targetApplySym =>
-
- val localDefs = rec(fun).filter(_.isDef).map(_.symbol).toSet
- val banned = rec(t).filter(x => defs(x.symbol) && !localDefs(x.symbol))
-
- if (banned.hasNext){
- val banned0 = banned.next()
- c.abort(
- banned0.pos,
- "Target#apply() call cannot use `" + banned0.symbol + "` defined within the T{...} block"
- )
- }
- val tempName = c.freshName(TermName("tmp"))
- val tempSym = c.internal.newTermSymbol(c.internal.enclosingOwner, tempName)
- c.internal.setInfo(tempSym, t.tpe)
- val tempIdent = Ident(tempSym)
- c.internal.setType(tempIdent, t.tpe)
- c.internal.setFlag(tempSym, (1L << 44).asInstanceOf[c.universe.FlagSet])
- bound.append((q"${c.prefix}.underlying($fun)", c.internal.valDef(tempSym)))
- tempIdent
- case (t, api)
- if t.symbol != null
- && t.symbol.annotations.exists(_.tree.tpe =:= typeOf[ImplicitStub]) =>
-
- val tempIdent = Ident(ctxSym)
- c.internal.setType(tempIdent, t.tpe)
- c.internal.setFlag(ctxSym, (1L << 44).asInstanceOf[c.universe.FlagSet])
- tempIdent
-
- case (t, api) => api.default(t)
- }
-
- val (exprs, bindings) = bound.unzip
-
-
- val ctxBinding = c.internal.valDef(ctxSym)
-
- val callback = c.typecheck(q"(..$bindings, $ctxBinding) => $transformed ")
-
- val res = q"${c.prefix}.zipMap(..$exprs){ $callback }"
-
- c.internal.changeOwner(transformed, c.internal.enclosingOwner, callback.symbol)
-
- c.Expr[M[T]](res)
- }
-
-}
diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala
deleted file mode 100644
index b51064be..00000000
--- a/core/src/main/scala/mill/define/Cross.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package mill.define
-import language.experimental.macros
-import scala.reflect.macros.blackbox
-
-
-object Cross{
- case class Factory[T](make: (Product, mill.define.Ctx) => T)
-
- object Factory{
- implicit def make[T]: Factory[T] = macro makeImpl[T]
- def makeImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[Factory[T]] = {
- import c.universe._
- val tpe = weakTypeOf[T]
-
- val primaryConstructorArgs =
- tpe.typeSymbol.asClass.primaryConstructor.typeSignature.paramLists.head
-
- val argTupleValues =
- for((a, n) <- primaryConstructorArgs.zipWithIndex)
- yield q"v.productElement($n).asInstanceOf[${a.info}]"
-
- val instance = c.Expr[(Product, mill.define.Ctx) => T](
- q"{ (v, ctx0) => new $tpe(..$argTupleValues){ override def millOuterCtx = ctx0 } }"
- )
-
- reify { mill.define.Cross.Factory[T](instance.splice) }
- }
- }
-
- trait Resolver[-T]{
- def resolve[V <: T](c: Cross[V]): V
- }
-}
-
-/**
- * Models "cross-builds": sets of duplicate builds which differ only in the
- * value of one or more "case" variables whose values are determined at runtime.
- * Used via:
- *
- * object foo extends Cross[FooModule]("bar", "baz", "qux")
- * class FooModule(v: String) extends Module{
- * ...
- * }
- */
-class Cross[T](cases: Any*)
- (implicit ci: Cross.Factory[T],
- ctx: mill.define.Ctx) extends mill.define.Module()(ctx) {
-
- override lazy val millModuleDirectChildren =
- this.millInternal.reflectNestedObjects[Module] ++
- items.collect{case (k, v: mill.define.Module) => v}
-
- val items = for(c0 <- cases.toList) yield{
- val c = c0 match{
- case p: Product => p
- case v => Tuple1(v)
- }
- val crossValues = c.productIterator.toList
- val relPath = ctx.segment.pathSegments
- val sub = ci.make(
- c,
- ctx.copy(
- segments = ctx.segments ++ Seq(ctx.segment),
- basePath = ctx.basePath / relPath,
- segment = Segment.Cross(crossValues)
- )
- )
- (crossValues, sub)
- }
- val itemMap = items.toMap
-
- /**
- * Fetch the cross module corresponding to the given cross values
- */
- def get(args: Seq[Any]) = itemMap(args.toList)
-
- /**
- * Fetch the cross module corresponding to the given cross values
- */
- def apply(arg0: Any, args: Any*) = itemMap(arg0 :: args.toList)
-
- /**
- * Fetch the relevant cross module given the implicit resolver you have in
- * scope. This is often the first cross module whose cross-version is
- * compatible with the current module.
- */
- def apply[V >: T]()(implicit resolver: Cross.Resolver[V]): T = {
- resolver.resolve(this.asInstanceOf[Cross[V]]).asInstanceOf[T]
- }
-} \ No newline at end of file
diff --git a/core/src/main/scala/mill/define/Ctx.scala b/core/src/main/scala/mill/define/Ctx.scala
deleted file mode 100644
index 6d685521..00000000
--- a/core/src/main/scala/mill/define/Ctx.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package mill.define
-
-import ammonite.main.Router.Overrides
-import ammonite.ops.{Path, RelPath}
-
-import scala.annotation.implicitNotFound
-
-sealed trait Segment{
- def pathSegments: Seq[String] = this match{
- case Segment.Label(s) => List(s)
- case Segment.Cross(vs) => vs.map(_.toString)
- }
-}
-object Segment{
- case class Label(value: String) extends Segment
- case class Cross(value: Seq[Any]) extends Segment
-}
-
-case class BasePath(value: Path)
-
-
-/**
- * Models a path with the Mill build hierarchy, e.g.
- *
- * amm.util[2.11].test.compile
- *
- * .-separated segments are [[Segment.Label]]s, while []-delimited
- * segments are [[Segment.Cross]]s
- */
-case class Segments(value: Segment*){
- def ++(other: Seq[Segment]): Segments = Segments(value ++ other:_*)
- def ++(other: Segments): Segments = Segments(value ++ other.value:_*)
- def render = value match {
- case Nil => ""
- case Segment.Label(head) :: rest =>
- val stringSegments = rest.map{
- case Segment.Label(s) => "." + s
- case Segment.Cross(vs) => "[" + vs.mkString(",") + "]"
- }
- head + stringSegments.mkString
- }
-}
-
-@implicitNotFound("Modules, Targets and Commands can only be defined within a mill Module")
-case class Ctx(enclosing: String,
- lineNum: Int,
- segment: Segment,
- basePath: Path,
- segments: Segments,
- overrides: Int){
-}
-
-object Ctx{
- implicit def make(implicit millModuleEnclosing0: sourcecode.Enclosing,
- millModuleLine0: sourcecode.Line,
- millName0: sourcecode.Name,
- millModuleBasePath0: BasePath,
- segments0: Segments,
- overrides0: Overrides): Ctx = {
- Ctx(
- millModuleEnclosing0.value,
- millModuleLine0.value,
- Segment.Label(millName0.value),
- millModuleBasePath0.value,
- segments0,
- overrides0.value
- )
- }
-} \ No newline at end of file
diff --git a/core/src/main/scala/mill/define/Discover.scala b/core/src/main/scala/mill/define/Discover.scala
deleted file mode 100644
index 52f4ab77..00000000
--- a/core/src/main/scala/mill/define/Discover.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package mill.define
-import language.experimental.macros
-import ammonite.main.Router.EntryPoint
-
-import scala.collection.mutable
-import scala.reflect.macros.blackbox
-
-case class Discover(value: Map[Class[_], Seq[EntryPoint[_]]])
-object Discover {
- def apply[T]: Discover = macro applyImpl[T]
-
- def applyImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[Discover] = {
- import c.universe._
- import compat._
- val seen = mutable.Set.empty[Type]
- def rec(tpe: Type): Unit = {
- if (!seen(tpe)){
- seen.add(tpe)
- for{
- m <- tpe.members
- memberTpe = m.typeSignature
- if memberTpe.resultType <:< typeOf[mill.define.Module] && memberTpe.paramLists.isEmpty
- } rec(memberTpe.resultType)
-
- if (tpe <:< typeOf[mill.define.Cross[_]]){
- val inner = typeOf[Cross[_]]
- .typeSymbol
- .asClass
- .typeParams
- .head
- .asType
- .toType
- .asSeenFrom(tpe, typeOf[Cross[_]].typeSymbol)
-
- rec(inner)
- }
- }
- }
- rec(weakTypeOf[T])
-
- val router = new ammonite.main.Router(c)
- val mapping = for{
- discoveredModuleType <- seen
- val routes = router.getAllRoutesForClass(
- discoveredModuleType.asInstanceOf[router.c.Type],
- _.returnType <:< weakTypeOf[mill.define.Command[_]].asInstanceOf[router.c.Type]
- ).map(_.asInstanceOf[c.Tree])
- if routes.nonEmpty
- } yield {
- val lhs = q"classOf[${discoveredModuleType.typeSymbol.asClass}]"
- val rhs = q"scala.Seq[ammonite.main.Router.EntryPoint[${discoveredModuleType.typeSymbol.asClass}]](..$routes)"
- q"$lhs -> $rhs"
- }
-
- c.Expr[Discover](q"mill.define.Discover(scala.collection.immutable.Map(..$mapping))")
- }
-}
diff --git a/core/src/main/scala/mill/define/Graph.scala b/core/src/main/scala/mill/define/Graph.scala
deleted file mode 100644
index f06dca11..00000000
--- a/core/src/main/scala/mill/define/Graph.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package mill.define
-
-import mill.eval.Tarjans
-import mill.util.MultiBiMap
-import mill.util.Strict.Agg
-
-object Graph {
- class TopoSorted private[Graph](val values: Agg[Task[_]])
- def groupAroundImportantTargets[T](topoSortedTargets: TopoSorted)
- (important: PartialFunction[Task[_], T]): MultiBiMap[T, Task[_]] = {
-
- val output = new MultiBiMap.Mutable[T, Task[_]]()
- for ((target, t) <- topoSortedTargets.values.flatMap(t => important.lift(t).map((t, _)))) {
-
- val transitiveTargets = new Agg.Mutable[Task[_]]
- def rec(t: Task[_]): Unit = {
- if (transitiveTargets.contains(t)) () // do nothing
- else if (important.isDefinedAt(t) && t != target) () // do nothing
- else {
- transitiveTargets.append(t)
- t.inputs.foreach(rec)
- }
- }
- rec(target)
- output.addAll(t, topoSorted(transitiveTargets).values)
- }
- output
- }
-
- def transitiveTargets(sourceTargets: Agg[Task[_]]): Agg[Task[_]] = {
- val transitiveTargets = new Agg.Mutable[Task[_]]
- def rec(t: Task[_]): Unit = {
- if (transitiveTargets.contains(t)) () // do nothing
- else {
- transitiveTargets.append(t)
- t.inputs.foreach(rec)
- }
- }
-
- 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: Agg[Task[_]]): TopoSorted = {
-
- val indexed = transitiveTargets.indexed
- val targetIndices = indexed.zipWithIndex.toMap
-
- val numberedEdges =
- for(t <- transitiveTargets.items)
- yield t.inputs.collect(targetIndices)
-
- val sortedClusters = Tarjans(numberedEdges)
- val nonTrivialClusters = sortedClusters.filter(_.length > 1)
- assert(nonTrivialClusters.isEmpty, nonTrivialClusters)
- new TopoSorted(Agg.from(sortedClusters.flatten.map(indexed)))
- }
-}
diff --git a/core/src/main/scala/mill/define/Module.scala b/core/src/main/scala/mill/define/Module.scala
deleted file mode 100644
index e42ce798..00000000
--- a/core/src/main/scala/mill/define/Module.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-package mill.define
-
-import java.lang.reflect.Modifier
-
-import ammonite.main.Router.{EntryPoint, Overrides}
-import ammonite.ops.Path
-
-import scala.language.experimental.macros
-import scala.reflect.ClassTag
-import scala.reflect.macros.blackbox
-/**
- * `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 =>
-
- /**
- * Miscellaneous machinery around traversing & querying the build hierarchy,
- * that should not be needed by normal users of Mill
- */
- object millInternal extends Module.Internal(this)
-
- lazy val millModuleDirectChildren = millInternal.reflectNestedObjects[Module]
- def millOuterCtx = outerCtx0
- def basePath: Path = millOuterCtx.basePath / millOuterCtx.segment.pathSegments
- implicit def millModuleBasePath: BasePath = BasePath(basePath)
- implicit def millModuleSegments: Segments = {
- millOuterCtx.segments ++ Seq(millOuterCtx.segment)
- }
-}
-
-object Module{
- class Internal(outer: Module){
- def traverse[T](f: Module => Seq[T]): Seq[T] = {
- def rec(m: Module): Seq[T] = f(m) ++ m.millModuleDirectChildren.flatMap(rec)
- rec(outer)
- }
- lazy val segmentsToModules = traverse{m => Seq(m.millModuleSegments -> m)}
- .toMap
-
- lazy val targets = traverse{_.millInternal.reflect[Target[_]]}.toSet
-
- lazy val segmentsToTargets = targets
- .map(t => (t.ctx.segments, t))
- .toMap
-
- // Ensure we do not propagate the implicit parameters as implicits within
- // the body of any inheriting class/trait/objects, as it would screw up any
- // one else trying to use sourcecode.{Enclosing,Line} to capture debug info
- lazy val millModuleEnclosing = outer.millOuterCtx.enclosing
- lazy val millModuleLine = outer.millOuterCtx.lineNum
-
- def reflect[T: ClassTag] = {
- outer
- .getClass
- .getMethods
- .filter(!_.getName.contains('$'))
- .filter(_.getParameterCount == 0)
- .filter(x => (x.getModifiers & Modifier.STATIC) == 0)
- .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType)
- .map(_.invoke(outer).asInstanceOf[T])
- }
- def reflectNames[T: ClassTag] = {
- outer
- .getClass
- .getMethods
- .filter(x => (x.getModifiers & Modifier.STATIC) == 0)
- .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType)
- .map(_.getName)
- }
- // For some reason, this fails to pick up concrete `object`s nested directly within
- // another top-level concrete `object`. This is fine for now, since Mill's Ammonite
- // script/REPL runner always wraps user code in a wrapper object/trait
- def reflectNestedObjects[T: ClassTag] = {
- reflect[T] ++
- outer
- .getClass
- .getClasses
- .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _)
- .flatMap(c => c.getFields.find(_.getName == "MODULE$").map(_.get(c).asInstanceOf[T]))
- }
- }
-}
-trait TaskModule extends Module {
- def defaultCommandName(): String
-}
-
-class BaseModule(basePath0: Path)
- (implicit millModuleEnclosing0: sourcecode.Enclosing,
- millModuleLine0: sourcecode.Line,
- millName0: sourcecode.Name,
- overrides0: Overrides)
- extends Module()(
- mill.define.Ctx.make(implicitly, implicitly, implicitly, BasePath(basePath0), Segments(), implicitly)
- ){
- // A BaseModule should provide an empty Segments list to it's children, since
- // it is the root of the module tree, and thus must not include it's own
- // sourcecode.Name as part of the list,
- override implicit def millModuleSegments: Segments = Segments()
- override implicit def millModuleBasePath: BasePath = BasePath(millOuterCtx.basePath)
- override def basePath = millOuterCtx.basePath
-} \ No newline at end of file
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
deleted file mode 100644
index 90908e4e..00000000
--- a/core/src/main/scala/mill/define/Task.scala
+++ /dev/null
@@ -1,308 +0,0 @@
-package mill.define
-
-import mill.define.Applicative.Applyable
-import mill.eval.{PathRef, Result}
-
-import upickle.default.{ReadWriter => RW, Reader => R, Writer => W}
-
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
-
-/**
- * Models a single node in the Mill build graph, with a list of inputs and a
- * single output of type [[T]].
- *
- * Generally not instantiated manually, but instead constructed via the
- * [[Target.apply]] & similar macros.
- */
-abstract class Task[+T] extends Task.Ops[T] with Applyable[Task, T]{
- /**
- * What other Targets does this Target depend on?
- */
- val inputs: Seq[Task[_]]
-
- /**
- * Evaluate this target
- */
- def evaluate(args: mill.util.Ctx): Result[T]
-
- /**
- * Even if this target's inputs did not change, does it need to re-evaluate
- * anyway?
- */
- def sideHash: Int = 0
-
- def flushDest: Boolean = true
-
- def asTarget: Option[Target[T]] = None
- def asCommand: Option[Command[T]] = None
- def asPersistent: Option[Persistent[T]] = None
- def self = this
-}
-
-trait NamedTask[+T] extends Task[T]{
- def ctx: mill.define.Ctx
- def label = ctx.segment match{case Segment.Label(v) => v}
-}
-trait Target[+T] extends NamedTask[T]{
- override def asTarget = Some(this)
- def readWrite: RW[_]
-}
-
-object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Result, mill.util.Ctx] {
-
- implicit def apply[T](t: T)
- (implicit r: R[T],
- w: W[T],
- ctx: mill.define.Ctx): Target[T] = macro targetImpl[T]
-
- def targetImpl[T: c.WeakTypeTag](c: Context)
- (t: c.Expr[T])
- (r: c.Expr[R[T]],
- w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
- import c.universe._
- val lhs = Applicative.impl0[Task, T, mill.util.Ctx](c)(reify(Result.Success(t.splice)).tree)
-
- mill.moduledefs.Cacher.impl0[TargetImpl[T]](c)(
- reify(
- new TargetImpl[T](lhs.splice, ctx.splice, RW(w.splice.write, r.splice.read))
- )
- )
- }
-
- implicit def apply[T](t: Result[T])
- (implicit r: R[T],
- w: W[T],
- ctx: mill.define.Ctx): Target[T] = macro targetResultImpl[T]
-
- def targetResultImpl[T: c.WeakTypeTag](c: Context)
- (t: c.Expr[Result[T]])
- (r: c.Expr[R[T]],
- w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
- import c.universe._
- mill.moduledefs.Cacher.impl0[Target[T]](c)(
- reify(
- new TargetImpl[T](
- Applicative.impl0[Task, T, mill.util.Ctx](c)(t.tree).splice,
- ctx.splice,
- RW(w.splice.write, r.splice.read)
- )
- )
- )
- }
-
- def apply[T](t: Task[T])
- (implicit r: R[T],
- w: W[T],
- ctx: mill.define.Ctx): Target[T] = macro targetTaskImpl[T]
-
- def targetTaskImpl[T: c.WeakTypeTag](c: Context)
- (t: c.Expr[Task[T]])
- (r: c.Expr[R[T]],
- w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
- import c.universe._
- mill.moduledefs.Cacher.impl0[Target[T]](c)(
- reify(
- new TargetImpl[T](t.splice, ctx.splice, RW(w.splice.write, r.splice.read))
- )
- )
- }
-
- def source(value: Result[ammonite.ops.Path])
- (implicit r: R[PathRef],
- w: W[PathRef],
- ctx: mill.define.Ctx): Input[PathRef] = macro sourceImpl
-
- def sourceImpl(c: Context)
- (value: c.Expr[Result[ammonite.ops.Path]])
- (r: c.Expr[R[PathRef]],
- w: c.Expr[W[PathRef]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Input[PathRef]] = {
- import c.universe._
- val wrapped: c.Expr[Result[PathRef]] = reify(value.splice match{
- case Result.Success(p) => Result.Success(PathRef(p))
- case x: Result.Failing => x
- })
- mill.moduledefs.Cacher.impl0[Input[PathRef]](c)(
- reify(
- new Input[PathRef](
- Applicative.impl0[Task, PathRef, mill.util.Ctx](c)(wrapped.tree).splice,
- ctx.splice,
- RW(w.splice.write, r.splice.read),
- )
- )
- )
- }
-
- def input[T](value: Result[T])
- (implicit r: R[T],
- w: W[T],
- ctx: mill.define.Ctx): Input[T] = macro inputImpl[T]
-
- def inputImpl[T: c.WeakTypeTag](c: Context)
- (value: c.Expr[T])
- (r: c.Expr[R[T]],
- w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Input[T]] = {
- import c.universe._
-
- mill.moduledefs.Cacher.impl0[Input[T]](c)(
- reify(
- new Input[T](
- Applicative.impl[Task, T, mill.util.Ctx](c)(value).splice,
- ctx.splice,
- RW(w.splice.write, r.splice.read)
- )
- )
- )
- }
-
- def command[T](t: Task[T])
- (implicit ctx: mill.define.Ctx,
- w: W[T]): Command[T] = new Command(t, ctx, w)
-
- def command[T](t: Result[T])
- (implicit w: W[T],
- ctx: mill.define.Ctx): Command[T] = macro commandImpl[T]
-
- def commandImpl[T: c.WeakTypeTag](c: Context)
- (t: c.Expr[T])
- (w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Command[T]] = {
- import c.universe._
- reify(
- new Command[T](Applicative.impl[Task, T, mill.util.Ctx](c)(t).splice, ctx.splice, w.splice)
- )
- }
-
- def task[T](t: Result[T]): Task[T] = macro Applicative.impl[Task, T, mill.util.Ctx]
-
- def persistent[T](t: Result[T])(implicit r: R[T],
- w: W[T],
- ctx: mill.define.Ctx): Target[T] = macro persistentImpl[T]
-
- def persistentImpl[T: c.WeakTypeTag](c: Context)
- (t: c.Expr[T])
- (r: c.Expr[R[T]],
- w: c.Expr[W[T]],
- ctx: c.Expr[mill.define.Ctx]): c.Expr[Persistent[T]] = {
- import c.universe._
-
-
- mill.moduledefs.Cacher.impl0[Persistent[T]](c)(
- reify(
- new Persistent[T](
- Applicative.impl[Task, T, mill.util.Ctx](c)(t).splice,
- ctx.splice,
- RW(w.splice.write, r.splice.read)
- )
- )
- )
- }
-
- type TT[+X] = Task[X]
- def makeT[X](inputs0: Seq[TT[_]], evaluate0: mill.util.Ctx => Result[X]) = new Task[X] {
- val inputs = inputs0
- def evaluate(x: mill.util.Ctx) = evaluate0(x)
- }
-
- def underlying[A](v: Task[A]) = v
- def mapCtx[A, B](t: Task[A])(f: (A, mill.util.Ctx) => Result[B]) = t.mapDest(f)
- def zip() = new Task.Task0(())
- def zip[A](a: Task[A]) = a.map(Tuple1(_))
- def zip[A, B](a: Task[A], b: Task[B]) = a.zip(b)
-}
-
-case class Caller[A](value: A)
-object Caller {
- def apply[T]()(implicit c: Caller[T]) = c.value
- implicit def generate[T]: Caller[T] = macro impl[T]
- def impl[T: c.WeakTypeTag](c: Context): c.Tree = {
- import c.universe._
- q"new _root_.mill.define.Caller[${weakTypeOf[T]}](this)"
- }
-}
-
-class TargetImpl[+T](t: Task[T],
- ctx0: mill.define.Ctx,
- val readWrite: RW[_]) extends Target[T] {
- val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment))
- val inputs = Seq(t)
- def evaluate(args: mill.util.Ctx) = args[T](0)
- override def toString = ctx.enclosing + "@" + Integer.toHexString(System.identityHashCode(this))
-}
-class Command[+T](t: Task[T],
- ctx0: mill.define.Ctx,
- val writer: W[_]) extends NamedTask[T] {
- val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment))
- val inputs = Seq(t)
- def evaluate(args: mill.util.Ctx) = args[T](0)
- override def asCommand = Some(this)
-}
-class Persistent[+T](t: Task[T],
- ctx0: mill.define.Ctx,
- readWrite: RW[_])
- extends TargetImpl[T](t, ctx0, readWrite) {
-
- override def flushDest = false
- override def asPersistent = Some(this)
-}
-class Input[T](t: Task[T],
- ctx0: mill.define.Ctx,
- val readWrite: RW[_]) extends Target[T]{
- val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment))
- val inputs = Seq(t)
- def evaluate(args: mill.util.Ctx) = args[T](0)
- override def sideHash = util.Random.nextInt()
-}
-
-object Task {
-
-
-
-
- class Task0[T](t: T) extends Task[T]{
- lazy val t0 = t
- val inputs = Nil
- def evaluate(args: mill.util.Ctx) = t0
- }
-
- abstract class Ops[+T]{ this: Task[T] =>
- def map[V](f: T => V) = new Task.Mapped(this, f)
- def mapDest[V](f: (T, mill.util.Ctx) => Result[V]) = new Task.MappedDest(this, f)
-
- def filter(f: T => Boolean) = this
- def withFilter(f: T => Boolean) = this
- def zip[V](other: Task[V]) = new Task.Zipped(this, other)
-
- }
-
- def traverse[T, V](source: Seq[T])(f: T => Task[V]) = {
- new Sequence[V](source.map(f))
- }
- def sequence[T](source: Seq[Task[T]]) = new Sequence[T](source)
-
- class Sequence[+T](inputs0: Seq[Task[T]]) extends Task[Seq[T]]{
- val inputs = inputs0
- def evaluate(args: mill.util.Ctx) = {
- for (i <- 0 until args.length)
- yield args(i).asInstanceOf[T]
- }
-
- }
- class Mapped[+T, +V](source: Task[T], f: T => V) extends Task[V]{
- def evaluate(args: mill.util.Ctx) = f(args(0))
- val inputs = List(source)
- }
- class MappedDest[+T, +V](source: Task[T], f: (T, mill.util.Ctx) => Result[V]) extends Task[V]{
- def evaluate(args: mill.util.Ctx) = f(args(0), args)
- val inputs = List(source)
- }
- class Zipped[+T, +V](source1: Task[T], source2: Task[V]) extends Task[(T, V)]{
- def evaluate(args: mill.util.Ctx) = (args(0), args(1))
- val inputs = List(source1, source2)
- }
-}
diff --git a/core/src/main/scala/mill/define/Worker.scala b/core/src/main/scala/mill/define/Worker.scala
deleted file mode 100644
index 3d35d2e0..00000000
--- a/core/src/main/scala/mill/define/Worker.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package mill.define
-
-
-/**
- * Worker serves three purposes:
- *
- * - Cache in-memory state between tasks (e.g. object initialization)
- * - Including warm classloaders with isolated bytecode
- * - Mutex to limit concurrency
- * - Manage out-of-process subprocesses <-- skip this for now
- *
- * Key usage:
- *
- * - T{
- * ZincWorker().compile(a() + b())
- * }
- *
- * Desugars into:
- *
- * - T.zipMap(ZincWorker, a, b){ (z, a1, b1) => z.compile(a1, b1) }
- *
- * Workers are shoehorned into the `Task` type. This lets them fit nicely in
- * the `T{...}` syntax, as well as being statically-inspectable before
- * evaluating the task graph. The Worker defines how it is evaluated, but it's
- * evaluation/caching/lifecycle are controlled by the `Evaluator`
- */
-trait Worker[V] extends Task[V] with mill.util.Ctx.Loader[V]{
- val inputs = Nil
- def make(): V
- def evaluate(args: mill.util.Ctx) = args.load(this)
- def path = this.getClass.getCanonicalName.filter(_ != '$').split('.')
-}
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
deleted file mode 100644
index 44f24275..00000000
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ /dev/null
@@ -1,285 +0,0 @@
-package mill.eval
-
-import java.net.URLClassLoader
-
-import ammonite.ops._
-import ammonite.runtime.SpecialClassLoader
-import mill.define.{Graph, NamedTask, Segment, Segments, Target, Task}
-import mill.util
-import mill.util.Ctx.Loader
-import mill.util._
-import mill.util.Strict.Agg
-
-import scala.collection.mutable
-import scala.util.control.NonFatal
-case class Labelled[T](target: NamedTask[T],
- segments: Segments){
- def format = target match{
- case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]])
- case _ => None
- }
- def writer = target match{
- case t: mill.define.Command[T] => Some(t.writer.asInstanceOf[upickle.default.Writer[T]])
- case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]])
- case _ => None
- }
-}
-object RootModuleLoader extends Loader[mill.Module] {
- def make() = ???
-}
-class Evaluator[T](val workspacePath: Path,
- val basePath: Path,
- val rootModule: mill.Module,
- log: Logger,
- val classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){
-
-
- val workerCache = mutable.Map.empty[Ctx.Loader[_], Any]
- workerCache(RootModuleLoader) = rootModule
- def evaluate(goals: Agg[Task[_]]): Evaluator.Results = {
- mkdir(workspacePath)
-
- val transitive = Graph.transitiveTargets(goals)
- val topoSorted = Graph.topoSorted(transitive)
- val sortedGroups = Graph.groupAroundImportantTargets(topoSorted){
- case t: NamedTask[Any] =>
- val segments = t.ctx.segments
- val (finalTaskOverrides, enclosing) = t match{
- case t: Target[_] => rootModule.millInternal.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing
- case c: mill.define.Command[_] => 0 -> c.ctx.enclosing
- }
- val additional =
- if (finalTaskOverrides == t.ctx.overrides) Nil
- else Seq(Segment.Label("overriden"), Segment.Label(enclosing))
-
- Right(Labelled(t, segments ++ additional))
- case t if goals.contains(t) => Left(t)
- }
-
- val evaluated = new Agg.Mutable[Task[_]]
- val results = mutable.LinkedHashMap.empty[Task[_], Result[Any]]
-
- for (((terminal, group), i) <- sortedGroups.items().zipWithIndex){
- // Increment the counter message by 1 to go from 1/10 to 10/10 instead of 0/10 to 9/10
- val counterMsg = (i+1) + "/" + sortedGroups.keyCount
- val (newResults, newEvaluated) = evaluateGroupCached(terminal, group, results, counterMsg)
- for(ev <- newEvaluated){
- evaluated.append(ev)
- }
- for((k, v) <- newResults) results.put(k, v)
-
- }
-
- val failing = new util.MultiBiMap.Mutable[Either[Task[_], Labelled[_]], Result.Failing]
- for((k, vs) <- sortedGroups.items()){
- failing.addAll(k, vs.items.flatMap(results.get).collect{case f: Result.Failing => f})
- }
- Evaluator.Results(
- goals.indexed.map(results),
- evaluated,
- transitive,
- failing,
- results
- )
- }
-
-
- def evaluateGroupCached(terminal: Either[Task[_], Labelled[_]],
- group: Agg[Task[_]],
- results: collection.Map[Task[_], Result[Any]],
- counterMsg: String): (collection.Map[Task[_], Result[Any]], Seq[Task[_]]) = {
-
-
- val externalInputs = group.items.flatMap(_.inputs).filter(!group.contains(_))
-
- val inputsHash =
- externalInputs.map(results).toVector.hashCode +
- group.toIterator.map(_.sideHash).toVector.hashCode() +
- classLoaderSig.hashCode()
-
- terminal match{
- case Left(task) =>
- evaluateGroup(
- group,
- results,
- groupBasePath = None,
- paths = None,
- maybeTargetLabel = None,
- counterMsg = counterMsg
- )
- case Right(labelledTarget) =>
- val paths = Evaluator.resolveDestPaths(workspacePath, labelledTarget.segments)
- val groupBasePath = basePath / Evaluator.makeSegmentStrings(labelledTarget.segments)
- mkdir(paths.out)
- val cached = for{
- json <- scala.util.Try(upickle.json.read(read(paths.meta))).toOption
- (cachedHash, terminalResult) <- scala.util.Try(upickle.default.readJs[(Int, upickle.Js.Value)](json)).toOption
- if cachedHash == inputsHash
- reader <- labelledTarget.format
- parsed <- reader.read.lift(terminalResult)
- } yield parsed
-
- cached match{
- case Some(parsed) =>
- val newResults = mutable.LinkedHashMap.empty[Task[_], Result[Any]]
- newResults(labelledTarget.target) = parsed
- (newResults, Nil)
-
- case _ =>
-
- val Seq(first, rest @_*) = labelledTarget.segments.value
- val msgParts = Seq(first.asInstanceOf[Segment.Label].value) ++ rest.map{
- case Segment.Label(s) => "." + s
- case Segment.Cross(s) => "[" + s.mkString(",") + "]"
- }
-
- if (labelledTarget.target.flushDest) rm(paths.dest)
- val (newResults, newEvaluated) = evaluateGroup(
- group,
- results,
- groupBasePath = Some(groupBasePath),
- paths = Some(paths),
- maybeTargetLabel = Some(msgParts.mkString),
- counterMsg = counterMsg
- )
-
- newResults(labelledTarget.target) match{
- case Result.Success(v) =>
- val terminalResult = labelledTarget
- .writer
- .asInstanceOf[Option[upickle.default.Writer[Any]]]
- .map(_.write(v))
-
- for(t <- terminalResult){
- write.over(paths.meta, upickle.default.write(inputsHash -> t, indent = 4))
- }
- case _ =>
- // Wipe out any cached meta.json file that exists, so
- // a following run won't look at the cached metadata file and
- // assume it's associated with the possibly-borked state of the
- // destPath after an evaluation failure.
- rm(paths.meta)
- }
-
-
-
- (newResults, newEvaluated)
- }
- }
- }
-
-
- def evaluateGroup(group: Agg[Task[_]],
- results: collection.Map[Task[_], Result[Any]],
- groupBasePath: Option[Path],
- paths: Option[Evaluator.Paths],
- maybeTargetLabel: Option[String],
- counterMsg: String) = {
-
-
- val newEvaluated = mutable.Buffer.empty[Task[_]]
- val newResults = mutable.LinkedHashMap.empty[Task[_], Result[Any]]
-
- val nonEvaluatedTargets = group.indexed.filterNot(results.contains)
-
- maybeTargetLabel.foreach { targetLabel =>
- val inputResults = for {
- target <- nonEvaluatedTargets
- item <- target.inputs.filterNot(group.contains)
- } yield results(item)
-
- val logRun = inputResults.forall(_.isInstanceOf[Result.Success[_]])
-
- if(logRun) { log.ticker(s"[$counterMsg] $targetLabel ") }
- }
-
- val multiLogger = resolveLogger(paths.map(_.log))
-
- for (target <- nonEvaluatedTargets) {
-
- newEvaluated.append(target)
- val targetInputValues = target.inputs
- .map(x => newResults.getOrElse(x, results(x)))
- .collect{ case Result.Success(v) => v }
-
- val res =
- if (targetInputValues.length != target.inputs.length) Result.Skipped
- else {
- val args = new Ctx(
- targetInputValues.toArray[Any],
- paths.map(_.dest).orNull,
- groupBasePath.orNull,
- multiLogger,
- new Ctx.LoaderCtx{
- def load[T](x: Ctx.Loader[T]): T = {
- workerCache.getOrElseUpdate(x, x.make()).asInstanceOf[T]
- }
- }
- )
-
- val out = System.out
- val err = System.err
- try{
- System.setErr(multiLogger.errorStream)
- System.setOut(multiLogger.outputStream)
- Console.withOut(multiLogger.outputStream){
- Console.withErr(multiLogger.errorStream){
- target.evaluate(args)
- }
- }
- }catch{ case NonFatal(e) =>
- val currentStack = new Exception().getStackTrace
- Result.Exception(e, currentStack)
- }finally{
- System.setErr(err)
- System.setOut(out)
- }
- }
-
- newResults(target) = res
- }
-
- multiLogger.close()
-
- (newResults, newEvaluated)
- }
-
- def resolveLogger(logPath: Option[Path]): Logger = logPath match{
- case None => log
- case Some(path) =>
- rm(path)
- MultiLogger(log.colored, log, FileLogger(log.colored, path))
- }
-}
-
-
-object Evaluator{
- case class Paths(out: Path,
- dest: Path,
- meta: Path,
- log: Path)
- def makeSegmentStrings(segments: Segments) = segments.value.flatMap{
- case Segment.Label(s) => Seq(s)
- case Segment.Cross(values) => values.map(_.toString)
- }
- def resolveDestPaths(workspacePath: Path, segments: Segments): Paths = {
- val segmentStrings = makeSegmentStrings(segments)
- val targetPath = workspacePath / segmentStrings
- Paths(targetPath, targetPath / 'dest, targetPath / "meta.json", targetPath / 'log)
- }
-
- // check if the build itself has changed
- def classLoaderSig = Thread.currentThread().getContextClassLoader match {
- case scl: SpecialClassLoader => scl.classpathSignature
- case ucl: URLClassLoader => SpecialClassLoader.initialClasspathSignature(ucl)
- case _ => Nil
-
- }
- case class Results(rawValues: Seq[Result[Any]],
- evaluated: Agg[Task[_]],
- transitive: Agg[Task[_]],
- failing: MultiBiMap[Either[Task[_], Labelled[_]], Result.Failing],
- results: collection.Map[Task[_], Result[Any]]){
- def values = rawValues.collect{case Result.Success(v) => v}
- }
-}
diff --git a/core/src/main/scala/mill/eval/PathRef.scala b/core/src/main/scala/mill/eval/PathRef.scala
deleted file mode 100644
index 0a629a14..00000000
--- a/core/src/main/scala/mill/eval/PathRef.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package mill.eval
-
-import java.io.IOException
-import java.nio.file.attribute.BasicFileAttributes
-import java.nio.file.{FileVisitResult, FileVisitor}
-import java.nio.{file => jnio}
-import java.security.MessageDigest
-import upickle.default.{ReadWriter => RW}
-import ammonite.ops.Path
-import mill.util.JsonFormatters
-
-
-/**
- * A wrapper around `ammonite.ops.Path` that calculates it's hashcode based
- * on the contents of the filesystem underneath it. Used to ensure filesystem
- * changes can bust caches which are keyed off hashcodes.
- */
-case class PathRef(path: ammonite.ops.Path, quick: Boolean = false){
- val sig = {
- val digest = MessageDigest.getInstance("MD5")
-
- val buffer = new Array[Byte](16 * 1024)
- jnio.Files.walkFileTree(
- path.toNIO,
- new FileVisitor[jnio.Path] {
- def preVisitDirectory(dir: jnio.Path, attrs: BasicFileAttributes) = {
- digest.update(dir.toAbsolutePath.toString.getBytes)
- FileVisitResult.CONTINUE
- }
-
- def visitFile(file: jnio.Path, attrs: BasicFileAttributes) = {
- digest.update(file.toAbsolutePath.toString.getBytes)
- if (quick){
- val value = (path.mtime.toMillis, path.size).hashCode()
- digest.update((value >>> 24).toByte)
- digest.update((value >>> 16).toByte)
- digest.update((value >>> 8).toByte)
- digest.update(value.toByte)
- }else {
- val is = jnio.Files.newInputStream(file)
-
- def rec(): Unit = {
- val length = is.read(buffer)
- if (length != -1) {
- digest.update(buffer, 0, length)
- rec()
- }
- }
- rec()
-
- is.close()
- }
- FileVisitResult.CONTINUE
- }
-
- def visitFileFailed(file: jnio.Path, exc: IOException) = FileVisitResult.CONTINUE
- def postVisitDirectory(dir: jnio.Path, exc: IOException) = FileVisitResult.CONTINUE
- }
- )
-
- java.util.Arrays.hashCode(digest.digest())
-
- }
- override def hashCode() = sig
-}
-
-object PathRef{
- private implicit val pathFormat: RW[Path] = JsonFormatters.pathReadWrite
- implicit def jsonFormatter: RW[PathRef] = upickle.default.macroRW
-}
diff --git a/core/src/main/scala/mill/eval/Result.scala b/core/src/main/scala/mill/eval/Result.scala
deleted file mode 100644
index a9b2c70b..00000000
--- a/core/src/main/scala/mill/eval/Result.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package mill.eval
-
-sealed trait Result[+T]
-object Result{
- implicit def create[T](t: => T): Result[T] = {
- try Success(t)
- catch { case e: Throwable => Exception(e, new java.lang.Exception().getStackTrace) }
- }
- case class Success[T](value: T) extends Result[T]
- case object Skipped extends Result[Nothing]
- sealed trait Failing extends Result[Nothing]
- case class Failure(msg: String) extends Failing
- case class Exception(throwable: Throwable, outerStack: Seq[StackTraceElement]) extends Failing
-} \ No newline at end of file
diff --git a/core/src/main/scala/mill/eval/Tarjans.scala b/core/src/main/scala/mill/eval/Tarjans.scala
deleted file mode 100644
index ade335a9..00000000
--- a/core/src/main/scala/mill/eval/Tarjans.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package mill.eval
-
-import scala.collection.mutable
-
-// Adapted from
-// https://github.com/indy256/codelibrary/blob/c52247216258e84aac442a23273b7d8306ef757b/java/src/SCCTarjan.java
-object Tarjans {
- def apply(graph0: TraversableOnce[TraversableOnce[Int]]): Seq[Seq[Int]] = {
- val graph = graph0.map(_.toArray).toArray
- val n = graph.length
- val visited = new Array[Boolean](n)
- val stack = mutable.ArrayBuffer.empty[Integer]
- var time = 0
- val lowlink = new Array[Int](n)
- val components = mutable.ArrayBuffer.empty[Seq[Int]]
-
-
- for (u <- 0 until n) {
- if (!visited(u)) dfs(u)
- }
-
- def dfs(u: Int): Unit = {
- lowlink(u) = time
- time += 1
- visited(u) = true
- stack.append(u)
- var isComponentRoot = true
- for (v <- graph(u)) {
- if (!visited(v)) dfs(v)
- if (lowlink(u) > lowlink(v)) {
- lowlink(u) = lowlink(v)
- isComponentRoot = false
- }
- }
- if (isComponentRoot) {
- val component = mutable.Buffer.empty[Int]
-
- var done = false
- while (!done) {
- val x = stack.last
- stack.remove(stack.length - 1)
- component.append(x)
- lowlink(x) = Integer.MAX_VALUE
- if (x == u) done = true
- }
- components.append(component)
- }
- }
- components
- }
-}
diff --git a/core/src/main/scala/mill/main/MainRunner.scala b/core/src/main/scala/mill/main/MainRunner.scala
deleted file mode 100644
index 5281b886..00000000
--- a/core/src/main/scala/mill/main/MainRunner.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package mill.main
-import java.io.{InputStream, OutputStream, PrintStream}
-
-import ammonite.Main
-import ammonite.interp.{Interpreter, Preprocessor}
-import ammonite.ops.Path
-import ammonite.util._
-import mill.define.Discover
-import mill.eval.{Evaluator, PathRef}
-import mill.util.PrintLogger
-import upickle.Js
-
-/**
- * Customized version of [[ammonite.MainRunner]], allowing us to run Mill
- * `build.sc` scripts with mill-specific tweaks such as a custom
- * `scriptCodeWrapper` or with a persistent evaluator between runs.
- */
-class MainRunner(config: ammonite.main.Cli.Config,
- show: Boolean,
- outprintStream: PrintStream,
- errPrintStream: PrintStream,
- stdIn: InputStream)
- extends ammonite.MainRunner(
- config, outprintStream, errPrintStream,
- stdIn, outprintStream, errPrintStream
- ){
- var lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_], Discover)] = None
-
- override def runScript(scriptPath: Path, scriptArgs: List[String]) =
- watchLoop(
- isRepl = false,
- printing = true,
- mainCfg => {
- val (result, interpWatched) = RunScript.runScript(
- mainCfg.wd,
- scriptPath,
- mainCfg.instantiateInterpreter(),
- scriptArgs,
- lastEvaluator,
- new PrintLogger(
- colors != ammonite.util.Colors.BlackWhite,
- colors,
- if (show) errPrintStream else outprintStream,
- errPrintStream,
- errPrintStream
- )
- )
-
- result match{
- case Res.Success(data) =>
- val (eval, discover, evaluationWatches, res) = data
-
- lastEvaluator = Some((interpWatched, eval, discover))
-
- (Res(res), interpWatched ++ evaluationWatches)
- case _ => (result, interpWatched)
- }
- }
- )
-
- override def handleWatchRes[T](res: Res[T], printing: Boolean) = {
- res match{
- case Res.Success(value) =>
- if (show){
- for(json <- value.asInstanceOf[Seq[Js.Value]]){
- outprintStream.println(json)
- }
- }
-
- true
-
- case _ => super.handleWatchRes(res, printing)
- }
-
- }
- override def initMain(isRepl: Boolean) = {
- super.initMain(isRepl).copy(
- scriptCodeWrapper = CustomCodeWrapper,
- // Ammonite does not properly forward the wd from CliConfig to Main, so
- // force forward it outselves
- wd = config.wd
- )
- }
- object CustomCodeWrapper extends Preprocessor.CodeWrapper {
- def top(pkgName: Seq[Name], imports: Imports, indexedWrapperName: Name) = {
- val wrapName = indexedWrapperName.backticked
- s"""
- |package ${pkgName.head.encoded}
- |package ${Util.encodeScalaSourcePath(pkgName.tail)}
- |$imports
- |import mill._
- |
- |object $wrapName extends mill.define.BaseModule(ammonite.ops.Path(${pprint.Util.literalize(config.wd.toString)})) with $wrapName{
- | // Stub to make sure Ammonite has something to call after it evaluates a script,
- | // even if it does nothing...
- | def $$main() = Iterator[String]()
- |
- | val millDiscover: mill.define.Discover = mill.define.Discover[this.type]
- | // Need to wrap the returned Module in Some(...) to make sure it
- | // doesn't get picked up during reflective child-module discovery
- | val millSelf = Some(this)
- |}
- |
- |sealed trait $wrapName extends mill.Module{
- |""".stripMargin
- }
-
-
- def bottom(printCode: String, indexedWrapperName: Name, extraCode: String) = {
- // We need to disable the `$main` method definition inside the wrapper class,
- // because otherwise it might get picked up by Ammonite and run as a static
- // class method, which blows up since it's defined as an instance method
- "\n}"
- }
- }
-}
diff --git a/core/src/main/scala/mill/main/ParseArgs.scala b/core/src/main/scala/mill/main/ParseArgs.scala
deleted file mode 100644
index dc848418..00000000
--- a/core/src/main/scala/mill/main/ParseArgs.scala
+++ /dev/null
@@ -1,142 +0,0 @@
-package mill.main
-
-import mill.util.EitherOps
-import fastparse.all._
-import mill.define.Segment
-
-object ParseArgs {
-
- def apply(scriptArgs: Seq[String])
- : Either[String, (List[List[Segment]], Seq[String])] = {
- val (selectors, args, isMultiSelectors) = extractSelsAndArgs(scriptArgs)
- 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)
-
- if (isMultiSelectors) {
- val dd = scriptArgs.indexOf("--")
- val selectors = (if (dd == -1) scriptArgs
- else scriptArgs.take(dd)).filterNot(multiFlags.contains)
- val args = if (dd == -1) Seq.empty else scriptArgs.drop(dd + 1)
-
- (selectors, args, isMultiSelectors)
- } else {
- (scriptArgs.take(1), scriptArgs.drop(1), isMultiSelectors)
- }
- }
-
- 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}")
- case Parsed.Success(expanded, _) => Right(expanded.toList)
- }
- }
-
- private sealed trait Fragment
- private object Fragment {
- case class Keep(value: String) extends Fragment
- case class Expand(values: List[List[Fragment]]) extends Fragment
-
- def unfold(fragments: List[Fragment]): Seq[String] = {
- fragments match {
- case head :: rest =>
- val prefixes = head match {
- case Keep(v) => Seq(v)
- case Expand(Nil) => Seq("{}")
- case Expand(List(vs)) => unfold(vs).map("{" + _ + "}")
- case Expand(vss) => vss.flatMap(unfold)
- }
- for {
- prefix <- prefixes
- suffix <- unfold(rest)
- } yield prefix + suffix
-
- case Nil => Seq("")
- }
- }
- }
-
- private object BraceExpansionParser {
- val plainChars =
- P(CharsWhile(c => c != ',' && c != '{' && c != '}')).!.map(Fragment.Keep)
-
- val toExpand: P[Fragment] =
- P("{" ~ braceParser.rep(1).rep(sep = ",") ~ "}").map(
- x => Fragment.Expand(x.toList.map(_.toList))
- )
-
- val braceParser = P(toExpand | plainChars)
-
- val parser = P(braceParser.rep(1).rep(sep = ",") ~ End)
- }
-
- private def parseBraceExpansion(input: String) = {
- def unfold(vss: List[Seq[String]]): Seq[String] = {
- vss match {
- case Nil => Seq("")
- case head :: rest =>
- for {
- str <- head
- r <- unfold(rest)
- } yield
- r match {
- case "" => str
- case _ => str + "," + r
- }
- }
- }
-
- BraceExpansionParser.parser
- .map { vss =>
- val stringss = vss.map(x => Fragment.unfold(x.toList)).toList
- unfold(stringss)
- }
- .parse(input)
- }
-
- def extractSegments(selectorString: String): Either[String, List[Segment]] =
- parseSelector(selectorString) match {
- case f: Parsed.Failure => Left(s"Parsing exception ${f.msg}")
- case Parsed.Success(selector, _) => Right(selector)
- }
-
- private def parseSelector(input: String) = {
- val segment =
- P(CharsWhileIn(('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).!).map(
- Segment.Label
- )
- val crossSegment =
- P("[" ~ CharsWhile(c => c != ',' && c != ']').!.rep(1, sep = ",") ~ "]")
- .map(Segment.Cross)
- val query = P(segment ~ ("." ~ segment | crossSegment).rep ~ End).map {
- case (h, rest) => h :: rest.toList
- }
- query.parse(input)
- }
-
-}
diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala
deleted file mode 100644
index 97efb6e5..00000000
--- a/core/src/main/scala/mill/main/ReplApplyHandler.scala
+++ /dev/null
@@ -1,124 +0,0 @@
-package mill.main
-
-
-import mill.define.Applicative.ApplyHandler
-import mill.define.Segment.Label
-import mill.define._
-import mill.eval.{Evaluator, Result}
-import mill.util.Strict.Agg
-
-import scala.collection.mutable
-object ReplApplyHandler{
- def apply[T](colors: ammonite.util.Colors,
- pprinter0: pprint.PPrinter,
- rootModule: mill.Module,
- discover: Discover) = {
- new ReplApplyHandler(
- pprinter0,
- new mill.eval.Evaluator(
- ammonite.ops.pwd / 'out,
- ammonite.ops.pwd,
- rootModule,
- new mill.util.PrintLogger(
- colors != ammonite.util.Colors.BlackWhite,
- colors,
- System.out,
- System.err,
- System.err
- )
- ),
- discover
- )
- }
-}
-class ReplApplyHandler(pprinter0: pprint.PPrinter,
- evaluator: Evaluator[_],
- discover: Discover) extends ApplyHandler[Task] {
- // Evaluate classLoaderSig only once in the REPL to avoid busting caches
- // as the user enters more REPL commands and changes the classpath
- val classLoaderSig = Evaluator.classLoaderSig
- override def apply[V](t: Task[V]) = {
- val res = evaluator.evaluate(Agg(t))
- res.values match{
- case Seq(head: V) => head
- case Nil =>
- val msg = new mutable.StringBuilder()
- msg.append(res.failing.keyCount + " targets failed\n")
- for((k, vs) <- res.failing.items){
- msg.append(k match{
- case Left(t) => "Anonymous Task\n"
- case Right(k) => k.segments.render + "\n"
- })
-
- for(v <- vs){
- v match{
- case Result.Failure(m) => msg.append(m + "\n")
- case Result.Exception(t, outerStack) =>
- msg.append(
- t.toString + t.getStackTrace.dropRight(outerStack.length).map("\n " + _).mkString + "\n"
- )
-
- }
- }
- }
- throw new Exception(msg.toString)
- }
- }
-
- val generatedEval = new EvalGenerated(evaluator)
-
- val millHandlers: PartialFunction[Any, pprint.Tree] = {
- case c: Cross[_] =>
- pprint.Tree.Lazy( ctx =>
- Iterator(c.millOuterCtx.enclosing , ":", c.millOuterCtx.lineNum.toString, ctx.applyPrefixColor("\nChildren:").toString) ++
- c.items.iterator.map(x =>
- "\n (" + x._1.map(pprint.PPrinter.BlackWhite.apply(_)).mkString(", ") + ")"
- )
- )
- case m: mill.Module if evaluator.rootModule.millModuleDirectChildren.contains(m) =>
- pprint.Tree.Lazy( ctx =>
- Iterator(m.millInternal.millModuleEnclosing, ":", m.millInternal.millModuleLine.toString) ++
- (if (m.millInternal.reflect[mill.Module].isEmpty) Nil
- else
- ctx.applyPrefixColor("\nChildren:").toString +:
- m.millInternal.reflect[mill.Module].map("\n ." + _.millOuterCtx.segments.render)) ++
- (discover.value.get(m.getClass) match{
- case None => Nil
- case Some(commands) =>
- ctx.applyPrefixColor("\nCommands:").toString +: commands.map{c =>
- "\n ." + c.name + "(" +
- c.argSignatures.map(s => s.name + ": " + s.typeString).mkString(", ") +
- ")()"
- }
- }) ++
- (if (m.millInternal.reflect[Target[_]].isEmpty) Nil
- else {
- Seq(ctx.applyPrefixColor("\nTargets:").toString) ++
- m.millInternal.reflect[Target[_]].sortBy(_.label).map(t =>
- "\n ." + t.label + "()"
- )
- })
-
- )
- case t: mill.define.Target[_] if evaluator.rootModule.millInternal.targets.contains(t) =>
- val seen = mutable.Set.empty[Task[_]]
- def rec(t: Task[_]): Seq[Segments] = {
- if (seen(t)) Nil // do nothing
- else t match {
- case t: Target[_] if evaluator.rootModule.millInternal.targets.contains(t) =>
- Seq(t.ctx.segments)
- case _ =>
- seen.add(t)
- t.inputs.flatMap(rec)
- }
- }
- pprint.Tree.Lazy(ctx =>
- Iterator(t.ctx.enclosing, ":", t.ctx.lineNum.toString, "\n", ctx.applyPrefixColor("Inputs:").toString) ++
- t.inputs.iterator.flatMap(rec).map("\n " + _.render)
- )
-
- }
- val pprinter = pprinter0.copy(
- additionalHandlers = millHandlers orElse pprinter0.additionalHandlers
- )
-}
diff --git a/core/src/main/scala/mill/main/Resolve.scala b/core/src/main/scala/mill/main/Resolve.scala
deleted file mode 100644
index ed4c4f80..00000000
--- a/core/src/main/scala/mill/main/Resolve.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package mill.main
-
-import mill.define._
-import mill.define.TaskModule
-import ammonite.main.Router
-import ammonite.main.Router.EntryPoint
-
-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, Task[Any]] = {
-
- 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 invokeCommand[V](target: mill.Module, name: String) = {
- for(cmd <- discover.value.get(target.getClass).toSeq.flatten.find(_.name == name))
- yield cmd.asInstanceOf[EntryPoint[mill.Module]].invoke(target, ammonite.main.Scripts.groupArgs(rest.toList)) match {
- case Router.Result.Success(v) => Right(v)
- case _ => Left(s"Command failed $last")
- }
- }
-
- 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()))
- case _ => None
- }
- } yield res
-
- val command = invokeCommand(obj, last)
-
- command orElse target orElse runDefault.headOption.flatten 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{ case x: Task[Any] => x }
- }
-
-
- case head :: tail =>
- val newRevSelectorsSoFar = head :: revSelectorsSoFar
- head match{
- case Segment.Label(singleLabel) =>
- 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)
- }
-
- case Segment.Cross(cross) =>
- obj match{
- case c: Cross[_] =>
- 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 Nil => Left("Selector cannot be empty")
- }
- }
-}
diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala
deleted file mode 100644
index aa254048..00000000
--- a/core/src/main/scala/mill/main/RunScript.scala
+++ /dev/null
@@ -1,210 +0,0 @@
-package mill.main
-
-import java.nio.file.NoSuchFileException
-
-import ammonite.interp.Interpreter
-import ammonite.ops.{Path, read}
-import ammonite.runtime.SpecialClassLoader
-import ammonite.util.Util.CodeSource
-import ammonite.util.{Name, Res, Util}
-import mill.{PathRef, define}
-import mill.define.{Discover, Segment, Task}
-import mill.eval.{Evaluator, Result}
-import mill.util.{EitherOps, Logger}
-import mill.util.Strict.Agg
-import upickle.Js
-
-/**
- * Custom version of ammonite.main.Scripts, letting us run the build.sc script
- * directly without going through Ammonite's main-method/argument-parsing
- * subsystem
- */
-object RunScript{
- def runScript(wd: Path,
- path: Path,
- instantiateInterpreter: => Either[(Res.Failing, Seq[(Path, Long)]), ammonite.interp.Interpreter],
- scriptArgs: Seq[String],
- lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_], Discover)],
- log: Logger)
- : (Res[(Evaluator[_], Discover, Seq[(Path, Long)], Either[String, Seq[Js.Value]])], Seq[(Path, Long)]) = {
-
- val (evalRes, interpWatched) = lastEvaluator match{
- case Some((prevInterpWatchedSig, prevEvaluator, prevDiscover))
- if watchedSigUnchanged(prevInterpWatchedSig) =>
-
- (Res.Success(prevEvaluator -> prevDiscover), prevInterpWatchedSig)
-
- case _ =>
- instantiateInterpreter match{
- case Left((res, watched)) => (res, watched)
- case Right(interp) =>
- interp.watch(path)
- val eval =
- for((mapping, discover) <- evaluateMapping(wd, path, interp))
- yield (
- new Evaluator(
- wd / 'out, wd, mapping, log,
- mapping.getClass.getClassLoader.asInstanceOf[SpecialClassLoader].classpathSignature
- ),
- discover
- )
- (eval, interp.watchedFiles)
- }
- }
-
- val evaluated = for{
- (evaluator, discover) <- evalRes
- (evalWatches, res) <- Res(evaluateTarget(evaluator, discover, scriptArgs))
- } 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
- // `PathRef` and the current moment, use random junk .sig values
- // to force an immediate re-run. Otherwise calculate the
- // pathSignatures the same way Ammonite would and hand over the
- // values, so Ammonite can watch them and only re-run if they
- // subsequently change
- val evaluationWatches =
- if (alreadyStale) evalWatches.map(_.path -> util.Random.nextLong())
- else evalWatches.map(p => p.path -> Interpreter.pathSignature(p.path))
-
- (evaluator, discover, evaluationWatches, res.map(_.flatMap(_._2)))
- }
- (evaluated, interpWatched)
- }
-
- def watchedSigUnchanged(sig: Seq[(Path, Long)]) = {
- sig.forall{case (p, l) => Interpreter.pathSignature(p) == l}
- }
-
- def evaluateMapping(wd: Path,
- path: Path,
- interp: ammonite.interp.Interpreter): Res[(mill.Module, Discover)] = {
-
- val (pkg, wrapper) = Util.pathToPackageWrapper(Seq(), path relativeTo wd)
-
- for {
- scriptTxt <-
- try Res.Success(Util.normalizeNewlines(read(path)))
- catch { case e: NoSuchFileException => Res.Failure("Script file not found: " + path) }
-
- processed <- interp.processModule(
- scriptTxt,
- CodeSource(wrapper, pkg, Seq(Name("ammonite"), Name("$file")), Some(path)),
- autoImport = true,
- extraCode = "",
- hardcoded = true
- )
-
- buildClsName <- processed.blockInfo.lastOption match {
- case Some(meta) => Res.Success(meta.id.wrapperPath)
- case None => Res.Skip
- }
-
- buildCls = interp
- .evalClassloader
- .loadClass(buildClsName)
-
- module <- try {
- Util.withContextClassloader(interp.evalClassloader) {
- Res.Success(
- buildCls.getMethod("millSelf")
- .invoke(null)
- .asInstanceOf[Some[mill.Module]]
- .get
- )
- }
- } catch {
- case e: Throwable => Res.Exception(e, "")
- }
- discover <- try {
- Util.withContextClassloader(interp.evalClassloader) {
- Res.Success(
- buildCls.getMethod("millDiscover")
- .invoke(null)
- .asInstanceOf[Discover]
- )
- }
- } catch {
- case e: Throwable => Res.Exception(e, "")
- }
-// _ <- Res(consistencyCheck(mapping))
- } yield (module, discover)
- }
-
- def evaluateTarget[T](evaluator: Evaluator[_],
- discover: Discover,
- scriptArgs: Seq[String]) = {
- for {
- parsed <- ParseArgs(scriptArgs)
- (selectors, args) = parsed
- targets <- {
- val selected = selectors.map { sel =>
- val crossSelectors = sel.map {
- case Segment.Cross(x) => x.toList.map(_.toString)
- case _ => Nil
- }
- mill.main.Resolve.resolve(
- sel, evaluator.rootModule,
- discover,
- args, crossSelectors, Nil
- )
- }
- EitherOps.sequence(selected)
- }
- (watched, res) = evaluate(evaluator, targets)
- } yield (watched, res)
- }
-
- def evaluate(evaluator: Evaluator[_],
- targets: Seq[Task[Any]]): (Seq[PathRef], Either[String, Seq[(Any, Option[upickle.Js.Value])]]) = {
- val evaluated = evaluator.evaluate(Agg.from(targets))
- val watched = evaluated.results
- .iterator
- .collect {
- case (t: define.Input[_], Result.Success(p: PathRef)) => p
- }
- .toSeq
-
- val errorStr =
- (for((k, fs) <- evaluated.failing.items()) yield {
- val ks = k match{
- case Left(t) => t.toString
- case Right(t) => t.segments.render
- }
- val fss = fs.map{
- case Result.Exception(t, outerStack) =>
- t.toString + t.getStackTrace.dropRight(outerStack.length).map("\n " + _).mkString
- case Result.Failure(t) => t
- }
- s"$ks ${fss.mkString(", ")}"
- }).mkString("\n")
-
- evaluated.failing.keyCount match {
- case 0 =>
- val json = for(t <- targets) yield {
- t match {
- case t: mill.define.NamedTask[_] =>
- val jsonFile = Evaluator
- .resolveDestPaths(evaluator.workspacePath, t.ctx.segments)
- .meta
- val metadata = upickle.json.read(jsonFile.toIO)
- Some(metadata(1))
-
- case _ => None
- }
- }
-
- watched -> Right(evaluated.values.zip(json))
- case n => watched -> Left(s"$n targets failed\n$errorStr")
- }
- }
-
-// def consistencyCheck[T](mapping: Discovered.Mapping[T]): Either[String, Unit] = {
-// val consistencyErrors = Discovered.consistencyCheck(mapping)
-// if (consistencyErrors.nonEmpty) {
-// Left(s"Failed Discovered.consistencyCheck: ${consistencyErrors.map(_.render)}")
-// } else {
-// Right(())
-// }
-// }
-}
diff --git a/core/src/main/scala/mill/modules/Jvm.scala b/core/src/main/scala/mill/modules/Jvm.scala
deleted file mode 100644
index 888a687b..00000000
--- a/core/src/main/scala/mill/modules/Jvm.scala
+++ /dev/null
@@ -1,259 +0,0 @@
-package mill.modules
-
-import java.io.FileOutputStream
-import java.lang.reflect.Modifier
-import java.net.URLClassLoader
-import java.nio.file.attribute.PosixFilePermission
-import java.util.jar.{JarEntry, JarFile, JarOutputStream}
-
-import ammonite.ops._
-import mill.define.Task
-import mill.eval.PathRef
-import mill.util.Ctx
-import mill.util.Ctx.LogCtx
-import mill.util.Loose.Agg
-
-import scala.annotation.tailrec
-import scala.collection.mutable
-
-
-object Jvm {
- def gatherClassloaderJars(): Agg[Path] = {
- val allJars = new Agg.Mutable[Path]()
- var currentClassloader = Thread.currentThread().getContextClassLoader
- while(currentClassloader != null){
- currentClassloader match{
- case u: URLClassLoader => allJars.appendAll(u.getURLs.map(x => Path(x.getFile)))
- case _ =>
- }
- currentClassloader = currentClassloader.getParent
- }
- allJars
- }
-
- def interactiveSubprocess(mainClass: String,
- classPath: Agg[Path],
- options: Seq[String] = Seq.empty): Unit = {
- import ammonite.ops.ImplicitWd._
- %("java", "-cp", classPath.mkString(":"), mainClass, options)
- }
-
- def inprocess(mainClass: String,
- classPath: Agg[Path],
- options: Seq[String] = Seq.empty)
- (implicit ctx: Ctx): Unit = {
- inprocess(classPath, classLoaderOverrideSbtTesting = false, cl => {
- getMainMethod(mainClass, cl).invoke(null, options.toArray)
- })
- }
-
- private def getMainMethod(mainClassName: String, cl: ClassLoader) = {
- val mainClass = cl.loadClass(mainClassName)
- val method = mainClass.getMethod("main", classOf[Array[String]])
- // jvm allows the actual main class to be non-public and to run a method in the non-public class,
- // we need to make it accessible
- method.setAccessible(true)
- val modifiers = method.getModifiers
- if (!Modifier.isPublic(modifiers))
- throw new NoSuchMethodException(mainClassName + ".main is not public")
- if (!Modifier.isStatic(modifiers))
- throw new NoSuchMethodException(mainClassName + ".main is not static")
- method
- }
-
-
- def inprocess[T](classPath: Agg[Path],
- classLoaderOverrideSbtTesting: Boolean,
- body: ClassLoader => T): T = {
- val cl = if (classLoaderOverrideSbtTesting) {
- val outerClassLoader = getClass.getClassLoader
- new URLClassLoader(
- classPath.map(_.toIO.toURI.toURL).toArray,
- ClassLoader.getSystemClassLoader().getParent()){
- override def findClass(name: String) = {
- if (name.startsWith("sbt.testing.")){
- outerClassLoader.loadClass(name)
- }else{
- super.findClass(name)
- }
- }
- }
- } else {
- new URLClassLoader(
- classPath.map(_.toIO.toURI.toURL).toArray,
- ClassLoader.getSystemClassLoader().getParent())
- }
- val oldCl = Thread.currentThread().getContextClassLoader
- Thread.currentThread().setContextClassLoader(cl)
- try {
- body(cl)
- }finally{
- Thread.currentThread().setContextClassLoader(oldCl)
- cl.close()
- }
- }
-
- def subprocess(mainClass: String,
- classPath: Agg[Path],
- jvmOptions: Seq[String] = Seq.empty,
- options: Seq[String] = Seq.empty,
- workingDir: Path = null)
- (implicit ctx: Ctx) = {
-
- val commandArgs =
- Vector("java") ++
- jvmOptions ++
- Vector("-cp", classPath.mkString(":"), mainClass) ++
- options
-
- val workingDir1 = Option(workingDir).getOrElse(ctx.dest)
- mkdir(workingDir1)
- val proc =
- new java.lang.ProcessBuilder()
- .directory(workingDir1.toIO)
- .command(commandArgs:_*)
- .redirectOutput(ProcessBuilder.Redirect.PIPE)
- .redirectError(ProcessBuilder.Redirect.PIPE)
- .start()
-
- val stdout = proc.getInputStream
- val stderr = proc.getErrorStream
- val sources = Seq(
- (stdout, Left(_: Bytes), ctx.log.outputStream),
- (stderr, Right(_: Bytes),ctx.log.errorStream )
- )
- val chunks = mutable.Buffer.empty[Either[Bytes, Bytes]]
- while(
- // Process.isAlive doesn't exist on JDK 7 =/
- util.Try(proc.exitValue).isFailure ||
- stdout.available() > 0 ||
- stderr.available() > 0
- ){
- var readSomething = false
- for ((subStream, wrapper, parentStream) <- sources){
- while (subStream.available() > 0){
- readSomething = true
- val array = new Array[Byte](subStream.available())
- val actuallyRead = subStream.read(array)
- chunks.append(wrapper(new ammonite.ops.Bytes(array)))
- parentStream.write(array, 0, actuallyRead)
- }
- }
- // if we did not read anything sleep briefly to avoid spinning
- if(!readSomething)
- Thread.sleep(2)
- }
-
- if (proc.exitValue() != 0) throw new InteractiveShelloutException()
- else ammonite.ops.CommandResult(proc.exitValue(), chunks)
- }
-
- private def createManifest(mainClass: Option[String]) = {
- val m = new java.util.jar.Manifest()
- m.getMainAttributes.put(java.util.jar.Attributes.Name.MANIFEST_VERSION, "1.0")
- m.getMainAttributes.putValue( "Created-By", "Scala mill" )
- mainClass.foreach(
- m.getMainAttributes.put(java.util.jar.Attributes.Name.MAIN_CLASS, _)
- )
- m
- }
-
- def createJar(inputPaths: Agg[Path], mainClass: Option[String] = None)
- (implicit ctx: Ctx.DestCtx): PathRef = {
- val outputPath = ctx.dest
- rm(outputPath)
- if(inputPaths.nonEmpty) {
- mkdir(outputPath/up)
-
- val jar = new JarOutputStream(
- new FileOutputStream(outputPath.toIO),
- createManifest(mainClass)
- )
-
- try{
- assert(inputPaths.forall(exists(_)))
- for{
- p <- inputPaths
- (file, mapping) <-
- if (p.isFile) Iterator(p -> empty/p.last)
- else ls.rec(p).filter(_.isFile).map(sub => sub -> sub.relativeTo(p))
- } {
- val entry = new JarEntry(mapping.toString)
- entry.setTime(file.mtime.toMillis)
- jar.putNextEntry(entry)
- jar.write(read.bytes(file))
- jar.closeEntry()
- }
- } finally {
- jar.close()
- }
-
- }
- PathRef(outputPath)
- }
-
- def createAssembly(inputPaths: Agg[Path],
- mainClass: Option[String] = None,
- prependShellScript: String = "")
- (implicit ctx: Ctx.DestCtx): PathRef = {
- val outputPath = ctx.dest
- rm(outputPath)
-
- if(inputPaths.nonEmpty) {
- mkdir(outputPath/up)
-
- val output = new FileOutputStream(outputPath.toIO)
-
- // Prepend shell script and make it executable
- if (prependShellScript.nonEmpty) {
- output.write((prependShellScript + "\n").getBytes)
- val perms = java.nio.file.Files.getPosixFilePermissions(outputPath.toNIO)
- perms.add(PosixFilePermission.GROUP_EXECUTE)
- perms.add(PosixFilePermission.OWNER_EXECUTE)
- perms.add(PosixFilePermission.OTHERS_EXECUTE)
- java.nio.file.Files.setPosixFilePermissions(outputPath.toNIO, perms)
- }
-
- val jar = new JarOutputStream(
- output,
- createManifest(mainClass)
- )
-
- val seen = mutable.Set("META-INF/MANIFEST.MF")
- try{
-
-
- for{
- p <- inputPaths
- if exists(p)
- (file, mapping) <-
- if (p.isFile) {
- val jf = new JarFile(p.toIO)
- import collection.JavaConverters._
- for(entry <- jf.entries().asScala if !entry.isDirectory) yield {
- read.bytes(jf.getInputStream(entry)) -> entry.getName
- }
- }
- else {
- ls.rec(p).iterator
- .filter(_.isFile)
- .map(sub => read.bytes(sub) -> sub.relativeTo(p).toString)
- }
- if !seen(mapping)
- } {
- seen.add(mapping)
- val entry = new JarEntry(mapping.toString)
- jar.putNextEntry(entry)
- jar.write(file)
- jar.closeEntry()
- }
- } finally {
- jar.close()
- output.close()
- }
-
- }
- PathRef(outputPath)
- }
-
-}
diff --git a/core/src/main/scala/mill/modules/Util.scala b/core/src/main/scala/mill/modules/Util.scala
deleted file mode 100644
index cd674bad..00000000
--- a/core/src/main/scala/mill/modules/Util.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package mill.modules
-
-import ammonite.ops.RelPath
-import mill.eval.PathRef
-import mill.util.Ctx
-
-object Util {
- def download(url: String, dest: RelPath)(implicit ctx: Ctx.DestCtx) = {
- ammonite.ops.mkdir(ctx.dest)
- val out = ctx.dest / dest
-
- val website = new java.net.URI(url).toURL
- val rbc = java.nio.channels.Channels.newChannel(website.openStream)
- try{
- val fos = new java.io.FileOutputStream(out.toIO)
- try{
- fos.getChannel.transferFrom(rbc, 0, java.lang.Long.MAX_VALUE)
- PathRef(out)
- } finally{
- fos.close()
- }
- } finally{
- rbc.close()
- }
- }
-}
diff --git a/core/src/main/scala/mill/package.scala b/core/src/main/scala/mill/package.scala
deleted file mode 100644
index 93916c8b..00000000
--- a/core/src/main/scala/mill/package.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-import mill.util.JsonFormatters
-
-package object mill extends JsonFormatters{
- val T = define.Target
- type T[T] = define.Target[T]
- val PathRef = mill.eval.PathRef
- type PathRef = mill.eval.PathRef
- type Module = define.Module
- type Cross[T] = define.Cross[T]
- type Agg[T] = util.Loose.Agg[T]
- val Agg = util.Loose.Agg
-}
diff --git a/core/src/main/scala/mill/util/AggWrapper.scala b/core/src/main/scala/mill/util/AggWrapper.scala
deleted file mode 100644
index c2994a9a..00000000
--- a/core/src/main/scala/mill/util/AggWrapper.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package mill.util
-
-
-
-import scala.collection.mutable
-object Strict extends AggWrapper(true)
-object Loose extends AggWrapper(false)
-sealed class AggWrapper(strictUniqueness: Boolean){
- /**
- * A collection with enforced uniqueness, fast contains and deterministic
- * ordering. Raises an exception if a duplicate is found; call
- * `toSeq.distinct` if you explicitly want to make it swallow duplicates
- */
- trait Agg[V] extends TraversableOnce[V]{
- def contains(v: V): Boolean
- def items: Iterator[V]
- def indexed: IndexedSeq[V]
- def flatMap[T](f: V => TraversableOnce[T]): Agg[T]
- def map[T](f: V => T): Agg[T]
- def filter(f: V => Boolean): Agg[V]
- def withFilter(f: V => Boolean): Agg[V]
- def collect[T](f: PartialFunction[V, T]): Agg[T]
- def zipWithIndex: Agg[(V, Int)]
- def reverse: Agg[V]
- def zip[T](other: Agg[T]): Agg[(V, T)]
- def ++[T >: V](other: TraversableOnce[T]): Agg[T]
- }
-
- object Agg{
- def empty[V]: Agg[V] = new Agg.Mutable[V]
- implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[Agg[T]] =
- upickle.default.ReadWriter[Agg[T]] (
- oset => upickle.default.writeJs(oset.toList),
- {case json => Agg.from(upickle.default.readJs[Seq[T]](json))}
- )
- def apply[V](items: V*) = from(items)
-
- implicit def from[V](items: TraversableOnce[V]): Agg[V] = {
- val set = new Agg.Mutable[V]()
- items.foreach(set.append)
- set
- }
-
-
- class Mutable[V]() extends Agg[V]{
-
- private[this] val set0 = mutable.LinkedHashSet.empty[V]
- def contains(v: V) = set0.contains(v)
- def append(v: V) = if (!contains(v)){
- set0.add(v)
-
- }else if (strictUniqueness){
- throw new Exception("Duplicated item inserted into OrderedSet: " + v)
- }
- def appendAll(vs: Seq[V]) = vs.foreach(append)
- def items = set0.iterator
- def indexed: IndexedSeq[V] = items.toIndexedSeq
- def set: collection.Set[V] = set0
-
- def map[T](f: V => T): Agg[T] = {
- val output = new Agg.Mutable[T]
- for(i <- items) output.append(f(i))
- output
- }
- def flatMap[T](f: V => TraversableOnce[T]): Agg[T] = {
- val output = new Agg.Mutable[T]
- for(i <- items) for(i0 <- f(i)) output.append(i0)
- output
- }
- def filter(f: V => Boolean): Agg[V] = {
- val output = new Agg.Mutable[V]
- for(i <- items) if (f(i)) output.append(i)
- output
- }
- def withFilter(f: V => Boolean): Agg[V] = filter(f)
-
- def collect[T](f: PartialFunction[V, T]) = this.filter(f.isDefinedAt).map(x => f(x))
-
- def zipWithIndex = {
- var i = 0
- this.map{ x =>
- i += 1
- (x, i-1)
- }
- }
-
- def reverse = Agg.from(indexed.reverseIterator)
-
- def zip[T](other: Agg[T]) = Agg.from(items.zip(other.items))
- def ++[T >: V](other: TraversableOnce[T]) = Agg.from(items ++ other)
-
- // Members declared in scala.collection.GenTraversableOnce
- def isTraversableAgain: Boolean = items.isTraversableAgain
- def toIterator: Iterator[V] = items.toIterator
- def toStream: Stream[V] = items.toStream
-
- // Members declared in scala.collection.TraversableOnce
- def copyToArray[B >: V](xs: Array[B], start: Int,len: Int): Unit = items.copyToArray(xs, start, len)
- def exists(p: V => Boolean): Boolean = items.exists(p)
- def find(p: V => Boolean): Option[V] = items.find(p)
- def forall(p: V => Boolean): Boolean = items.forall(p)
- def foreach[U](f: V => U): Unit = items.foreach(f)
- def hasDefiniteSize: Boolean = items.hasDefiniteSize
- def isEmpty: Boolean = items.isEmpty
- def seq: scala.collection.TraversableOnce[V] = items
- def toTraversable: Traversable[V] = items.toTraversable
-
- override def hashCode() = items.map(_.hashCode()).sum
- override def equals(other: Any) = other match{
- case s: Agg[_] => items.sameElements(s.items)
- case _ => super.equals(other)
- }
- override def toString = items.mkString("Agg(", ", ", ")")
- }
- }
-}
diff --git a/core/src/main/scala/mill/util/Ctx.scala b/core/src/main/scala/mill/util/Ctx.scala
deleted file mode 100644
index 60e6bdbf..00000000
--- a/core/src/main/scala/mill/util/Ctx.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package mill.util
-
-import ammonite.ops.Path
-import mill.define.Applicative.ImplicitStub
-import mill.util.Ctx.{ArgCtx, BaseCtx, DestCtx, LoaderCtx, LogCtx}
-
-import scala.annotation.compileTimeOnly
-import scala.language.implicitConversions
-
-object Ctx{
- @compileTimeOnly("Target.ctx() can only be used with a T{...} block")
- @ImplicitStub
- implicit def taskCtx: Ctx = ???
-
- object DestCtx {
- implicit def pathToCtx(path: Path): DestCtx = new DestCtx { def dest = path }
- }
- trait DestCtx{
- def dest: Path
- }
- trait BaseCtx{
- def base: Path
- }
- object BaseCtx {
- implicit def pathToCtx(path: Path): BaseCtx = new BaseCtx { def base = path }
- }
- trait LogCtx{
- def log: Logger
- }
- object LogCtx{
- implicit def logToCtx(l: Logger): LogCtx = new LogCtx { def log = l }
- }
- trait ArgCtx{
- def args: IndexedSeq[_]
- }
- trait LoaderCtx{
- def load[T](x: Loader[T]): T
- }
- trait Loader[T]{
- def make(): T
- }
-}
-class Ctx(val args: IndexedSeq[_],
- val dest: Path,
- val base: Path,
- val log: Logger,
- workerCtx0: Ctx.LoaderCtx)
- extends DestCtx
- with LogCtx
- with ArgCtx
- with LoaderCtx
- with BaseCtx{
-
- def load[T](x: Ctx.Loader[T]): T = workerCtx0.load(x)
- def length = args.length
- def apply[T](index: Int): T = {
- if (index >= 0 && index < args.length) args(index).asInstanceOf[T]
- else throw new IndexOutOfBoundsException(s"Index $index outside of range 0 - ${args.length}")
- }
-}
diff --git a/core/src/main/scala/mill/util/EitherOps.scala b/core/src/main/scala/mill/util/EitherOps.scala
deleted file mode 100644
index da2552c8..00000000
--- a/core/src/main/scala/mill/util/EitherOps.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package mill.util
-
-import scala.collection.generic.CanBuildFrom
-import scala.collection.mutable
-import scala.language.higherKinds
-
-object EitherOps {
-
- // implementation similar to scala.concurrent.Future#sequence
- def sequence[A, B, M[X] <: TraversableOnce[X]](in: M[Either[A, B]])(
- implicit cbf: CanBuildFrom[M[Either[A, B]], B, M[B]]): Either[A, M[B]] = {
- in.foldLeft[Either[A, mutable.Builder[B, M[B]]]](Right(cbf(in))) {
- case (acc, el) =>
- for (a <- acc; e <- el) yield a += e
- }
- .map(_.result())
- }
-}
diff --git a/core/src/main/scala/mill/util/JsonFormatters.scala b/core/src/main/scala/mill/util/JsonFormatters.scala
deleted file mode 100644
index 00a40e7d..00000000
--- a/core/src/main/scala/mill/util/JsonFormatters.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package mill.util
-
-import ammonite.ops.{Bytes, Path}
-import upickle.Js
-import upickle.default.{ReadWriter => RW}
-object JsonFormatters extends JsonFormatters
-trait JsonFormatters {
- implicit val pathReadWrite: RW[ammonite.ops.Path] = RW[ammonite.ops.Path](
- o => Js.Str(o.toString()),
- {case Js.Str(json) => Path(json.toString)},
- )
-
- implicit val bytesReadWrite: RW[Bytes] = RW[Bytes](
- o => Js.Str(javax.xml.bind.DatatypeConverter.printBase64Binary(o.array)),
- {case Js.Str(json) => new Bytes(javax.xml.bind.DatatypeConverter.parseBase64Binary(json.toString))}
- )
-
-
- implicit lazy val crFormat: RW[ammonite.ops.CommandResult] = upickle.default.macroRW
-
- implicit lazy val modFormat: RW[coursier.Module] = upickle.default.macroRW
- implicit lazy val depFormat: RW[coursier.Dependency]= upickle.default.macroRW
- implicit lazy val attrFormat: RW[coursier.Attributes] = upickle.default.macroRW
- implicit val stackTraceRW = upickle.default.ReadWriter[StackTraceElement](
- ste => Js.Obj(
- "declaringClass" -> Js.Str(ste.getClassName),
- "methodName" -> Js.Str(ste.getMethodName),
- "fileName" -> Js.Str(ste.getFileName),
- "lineNumber" -> Js.Num(ste.getLineNumber)
- ),
- {case json: Js.Obj =>
- new StackTraceElement(
- json("declaringClass").str.toString,
- json("methodName").str.toString,
- json("fileName").str.toString,
- json("lineNumber").num.toInt
- )
- }
- )
-
-
-}
diff --git a/core/src/main/scala/mill/util/Logger.scala b/core/src/main/scala/mill/util/Logger.scala
deleted file mode 100644
index 17c66d27..00000000
--- a/core/src/main/scala/mill/util/Logger.scala
+++ /dev/null
@@ -1,138 +0,0 @@
-package mill.util
-
-import java.io._
-
-import ammonite.ops.Path
-import ammonite.util.Colors
-
-
-/**
- * The standard logging interface of the Mill build tool.
- *
- * Contains four primary logging methods, in order of increasing importance:
- *
- * - `ticker`: short-lived logging output where consecutive lines over-write
- * each other; useful for information which is transient and disposable
- *
- * - `info`: miscellaneous logging output which isn't part of the main output
- * a user is looking for, but useful to provide context on what Mill is doing
- *
- * - `error`: logging output which represents problems the user should care
- * about
- *
- * Also contains the two forwarded stdout and stderr streams, for code executed
- * by Mill to use directly. Typically these correspond to the stdout and stderr,
- * but when `--show` is used both are forwarded to stderr and stdout is only
- * used to display the final `--show` output for easy piping.
- */
-trait Logger {
- def colored: Boolean
- val errorStream: PrintStream
- val outputStream: PrintStream
- def info(s: String): Unit
- def error(s: String): Unit
- def ticker(s: String): Unit
- def close(): Unit = ()
-}
-
-object DummyLogger extends Logger {
- def colored = false
- object errorStream extends PrintStream(_ => ())
- object outputStream extends PrintStream(_ => ())
- def info(s: String) = ()
- def error(s: String) = ()
- def ticker(s: String) = ()
-}
-
-class CallbackStream(wrapped: OutputStream, f: () => Unit) extends OutputStream{
- override def write(b: Array[Byte]): Unit = { f(); wrapped.write(b) }
-
- override def write(b: Array[Byte], off: Int, len: Int): Unit = {
- f()
- wrapped.write(b, off, len)
- }
-
- def write(b: Int) = {f(); wrapped.write(b)}
-}
-case class PrintLogger(colored: Boolean,
- colors: ammonite.util.Colors,
- outStream: PrintStream,
- infoStream: PrintStream,
- errStream: PrintStream) extends Logger {
-
- var lastLineTicker = false
- def falseTicker[T](t: T) = {
- lastLineTicker = false
- t
- }
- override val errorStream = new PrintStream(
- new CallbackStream(errStream, () => lastLineTicker = false)
- )
- override val outputStream = new PrintStream(
- new CallbackStream(outStream, () => lastLineTicker = false)
- )
-
-
- def info(s: String) = {
- lastLineTicker = false
- infoStream.println(colors.info()(s))
- }
- def error(s: String) = {
- lastLineTicker = false
- errStream.println(colors.error()(s))
- }
- def ticker(s: String) = {
- if (lastLineTicker){
- val p = new PrintWriter(infoStream)
- val nav = new ammonite.terminal.AnsiNav(p)
- nav.up(1)
- nav.clearLine(2)
- nav.left(9999)
- p.flush()
- }else{
- infoStream.println()
- }
- lastLineTicker = true
- infoStream.println(colors.info()(s))
- }
-}
-
-case class FileLogger(colored: Boolean, file: Path) extends Logger {
- private[this] var outputStreamUsed: Boolean = false
-
- lazy val outputStream = {
- outputStreamUsed = true
- new PrintStream(new FileOutputStream(file.toIO.getAbsolutePath))
- }
-
- lazy val errorStream = {
- outputStreamUsed = true
- new PrintStream(new FileOutputStream(file.toIO.getAbsolutePath))
- }
-
- def info(s: String) = outputStream.println(s)
- def error(s: String) = outputStream.println(s)
- def ticker(s: String) = outputStream.println(s)
- override def close() = {
- if (outputStreamUsed)
- outputStream.close()
- }
-}
-
-case class MultiLogger(colored: Boolean, streams: Logger*) extends Logger {
- lazy val outputStream: PrintStream =
- new PrintStream(b => streams.foreach(_.outputStream.write(b))) {
- override def flush() = streams.foreach(_.outputStream.flush())
- override def close() = streams.foreach(_.outputStream.close())
- }
- lazy val errorStream: PrintStream =
- new PrintStream(b => streams.foreach(_.outputStream.write(b))) {
- override def flush() = streams.foreach(_.outputStream.flush())
- override def close() = streams.foreach(_.outputStream.close())
- }
-
- def info(s: String) = streams.foreach(_.info(s))
- def error(s: String) = streams.foreach(_.error(s))
- def ticker(s: String) = streams.foreach(_.ticker(s))
- override def close() = streams.foreach(_.close())
-} \ No newline at end of file
diff --git a/core/src/main/scala/mill/util/MultiBiMap.scala b/core/src/main/scala/mill/util/MultiBiMap.scala
deleted file mode 100644
index 2cb81944..00000000
--- a/core/src/main/scala/mill/util/MultiBiMap.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package mill.util
-
-import scala.collection.mutable
-import Strict.Agg
-/**
- * A map from keys to collections of values: you can assign multiple values
- * to any particular key. Also allows lookups in both directions: what values
- * are assigned to a key or what key a value is assigned ti.
- */
-trait MultiBiMap[K, V]{
- def containsValue(v: V): Boolean
- def lookupKey(k: K): Agg[V]
- def lookupValue(v: V): K
- def lookupValueOpt(v: V): Option[K]
- def add(k: K, v: V): Unit
- def removeAll(k: K): Agg[V]
- def addAll(k: K, vs: TraversableOnce[V]): Unit
- def keys(): Iterator[K]
- def items(): Iterator[(K, Agg[V])]
- def values(): Iterator[Agg[V]]
- def keyCount: Int
-}
-
-object MultiBiMap{
- class Mutable[K, V]() extends MultiBiMap[K, V]{
- private[this] val valueToKey = mutable.LinkedHashMap.empty[V, K]
- private[this] val keyToValues = mutable.LinkedHashMap.empty[K, Agg.Mutable[V]]
- def containsValue(v: V) = valueToKey.contains(v)
- def lookupKey(k: K) = keyToValues(k)
- def lookupKeyOpt(k: K) = keyToValues.get(k)
- def lookupValue(v: V) = valueToKey(v)
- def lookupValueOpt(v: V) = valueToKey.get(v)
- def add(k: K, v: V): Unit = {
- valueToKey(v) = k
- keyToValues.getOrElseUpdate(k, new Agg.Mutable[V]()).append(v)
- }
- def removeAll(k: K): Agg[V] = keyToValues.get(k) match {
- case None => Agg()
- case Some(vs) =>
- vs.foreach(valueToKey.remove)
-
- keyToValues.remove(k)
- vs
- }
- def addAll(k: K, vs: TraversableOnce[V]): Unit = vs.foreach(this.add(k, _))
-
- def keys() = keyToValues.keysIterator
-
- def values() = keyToValues.valuesIterator
-
- def items() = keyToValues.iterator
-
- def keyCount = keyToValues.size
- }
-}