summaryrefslogtreecommitdiff
path: root/scalaplugin
diff options
context:
space:
mode:
authorGrant <gavares@gmail.com>2017-12-18 19:57:15 -0800
committerGitHub <noreply@github.com>2017-12-18 19:57:15 -0800
commit2ecfb282365f7fd8168bfb845cdbb403c00e9615 (patch)
treedc1a935a3bf33054697582a730cc4c3145de4d92 /scalaplugin
parentb83546cacea1292af3d4ae8e8c349f529b201ed2 (diff)
downloadmill-2ecfb282365f7fd8168bfb845cdbb403c00e9615.tar.gz
mill-2ecfb282365f7fd8168bfb845cdbb403c00e9615.tar.bz2
mill-2ecfb282365f7fd8168bfb845cdbb403c00e9615.zip
Report errors when dependency resolution fails (#71)
* Report errors when dependency resolution fails Function `Lib.reolveDependencies` now checks the result of the coursier dependency resolution for errors. The return value of the fuction is now a `Result[Seq[PathRef]]` and errors are signaled by returning an instance of Failure when errors occur while resolving dependencies. `ScalaModule` now has a new task called `resolve` which allows for triggering dependency resolution directly from the cmd line like: `mill run resolve`. `ResolveDepsTests` was added to verify failed resolution is properly detected and reported. * Remove type signatures in ScalaModule.scala * Updates from PR comments
Diffstat (limited to 'scalaplugin')
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/Lib.scala39
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala12
-rw-r--r--scalaplugin/src/test/resource/resolve-deps/src/main/scala/Main.scala3
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/ResolveDepsTests.scala39
4 files changed, 76 insertions, 17 deletions
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/Lib.scala b/scalaplugin/src/main/scala/mill/scalaplugin/Lib.scala
index 637906a5..c89254b0 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/Lib.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/Lib.scala
@@ -6,7 +6,7 @@ import java.net.URLClassLoader
import java.util.Optional
import ammonite.ops._
-import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution}
+import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution, Module => CoursierModule}
import mill.define.Worker
import mill.eval.{PathRef, Result}
import mill.util.Ctx
@@ -159,7 +159,7 @@ object Lib{
scalaVersion: String,
scalaBinaryVersion: String,
deps: Seq[Dep],
- sources: Boolean = false): Seq[PathRef] = {
+ sources: Boolean = false): Result[Seq[PathRef]] = {
val flattened = deps.map{
case Dep.Java(dep) => dep
case Dep.Scala(dep) =>
@@ -171,15 +171,30 @@ object Lib{
val fetch = Fetch.from(repositories, Cache.fetch())
val resolution = start.process.run(fetch).unsafePerformSync
- val sourceOrJar =
- if (sources) resolution.classifiersArtifacts(Seq("sources"))
- else resolution.artifacts
- val localArtifacts: Seq[File] = scalaz.concurrent.Task
- .gatherUnordered(sourceOrJar.map(Cache.file(_).run))
- .unsafePerformSync
- .flatMap(_.toOption)
-
- localArtifacts.map(p => PathRef(Path(p), quick = true))
+ val errs = resolution.metadataErrors
+ if(errs.nonEmpty) {
+ val header =
+ s"""|
+ |Resolution failed for ${errs.length} modules:
+ |--------------------------------------------
+ |""".stripMargin
+
+ val errLines = errs.map {
+ case ((module, vsn), errMsgs) => s" ${module.trim}:$vsn \n\t" + errMsgs.mkString("\n\t")
+ }.mkString("\n")
+ val msg = header + errLines + "\n"
+ Result.Failure(msg)
+ } else {
+ val sourceOrJar =
+ if (sources) resolution.classifiersArtifacts(Seq("sources"))
+ else resolution.artifacts
+ val localArtifacts: Seq[File] = scalaz.concurrent.Task
+ .gatherUnordered(sourceOrJar.map(Cache.file(_).run))
+ .unsafePerformSync
+ .flatMap(_.toOption)
+
+ localArtifacts.map(p => PathRef(Path(p), quick = true))
+ }
}
def scalaCompilerIvyDeps(scalaVersion: String) = Seq(
Dep.Java("org.scala-lang", "scala-compiler", scalaVersion),
@@ -195,4 +210,4 @@ object Lib{
"#!/usr/bin/env sh",
"exec java -jar \"$0\" \"$@\""
)
-} \ No newline at end of file
+}
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
index 9f9425a4..ce7b5e00 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
@@ -2,13 +2,12 @@ package mill
package scalaplugin
import ammonite.ops._
-import coursier.{Cache, MavenRepository, Repository, Resolution}
-import mill.define.Task
+import coursier.{Cache, MavenRepository, Repository}
+import mill.define.{Source, Task}
import mill.define.Task.{Module, TaskModule}
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess}
-
import Lib._
trait TestScalaModule extends ScalaModule with TaskModule {
override def defaultCommandName() = "test"
@@ -101,6 +100,7 @@ trait ScalaModule extends Module with TaskModule{ outer =>
sources
)
}
+
def externalCompileDepClasspath: T[Seq[PathRef]] = T{
Task.traverse(projectDeps)(_.externalCompileDepClasspath)().flatten ++
resolveDeps(
@@ -115,6 +115,7 @@ trait ScalaModule extends Module with TaskModule{ outer =>
sources = true
)()
}
+
/**
* Things that need to be on the classpath in order for this code to compile;
* might be less than the runtime classpath
@@ -140,8 +141,9 @@ trait ScalaModule extends Module with TaskModule{ outer =>
Seq(dep)
)
classpath match {
- case Seq(single) => PathRef(single.path, quick = true)
- case Seq() => throw new Exception(dep + " resolution failed")
+ case Result.Success(Seq(single)) => PathRef(single.path, quick = true)
+ case Result.Success(Seq()) => throw new Exception(dep + " resolution failed")
+ case f: Result.Failure => throw new Exception(dep + s" resolution failed.\n + ${f.msg}")
case _ => throw new Exception(dep + " resolution resulted in more than one file")
}
}
diff --git a/scalaplugin/src/test/resource/resolve-deps/src/main/scala/Main.scala b/scalaplugin/src/test/resource/resolve-deps/src/main/scala/Main.scala
new file mode 100644
index 00000000..5dcbe39a
--- /dev/null
+++ b/scalaplugin/src/test/resource/resolve-deps/src/main/scala/Main.scala
@@ -0,0 +1,3 @@
+object Main {
+ println("ResolveDeps Main: hello world!")
+}
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/ResolveDepsTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/ResolveDepsTests.scala
new file mode 100644
index 00000000..cd6bd40f
--- /dev/null
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/ResolveDepsTests.scala
@@ -0,0 +1,39 @@
+package mill.scalaplugin
+
+import coursier.Cache
+import coursier.maven.MavenRepository
+import mill.eval.Result.{Failure, Success}
+import mill.eval.{PathRef, Result}
+import utest._
+
+object ResolveDepsTests extends TestSuite {
+ val repos = Seq(Cache.ivy2Local, MavenRepository("https://repo1.maven.org/maven2"))
+
+ def evalDeps(deps: Seq[Dep]): Result[Seq[PathRef]] = Lib.resolveDependencies(repos, "2.12.4", "2.12", deps)
+
+ val tests = Tests {
+ 'resolveValidDeps - {
+ val deps = Seq(Dep("com.lihaoyi", "pprint", "0.5.3"))
+ val Success(paths) = evalDeps(deps)
+ assert(paths.nonEmpty)
+ }
+
+ 'errOnInvalidOrgDeps - {
+ val deps = Seq(Dep("xxx.yyy.invalid", "pprint", "0.5.3"))
+ val Failure(errMsg) = evalDeps(deps)
+ assert(errMsg.contains("xxx.yyy.invalid"))
+ }
+
+ 'errOnInvalidVersionDeps - {
+ val deps = Seq(Dep("com.lihaoyi", "pprint", "invalid.version.num"))
+ val Failure(errMsg) = evalDeps(deps)
+ assert(errMsg.contains("invalid.version.num"))
+ }
+
+ 'errOnPartialSuccess - {
+ val deps = Seq(Dep("com.lihaoyi", "pprint", "0.5.3"), Dep("fake", "fake", "fake"))
+ val Failure(errMsg) = evalDeps(deps)
+ assert(errMsg.contains("fake"))
+ }
+ }
+}