From d1c65c7e85467c23a31291b02d2f8fa5889335dc Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 15 Jan 2018 22:48:04 -0800 Subject: - Swap over to new `ivy"foo:bar:baz"` syntax for defining ivy dependencies - `projectDeps` is now `moduleDeps` for compatibility with our `Module` terminology - `scalalib.Module` is now `ScalaModule` for compatibility with `import scalalib._` --- scalalib/src/main/scala/mill/scalalib/Dep.scala | 9 + .../src/main/scala/mill/scalalib/GenIdea.scala | 4 +- .../src/main/scala/mill/scalalib/MiscModule.scala | 2 +- scalalib/src/main/scala/mill/scalalib/Module.scala | 310 --------------------- .../main/scala/mill/scalalib/PublishModule.scala | 2 +- .../src/main/scala/mill/scalalib/ScalaModule.scala | 310 +++++++++++++++++++++ .../src/main/scala/mill/scalalib/package.scala | 9 +- .../test/scala/mill/scalalib/HelloWorldTests.scala | 2 +- .../scala/mill/scalalib/ResolveDepsTests.scala | 8 +- 9 files changed, 336 insertions(+), 320 deletions(-) delete mode 100644 scalalib/src/main/scala/mill/scalalib/Module.scala create mode 100644 scalalib/src/main/scala/mill/scalalib/ScalaModule.scala (limited to 'scalalib/src') diff --git a/scalalib/src/main/scala/mill/scalalib/Dep.scala b/scalalib/src/main/scala/mill/scalalib/Dep.scala index 3d4c43ac..aa301fcb 100644 --- a/scalalib/src/main/scala/mill/scalalib/Dep.scala +++ b/scalalib/src/main/scala/mill/scalalib/Dep.scala @@ -3,6 +3,15 @@ import mill.util.JsonFormatters._ import upickle.default.{macroRW, ReadWriter => RW} sealed trait Dep object Dep{ + + implicit def parse(signature: String) = { + signature.split(':') match{ + case Array(a, b, c) => Dep.Java(a, b, c) + case Array(a, "", b, c) => Dep.Scala(a, b, c) + case Array(a, "", "", b, c) => Dep.Point(a, b, c) + case _ => throw new Exception(s"Unable to parse signature: [$signature]") + } + } def apply(org: String, name: String, version: String): Dep = { this(coursier.Dependency(coursier.Module(org, name), version)) } diff --git a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala index b11c58f3..e9d8fac5 100644 --- a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala +++ b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala @@ -27,7 +27,7 @@ object GenIdea { def xmlFileLayout[T](evaluator: Evaluator[T], rootModule: mill.Module): Seq[(RelPath, scala.xml.Node)] = { - val modules = rootModule.millInternal.segmentsToModules.values.collect{case x: scalalib.Module => (x.millModuleSegments, x)}.toSeq + val modules = rootModule.millInternal.segmentsToModules.values.collect{case x: scalalib.ScalaModule => (x.millModuleSegments, x)}.toSeq val resolved = for((path, mod) <- modules) yield { val Seq(resolvedCp: Loose.Agg[PathRef], resolvedSrcs: Loose.Agg[PathRef]) = @@ -87,7 +87,7 @@ object GenIdea { Strict.Agg.from(generatedSourcePaths), Strict.Agg(paths.out), Strict.Agg.from(resolvedDeps.map(pathToLibName)), - Strict.Agg.from(mod.projectDeps.map{m => moduleName(moduleLabels(m))}.distinct) + Strict.Agg.from(mod.moduleDeps.map{ m => moduleName(moduleLabels(m))}.distinct) ) Tuple2(".idea_modules"/s"${moduleName(path)}.iml", elem) } diff --git a/scalalib/src/main/scala/mill/scalalib/MiscModule.scala b/scalalib/src/main/scala/mill/scalalib/MiscModule.scala index 5e28c34b..52a95337 100644 --- a/scalalib/src/main/scala/mill/scalalib/MiscModule.scala +++ b/scalalib/src/main/scala/mill/scalalib/MiscModule.scala @@ -7,7 +7,7 @@ import mill.eval.{PathRef, Result} import mill.util.Loose.Agg -trait SbtModule extends Module { outer => +trait SbtModule extends ScalaModule { outer => override def sources = T.input{ Agg(PathRef(basePath / 'src / 'main / 'scala)) } override def resources = T.input{ Agg(PathRef(basePath / 'src / 'main / 'resources)) } trait Tests extends super.Tests { diff --git a/scalalib/src/main/scala/mill/scalalib/Module.scala b/scalalib/src/main/scala/mill/scalalib/Module.scala deleted file mode 100644 index 48eb4b14..00000000 --- a/scalalib/src/main/scala/mill/scalalib/Module.scala +++ /dev/null @@ -1,310 +0,0 @@ -package mill -package scalalib - -import ammonite.ops._ -import coursier.{Cache, MavenRepository, Repository} -import mill.define.{Cross, Task} -import mill.define.TaskModule -import mill.eval.{PathRef, Result} -import mill.modules.Jvm -import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess} -import Lib._ -import mill.define.Cross.Resolver -import mill.util.Loose.Agg -import sbt.testing.Status - -/** - * Core configuration required to compile a single Scala compilation target - */ -trait Module extends mill.Module with TaskModule { outer => - def defaultCommandName() = "run" - trait Tests extends TestModule{ - def scalaVersion = outer.scalaVersion() - override def projectDeps = Seq(outer) - } - def scalaVersion: T[String] - def mainClass: T[Option[String]] = None - - def scalaBinaryVersion = T{ scalaVersion().split('.').dropRight(1).mkString(".") } - def ivyDeps = T{ Agg.empty[Dep] } - def compileIvyDeps = T{ Agg.empty[Dep] } - def scalacPluginIvyDeps = T{ Agg.empty[Dep] } - def runIvyDeps = T{ Agg.empty[Dep] } - - def scalacOptions = T{ Seq.empty[String] } - def javacOptions = T{ Seq.empty[String] } - - def repositories: Seq[Repository] = Seq( - Cache.ivy2Local, - MavenRepository("https://repo1.maven.org/maven2") - ) - - def projectDeps = Seq.empty[Module] - def depClasspath = T{ Agg.empty[PathRef] } - - - def upstreamRunClasspath = T{ - Task.traverse(projectDeps)(p => - T.task(p.runDepClasspath() ++ p.runClasspath()) - ) - } - - def upstreamCompileOutput = T{ - Task.traverse(projectDeps)(_.compile) - } - def upstreamCompileClasspath = T{ - externalCompileDepClasspath() ++ - upstreamCompileOutput().map(_.classes) ++ - Task.traverse(projectDeps)(_.compileDepClasspath)().flatten - } - - def resolveDeps(deps: Task[Agg[Dep]], sources: Boolean = false) = T.task{ - resolveDependencies( - repositories, - scalaVersion(), - scalaBinaryVersion(), - deps(), - sources - ) - } - - def externalCompileDepClasspath: T[Agg[PathRef]] = T{ - Agg.from(Task.traverse(projectDeps)(_.externalCompileDepClasspath)().flatten) ++ - resolveDeps( - T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())} - )() - } - - def externalCompileDepSources: T[Agg[PathRef]] = T{ - Agg.from(Task.traverse(projectDeps)(_.externalCompileDepSources)().flatten) ++ - resolveDeps( - T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())}, - sources = true - )() - } - - /** - * Things that need to be on the classpath in order for this code to compile; - * might be less than the runtime classpath - */ - def compileDepClasspath: T[Agg[PathRef]] = T{ - upstreamCompileClasspath() ++ - depClasspath() - } - - /** - * Strange compiler-bridge jar that the Zinc incremental compile needs - */ - def compilerBridge: T[PathRef] = T{ - val compilerBridgeKey = "MILL_COMPILER_BRIDGE_" + scalaVersion().replace('.', '_') - val compilerBridgePath = sys.props(compilerBridgeKey) - if (compilerBridgePath != null) PathRef(Path(compilerBridgePath), quick = true) - else { - val dep = compilerBridgeIvyDep(scalaVersion()) - val classpath = resolveDependencies( - repositories, - scalaVersion(), - scalaBinaryVersion(), - Seq(dep) - ) - classpath match { - case Result.Success(resolved) => - resolved.filter(_.path.ext != "pom").toSeq match { - case Seq(single) => PathRef(single.path, quick = true) - case Seq() => throw new Exception(dep + " resolution failed") // TODO: find out, is it possible? - case _ => throw new Exception(dep + " resolution resulted in more than one file") - } - case f: Result.Failure => throw new Exception(dep + s" resolution failed.\n + ${f.msg}") // TODO: remove, resolveDependencies will take care of this. - } - } - } - - def scalacPluginClasspath: T[Agg[PathRef]] = - resolveDeps( - T.task{scalacPluginIvyDeps()} - )() - - /** - * Classpath of the Scala Compiler & any compiler plugins - */ - def scalaCompilerClasspath: T[Agg[PathRef]] = T{ - resolveDeps( - T.task{scalaCompilerIvyDeps(scalaVersion()) ++ scalaRuntimeIvyDeps(scalaVersion())} - )() - } - - /** - * Things that need to be on the classpath in order for this code to run - */ - def runDepClasspath: T[Agg[PathRef]] = T{ - Agg.from(upstreamRunClasspath().flatten) ++ - depClasspath() ++ - resolveDeps( - T.task{ivyDeps() ++ runIvyDeps() ++ scalaRuntimeIvyDeps(scalaVersion())} - )() - } - - def prependShellScript: T[String] = T{ "" } - - def sources = T.input{ Agg(PathRef(basePath / 'src)) } - def resources = T.input{ Agg(PathRef(basePath / 'resources)) } - def generatedSources = T { Agg.empty[PathRef] } - def allSources = T{ sources() ++ generatedSources() } - def compile: T[CompilationResult] = T.persistent{ - compileScala( - ZincWorker(), - scalaVersion(), - allSources().map(_.path), - compileDepClasspath().map(_.path), - scalaCompilerClasspath().map(_.path), - scalacPluginClasspath().map(_.path), - compilerBridge().path, - scalacOptions(), - scalacPluginClasspath().map(_.path), - javacOptions(), - upstreamCompileOutput() - ) - } - def runClasspath = T{ - runDepClasspath() ++ resources() ++ Seq(compile().classes) - } - - def assembly = T{ - createAssembly( - runClasspath().map(_.path).filter(exists), - mainClass(), - prependShellScript = prependShellScript() - ) - } - - def localClasspath = T{ resources() ++ Seq(compile().classes) } - - def jar = T{ - createJar( - localClasspath().map(_.path).filter(exists), - mainClass() - ) - } - - def docsJar = T { - val outDir = T.ctx().dest - - val javadocDir = outDir / 'javadoc - mkdir(javadocDir) - - val options = { - - val files = for{ - ref <- sources() - p <- ls.rec(ref.path) - if p.isFile - } yield p.toNIO.toString - files ++ Seq("-d", javadocDir.toNIO.toString, "-usejavacp") - } - - subprocess( - "scala.tools.nsc.ScalaDoc", - compileDepClasspath().filter(_.path.ext != "pom").map(_.path), - options = options.toSeq - ) - - createJar(Agg(javadocDir))(outDir / "javadoc.jar") - } - - def sourcesJar = T { - createJar((sources() ++ resources()).map(_.path).filter(exists))(T.ctx().dest / "sources.jar") - } - - def forkArgs = T{ Seq.empty[String] } - - def run(args: String*) = T.command{ - subprocess( - mainClass().getOrElse(throw new RuntimeException("No mainClass provided!")), - runClasspath().map(_.path), - forkArgs(), - args, - workingDir = ammonite.ops.pwd) - } - - def runMain(mainClass: String, args: String*) = T.command{ - subprocess( - mainClass, - runClasspath().map(_.path), - forkArgs(), - args, - workingDir = ammonite.ops.pwd - ) - } - - def console() = T.command{ - interactiveSubprocess( - mainClass = "scala.tools.nsc.MainGenericRunner", - classPath = runClasspath().map(_.path), - options = Seq("-usejavacp") - ) - } - - // publish artifact with name "mill_2.12.4" instead of "mill_2.12" - def crossFullScalaVersion: T[Boolean] = false - - def artifactName: T[String] = basePath.last.toString - def artifactScalaVersion: T[String] = T { - if (crossFullScalaVersion()) scalaVersion() - else scalaBinaryVersion() - } - - def artifactId: T[String] = T { s"${artifactName()}_${artifactScalaVersion()}" } - -} - - -object TestModule{ - def handleResults(doneMsg: String, results: Seq[TestRunner.Result]) = { - if (results.count(Set(Status.Error, Status.Failure)) == 0) Result.Success((doneMsg, results)) - else { - val grouped = results.map(_.status).groupBy(x => x).mapValues(_.length).filter(_._2 != 0).toList.sorted - - Result.Failure(grouped.map{case (k, v) => k + ": " + v}.mkString(",")) - } - } -} -trait TestModule extends Module with TaskModule { - override def defaultCommandName() = "test" - def testFramework: T[String] - - def forkWorkingDir = ammonite.ops.pwd - - def forkTest(args: String*) = T.command{ - mkdir(T.ctx().dest) - val outputPath = T.ctx().dest/"out.json" - - Jvm.subprocess( - mainClass = "mill.scalalib.TestRunner", - classPath = Jvm.gatherClassloaderJars(), - jvmOptions = forkArgs(), - options = Seq( - testFramework(), - runClasspath().map(_.path).mkString(" "), - Seq(compile().classes.path).mkString(" "), - args.mkString(" "), - outputPath.toString, - T.ctx().log.colored.toString - ), - workingDir = forkWorkingDir - ) - - val jsonOutput = upickle.json.read(outputPath.toIO) - val (doneMsg, results) = upickle.default.readJs[(String, Seq[TestRunner.Result])](jsonOutput) - TestModule.handleResults(doneMsg, results) - - } - def test(args: String*) = T.command{ - val (doneMsg, results) = TestRunner( - testFramework(), - runClasspath().map(_.path), - Agg(compile().classes.path), - args - ) - TestModule.handleResults(doneMsg, results) - } -} \ No newline at end of file diff --git a/scalalib/src/main/scala/mill/scalalib/PublishModule.scala b/scalalib/src/main/scala/mill/scalalib/PublishModule.scala index 4fd8e94f..64efce77 100644 --- a/scalalib/src/main/scala/mill/scalalib/PublishModule.scala +++ b/scalalib/src/main/scala/mill/scalalib/PublishModule.scala @@ -7,7 +7,7 @@ import mill.util.Loose.Agg /** * Configuration necessary for publishing a Scala module to Maven Central or similar */ -trait PublishModule extends Module { outer => +trait PublishModule extends ScalaModule { outer => import mill.scalalib.publish._ def pomSettings: T[PomSettings] diff --git a/scalalib/src/main/scala/mill/scalalib/ScalaModule.scala b/scalalib/src/main/scala/mill/scalalib/ScalaModule.scala new file mode 100644 index 00000000..5bae1749 --- /dev/null +++ b/scalalib/src/main/scala/mill/scalalib/ScalaModule.scala @@ -0,0 +1,310 @@ +package mill +package scalalib + +import ammonite.ops._ +import coursier.{Cache, MavenRepository, Repository} +import mill.define.{Cross, Task} +import mill.define.TaskModule +import mill.eval.{PathRef, Result} +import mill.modules.Jvm +import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess} +import Lib._ +import mill.define.Cross.Resolver +import mill.util.Loose.Agg +import sbt.testing.Status + +/** + * Core configuration required to compile a single Scala compilation target + */ +trait ScalaModule extends mill.Module with TaskModule { outer => + def defaultCommandName() = "run" + trait Tests extends TestModule{ + def scalaVersion = outer.scalaVersion() + override def moduleDeps = Seq(outer) + } + def scalaVersion: T[String] + def mainClass: T[Option[String]] = None + + def scalaBinaryVersion = T{ scalaVersion().split('.').dropRight(1).mkString(".") } + def ivyDeps = T{ Agg.empty[Dep] } + def compileIvyDeps = T{ Agg.empty[Dep] } + def scalacPluginIvyDeps = T{ Agg.empty[Dep] } + def runIvyDeps = T{ Agg.empty[Dep] } + + def scalacOptions = T{ Seq.empty[String] } + def javacOptions = T{ Seq.empty[String] } + + def repositories: Seq[Repository] = Seq( + Cache.ivy2Local, + MavenRepository("https://repo1.maven.org/maven2") + ) + + def moduleDeps = Seq.empty[ScalaModule] + def depClasspath = T{ Agg.empty[PathRef] } + + + def upstreamRunClasspath = T{ + Task.traverse(moduleDeps)(p => + T.task(p.runDepClasspath() ++ p.runClasspath()) + ) + } + + def upstreamCompileOutput = T{ + Task.traverse(moduleDeps)(_.compile) + } + def upstreamCompileClasspath = T{ + externalCompileDepClasspath() ++ + upstreamCompileOutput().map(_.classes) ++ + Task.traverse(moduleDeps)(_.compileDepClasspath)().flatten + } + + def resolveDeps(deps: Task[Agg[Dep]], sources: Boolean = false) = T.task{ + resolveDependencies( + repositories, + scalaVersion(), + scalaBinaryVersion(), + deps(), + sources + ) + } + + def externalCompileDepClasspath: T[Agg[PathRef]] = T{ + Agg.from(Task.traverse(moduleDeps)(_.externalCompileDepClasspath)().flatten) ++ + resolveDeps( + T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())} + )() + } + + def externalCompileDepSources: T[Agg[PathRef]] = T{ + Agg.from(Task.traverse(moduleDeps)(_.externalCompileDepSources)().flatten) ++ + resolveDeps( + T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())}, + sources = true + )() + } + + /** + * Things that need to be on the classpath in order for this code to compile; + * might be less than the runtime classpath + */ + def compileDepClasspath: T[Agg[PathRef]] = T{ + upstreamCompileClasspath() ++ + depClasspath() + } + + /** + * Strange compiler-bridge jar that the Zinc incremental compile needs + */ + def compilerBridge: T[PathRef] = T{ + val compilerBridgeKey = "MILL_COMPILER_BRIDGE_" + scalaVersion().replace('.', '_') + val compilerBridgePath = sys.props(compilerBridgeKey) + if (compilerBridgePath != null) PathRef(Path(compilerBridgePath), quick = true) + else { + val dep = compilerBridgeIvyDep(scalaVersion()) + val classpath = resolveDependencies( + repositories, + scalaVersion(), + scalaBinaryVersion(), + Seq(dep) + ) + classpath match { + case Result.Success(resolved) => + resolved.filter(_.path.ext != "pom").toSeq match { + case Seq(single) => PathRef(single.path, quick = true) + case Seq() => throw new Exception(dep + " resolution failed") // TODO: find out, is it possible? + case _ => throw new Exception(dep + " resolution resulted in more than one file") + } + case f: Result.Failure => throw new Exception(dep + s" resolution failed.\n + ${f.msg}") // TODO: remove, resolveDependencies will take care of this. + } + } + } + + def scalacPluginClasspath: T[Agg[PathRef]] = + resolveDeps( + T.task{scalacPluginIvyDeps()} + )() + + /** + * Classpath of the Scala Compiler & any compiler plugins + */ + def scalaCompilerClasspath: T[Agg[PathRef]] = T{ + resolveDeps( + T.task{scalaCompilerIvyDeps(scalaVersion()) ++ scalaRuntimeIvyDeps(scalaVersion())} + )() + } + + /** + * Things that need to be on the classpath in order for this code to run + */ + def runDepClasspath: T[Agg[PathRef]] = T{ + Agg.from(upstreamRunClasspath().flatten) ++ + depClasspath() ++ + resolveDeps( + T.task{ivyDeps() ++ runIvyDeps() ++ scalaRuntimeIvyDeps(scalaVersion())} + )() + } + + def prependShellScript: T[String] = T{ "" } + + def sources = T.input{ Agg(PathRef(basePath / 'src)) } + def resources = T.input{ Agg(PathRef(basePath / 'resources)) } + def generatedSources = T { Agg.empty[PathRef] } + def allSources = T{ sources() ++ generatedSources() } + def compile: T[CompilationResult] = T.persistent{ + compileScala( + ZincWorker(), + scalaVersion(), + allSources().map(_.path), + compileDepClasspath().map(_.path), + scalaCompilerClasspath().map(_.path), + scalacPluginClasspath().map(_.path), + compilerBridge().path, + scalacOptions(), + scalacPluginClasspath().map(_.path), + javacOptions(), + upstreamCompileOutput() + ) + } + def runClasspath = T{ + runDepClasspath() ++ resources() ++ Seq(compile().classes) + } + + def assembly = T{ + createAssembly( + runClasspath().map(_.path).filter(exists), + mainClass(), + prependShellScript = prependShellScript() + ) + } + + def localClasspath = T{ resources() ++ Seq(compile().classes) } + + def jar = T{ + createJar( + localClasspath().map(_.path).filter(exists), + mainClass() + ) + } + + def docsJar = T { + val outDir = T.ctx().dest + + val javadocDir = outDir / 'javadoc + mkdir(javadocDir) + + val options = { + + val files = for{ + ref <- sources() + p <- ls.rec(ref.path) + if p.isFile + } yield p.toNIO.toString + files ++ Seq("-d", javadocDir.toNIO.toString, "-usejavacp") + } + + subprocess( + "scala.tools.nsc.ScalaDoc", + compileDepClasspath().filter(_.path.ext != "pom").map(_.path), + options = options.toSeq + ) + + createJar(Agg(javadocDir))(outDir / "javadoc.jar") + } + + def sourcesJar = T { + createJar((sources() ++ resources()).map(_.path).filter(exists))(T.ctx().dest / "sources.jar") + } + + def forkArgs = T{ Seq.empty[String] } + + def run(args: String*) = T.command{ + subprocess( + mainClass().getOrElse(throw new RuntimeException("No mainClass provided!")), + runClasspath().map(_.path), + forkArgs(), + args, + workingDir = ammonite.ops.pwd) + } + + def runMain(mainClass: String, args: String*) = T.command{ + subprocess( + mainClass, + runClasspath().map(_.path), + forkArgs(), + args, + workingDir = ammonite.ops.pwd + ) + } + + def console() = T.command{ + interactiveSubprocess( + mainClass = "scala.tools.nsc.MainGenericRunner", + classPath = runClasspath().map(_.path), + options = Seq("-usejavacp") + ) + } + + // publish artifact with name "mill_2.12.4" instead of "mill_2.12" + def crossFullScalaVersion: T[Boolean] = false + + def artifactName: T[String] = basePath.last.toString + def artifactScalaVersion: T[String] = T { + if (crossFullScalaVersion()) scalaVersion() + else scalaBinaryVersion() + } + + def artifactId: T[String] = T { s"${artifactName()}_${artifactScalaVersion()}" } + +} + + +object TestModule{ + def handleResults(doneMsg: String, results: Seq[TestRunner.Result]) = { + if (results.count(Set(Status.Error, Status.Failure)) == 0) Result.Success((doneMsg, results)) + else { + val grouped = results.map(_.status).groupBy(x => x).mapValues(_.length).filter(_._2 != 0).toList.sorted + + Result.Failure(grouped.map{case (k, v) => k + ": " + v}.mkString(",")) + } + } +} +trait TestModule extends ScalaModule with TaskModule { + override def defaultCommandName() = "test" + def testFramework: T[String] + + def forkWorkingDir = ammonite.ops.pwd + + def forkTest(args: String*) = T.command{ + mkdir(T.ctx().dest) + val outputPath = T.ctx().dest/"out.json" + + Jvm.subprocess( + mainClass = "mill.scalalib.TestRunner", + classPath = Jvm.gatherClassloaderJars(), + jvmOptions = forkArgs(), + options = Seq( + testFramework(), + runClasspath().map(_.path).mkString(" "), + Seq(compile().classes.path).mkString(" "), + args.mkString(" "), + outputPath.toString, + T.ctx().log.colored.toString + ), + workingDir = forkWorkingDir + ) + + val jsonOutput = upickle.json.read(outputPath.toIO) + val (doneMsg, results) = upickle.default.readJs[(String, Seq[TestRunner.Result])](jsonOutput) + TestModule.handleResults(doneMsg, results) + + } + def test(args: String*) = T.command{ + val (doneMsg, results) = TestRunner( + testFramework(), + runClasspath().map(_.path), + Agg(compile().classes.path), + args + ) + TestModule.handleResults(doneMsg, results) + } +} \ No newline at end of file diff --git a/scalalib/src/main/scala/mill/scalalib/package.scala b/scalalib/src/main/scala/mill/scalalib/package.scala index 1bad9226..5a282e82 100644 --- a/scalalib/src/main/scala/mill/scalalib/package.scala +++ b/scalalib/src/main/scala/mill/scalalib/package.scala @@ -1,5 +1,12 @@ package mill package object scalalib { - + implicit class DepSyntax(ctx: StringContext){ + def ivy(args: Any*) = Dep.parse{ + ( + ctx.parts.take(args.length).zip(args).flatMap{case (p, a) => Seq(p, a)} ++ + ctx.parts.drop(args.length) + ).mkString + } + } } diff --git a/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala b/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala index 657ddc9e..70c78cee 100644 --- a/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala +++ b/scalalib/src/test/scala/mill/scalalib/HelloWorldTests.scala @@ -16,7 +16,7 @@ import scala.collection.JavaConverters._ object HelloWorldTests extends TestSuite { - trait HelloWorldModule extends scalalib.Module { + trait HelloWorldModule extends scalalib.ScalaModule { def scalaVersion = "2.12.4" def basePath = HelloWorldTests.workingSrcPath } diff --git a/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala b/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala index f28df152..d1ddde20 100644 --- a/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala +++ b/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala @@ -14,25 +14,25 @@ object ResolveDepsTests extends TestSuite { val tests = Tests { 'resolveValidDeps - { - val deps = Agg(Dep("com.lihaoyi", "pprint", "0.5.3")) + val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3") val Success(paths) = evalDeps(deps) assert(paths.nonEmpty) } 'errOnInvalidOrgDeps - { - val deps = Agg(Dep("xxx.yyy.invalid", "pprint", "0.5.3")) + val deps = Agg(ivy"xxx.yyy.invalid::pprint:0.5.3") val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("xxx.yyy.invalid")) } 'errOnInvalidVersionDeps - { - val deps = Agg(Dep("com.lihaoyi", "pprint", "invalid.version.num")) + val deps = Agg(ivy"com.lihaoyi::pprint:invalid.version.num") val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("invalid.version.num")) } 'errOnPartialSuccess - { - val deps = Agg(Dep("com.lihaoyi", "pprint", "0.5.3"), Dep("fake", "fake", "fake")) + val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3", ivy"fake::fake:fake") val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("fake")) } -- cgit v1.2.3