diff options
-rw-r--r-- | core/src/main/scala/mill/eval/Evaluator.scala | 55 | ||||
-rw-r--r-- | core/src/main/scala/mill/main/RunScript.scala | 2 | ||||
-rw-r--r-- | core/src/test/scala/mill/eval/JavaCompileJarTests.scala | 4 | ||||
-rw-r--r-- | readme.md | 12 | ||||
-rw-r--r-- | scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala | 4 | ||||
-rw-r--r-- | scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala | 12 | ||||
-rwxr-xr-x | test.sh | 8 |
7 files changed, 46 insertions, 51 deletions
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index ed8145b2..0a295ee1 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -41,10 +41,10 @@ class Evaluator[T](val workspacePath: Path, } val delta = finalTaskOverrides - t.overrides val additional = - if (delta == 0) Seq(segments.last) - else Seq(Segment.Label(segments.last.asInstanceOf[Segment.Label].value + "-override-" + delta)) + if (delta == 0) Nil + else Seq(Segment.Label("override" + delta)) - Right(Labelled(t, segments.init ++ additional)) + Right(Labelled(t, segments ++ additional)) case t if goals.contains(t) => Left(t) } @@ -82,11 +82,12 @@ class Evaluator[T](val workspacePath: Path, terminal match{ case Left(task) => - evaluateGroup(group, results, targetDestPath = None, maybeTargetLabel = None) + evaluateGroup(group, results, paths = None, maybeTargetLabel = None) case Right(labelledTarget) => - val (destPath, metadataPath) = Evaluator.resolveDestPaths(workspacePath, labelledTarget) + val paths = Evaluator.resolveDestPaths(workspacePath, labelledTarget) + mkdir(paths.base) val cached = for{ - json <- scala.util.Try(upickle.json.read(read(metadataPath))).toOption + 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 } yield terminalResult @@ -105,11 +106,11 @@ class Evaluator[T](val workspacePath: Path, case Mirror.Segment.Cross(s) => "[" + s.mkString(",") + "]" } - if (labelledTarget.target.flushDest) rm(destPath) + if (labelledTarget.target.flushDest) rm(paths.dest) val (newResults, newEvaluated) = evaluateGroup( group, results, - Some(destPath), + Some(paths), maybeTargetLabel = Some(msgParts.mkString)) newResults(labelledTarget.target) match{ @@ -120,14 +121,14 @@ class Evaluator[T](val workspacePath: Path, .map(_.write(v)) for(t <- terminalResult){ - write.over(metadataPath, upickle.default.write(inputsHash -> t, indent = 4)) + write.over(paths.meta, upickle.default.write(inputsHash -> t, indent = 4)) } case _ => - // Wipe out any cached metadata.mill.json file that exists, so + // 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(metadataPath) + rm(paths.meta) } @@ -140,7 +141,7 @@ class Evaluator[T](val workspacePath: Path, def evaluateGroup(group: OSet[Task[_]], results: collection.Map[Task[_], Result[Any]], - targetDestPath: Option[Path], + paths: Option[Evaluator.Paths], maybeTargetLabel: Option[String]) = { @@ -160,7 +161,7 @@ class Evaluator[T](val workspacePath: Path, if(logRun) { log.info("Running " + targetLabel) } } - val multiLogger = resolveLogger(targetDestPath) + val multiLogger = resolveLogger(paths.map(_.log)) for (target <- nonEvaluatedTargets) { @@ -174,7 +175,7 @@ class Evaluator[T](val workspacePath: Path, else { val args = new Ctx( targetInputValues.toArray[Any], - targetDestPath.orNull, + paths.map(_.dest).orNull, multiLogger, new Ctx.LoaderCtx{ def load[T](x: Ctx.Loader[T]): T = { @@ -207,33 +208,27 @@ class Evaluator[T](val workspacePath: Path, (newResults, newEvaluated) } - def resolveLogger(targetDestPath: Option[Path]): Logger = { - if (targetDestPath.isEmpty) log - else { - val path = targetDestPath.getOrElse(pwd/ 'out / 'command) - val dir = path / up - mkdir(dir) - val file = dir / (path.last + ".log") - rm(file) - MultiLogger(log, FileLogger(file)) - } + def resolveLogger(logPath: Option[Path]): Logger = logPath match{ + case None => log + case Some(path) => + rm(path) + MultiLogger(log, FileLogger(path)) } - } object Evaluator{ - def resolveDestPaths(workspacePath: Path, t: Labelled[_]): (Path, Path) = { + case class Paths(base: Path, dest: Path, meta: Path, log: Path) + def resolveDestPaths(workspacePath: Path, t: Labelled[_]): Paths = { resolveDestPaths(workspacePath, t.segments) } - def resolveDestPaths(workspacePath: Path, segments: Seq[Segment]): (Path, Path) = { + def resolveDestPaths(workspacePath: Path, segments: Seq[Segment]): Paths = { val segmentStrings = segments.flatMap{ case Mirror.Segment.Label(s) => Seq(s) case Mirror.Segment.Cross(values) => values.map(_.toString) } - val targetDestPath = workspacePath / segmentStrings - val metadataPath = targetDestPath / up / (targetDestPath.last + ".mill.json") - (targetDestPath, metadataPath) + val targetPath = workspacePath / segmentStrings + Paths(targetPath, targetPath / 'dest, targetPath / "meta.json", targetPath / 'log) } // check if the build itself has changed diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala index 7ea96b2b..22d6fc95 100644 --- a/core/src/main/scala/mill/main/RunScript.scala +++ b/core/src/main/scala/mill/main/RunScript.scala @@ -143,7 +143,7 @@ object RunScript{ t match { case t: mill.define.Target[_] => for (segments <- evaluator.mapping.modules.get(t.owner)) yield { - val jsonFile = Evaluator.resolveDestPaths(evaluator.workspacePath, segments :+ Segment.Label(t.name))._2 + val jsonFile = Evaluator.resolveDestPaths(evaluator.workspacePath, segments :+ Segment.Label(t.name)).meta val metadata = upickle.json.read(jsonFile.toIO) metadata(1) } diff --git a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala index 2b5bcb58..ba74dea3 100644 --- a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala +++ b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala @@ -123,7 +123,7 @@ object JavaCompileJarTests extends TestSuite{ check(targets = OSet(allSources), expected = OSet(allSources)) check(targets = OSet(jar), expected = OSet(classFiles, jar)) - val jarContents = %%('jar, "-tf", workspacePath/'jar)(workspacePath).out.string + val jarContents = %%('jar, "-tf", workspacePath/'jar/'dest)(workspacePath).out.string val expectedJarContents = """META-INF/MANIFEST.MF |hello.txt @@ -135,7 +135,7 @@ object JavaCompileJarTests extends TestSuite{ |""".stripMargin assert(jarContents == expectedJarContents) - val executed = %%('java, "-cp", workspacePath/'jar, "test.Foo")(workspacePath).out.string + val executed = %%('java, "-cp", workspacePath/'jar/'dest, "test.Foo")(workspacePath).out.string assert(executed == (31337 + 271828) + "\n") for(i <- 0 until 3){ @@ -135,7 +135,7 @@ sbt bin/test:assembly bin/target/mill devAssembly # Build Mill executable using the Mill executable generated by Mill itself -out/devAssembly devAssembly +out/devAssembly/dest devAssembly ``` Eventually, as Mill stabilizes, we will get rid of the SBT build entirely and @@ -188,7 +188,7 @@ run something via `mill Core.cross[a].printIt` while from code you use ### Caching by default Every `Target` in a build, defined by `def foo = T{...}`, is cached by default. -Currently this is done using a `foo.mill.json` file in the `out/` folder. The +Currently this is done using a `foo/meta.json` file in the `out/` folder. The `Target` is also provided a `foo/` path on the filesystem dedicated to it, for it to store output files etc. @@ -209,10 +209,10 @@ structures where a previous process left off, in order to continue the build. Re-construction is done via the hierarchical nature of the build: each `Target` `Foo.bar.baz` has a fixed position in the build hierarchy, and thus a fixed -position on disk `out/foo/bar/baz.mill.json`. When the old process dies and a +position on disk `out/foo/bar/baz/meta.json`. When the old process dies and a new process starts, there will be a new instance of `Target` with the same implementation code and same position in the build hierarchy: this new `Target` -can then load the `out/foo/bar/baz.mill.json` file and pick up where the +can then load the `out/foo/bar/baz/meta.json` file and pick up where the previous process left off. Minimizing startup time means aggressive caching, as well as minimizing the @@ -328,9 +328,9 @@ the `Target`s you can run. A `Target`'s position in the module hierarchy tells you many things. For example, a `Target` at position `Core.test.compile` would: -- Cache output metadata at `out/Core/test/compile.mill.json` +- Cache output metadata at `out/Core/test/compile/meta.json` -- Output files to the folder `out/Core/test/compile/` +- Output files to the folder `out/Core/test/compile/dest/` - Be runnable from the command-line via `mill Core.test.compile` diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala index ee2ddf60..d6cd0f7a 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala @@ -78,14 +78,14 @@ object GenIdea { val Seq(sourcePath: PathRef) = evaluator.evaluate(OSet(mod.sources)).values - val (destPath, jsonPath) = Evaluator.resolveDestPaths( + val paths = Evaluator.resolveDestPaths( evaluator.workspacePath, evaluator.mapping.modules(mod.compile) ) val elem = moduleXmlTemplate( sourcePath.path, - Seq(destPath, jsonPath), + Seq(paths.base), resolvedDeps.map(pathToLibName), for(m <- mod.projectDeps) yield moduleName(moduleLabels(m)) diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala index 4272654a..b7948167 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala @@ -139,9 +139,9 @@ object HelloWorldTests extends TestSuite { val outPath = result.classes.path val analysisFile = result.analysisFile val outputFiles = ls.rec(outPath) - val expectedClassfiles = compileClassfiles.map(workspacePath / 'compile / 'classes / _) + val expectedClassfiles = compileClassfiles.map(workspacePath / 'compile / 'dest / 'classes / _) assert( - outPath == workspacePath / 'compile / 'classes, + outPath == workspacePath / 'compile / 'dest / 'classes, exists(analysisFile), outputFiles.nonEmpty, outputFiles.forall(expectedClassfiles.contains), @@ -168,14 +168,14 @@ object HelloWorldTests extends TestSuite { assert(err.isInstanceOf[CompileFailed]) - val (compilePath, compileMetadataPath) = Evaluator.resolveDestPaths( + val paths = Evaluator.resolveDestPaths( workspacePath, helloWorldEvaluator.evaluator.mapping.targets(HelloWorld.compile) ) assert( - ls.rec(compilePath / 'classes).isEmpty, - !exists(compileMetadataPath) + ls.rec(paths.dest / 'classes).isEmpty, + !exists(paths.meta) ) // Works when fixed write.over(mainObject, read(mainObject).dropRight("val x: ".length)) @@ -300,7 +300,7 @@ object HelloWorldTests extends TestSuite { 'logOutputToFile { helloWorldEvaluator(HelloWorld.compile) - val logFile = workspacePath / "compile.log" + val logFile = workspacePath / 'compile / 'log assert(exists(logFile)) } } @@ -12,7 +12,7 @@ sbt core/test scalaplugin/test scalajsplugin/test bin/test:assembly bin/target/mill devAssembly # Second build & run tests using Mill -out/devAssembly Core.test -out/devAssembly ScalaPlugin.test -out/devAssembly ScalaJSPlugin.test -out/devAssembly devAssembly
\ No newline at end of file +out/devAssembly/dest Core.test +out/devAssembly/dest ScalaPlugin.test +out/devAssembly/dest ScalaJSPlugin.test +out/devAssembly/dest devAssembly
\ No newline at end of file |