summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSheng Chen <shengcer@gmail.com>2018-03-26 22:57:18 -0400
committerLi Haoyi <haoyi.sg@gmail.com>2018-03-26 19:57:18 -0700
commita4713c3842c91a914cbc0ccd1f57339fa030f676 (patch)
tree2f1baa1eadcd01985db7cb3a58ffbc09896a94c6
parentc27a29058e990c5aa965bf71e19290de7f9793b4 (diff)
downloadmill-a4713c3842c91a914cbc0ccd1f57339fa030f676.tar.gz
mill-a4713c3842c91a914cbc0ccd1f57339fa030f676.tar.bz2
mill-a4713c3842c91a914cbc0ccd1f57339fa030f676.zip
add exclusions and custom configuration to dependencies (#254)
* doc to address #187 and #246 * add exclusions and custom configuration to dependencies and tests
-rw-r--r--scalalib/src/mill/scalalib/Dep.scala14
-rw-r--r--scalalib/src/mill/scalalib/publish/Ivy.scala8
-rw-r--r--scalalib/src/mill/scalalib/publish/Pom.scala28
-rw-r--r--scalalib/src/mill/scalalib/publish/settings.scala16
-rw-r--r--scalalib/test/src/mill/scalalib/ResolveDepsTests.scala18
-rw-r--r--scalalib/test/src/mill/scalalib/publish/IvyTests.scala60
-rw-r--r--scalalib/test/src/mill/scalalib/publish/PomTests.scala12
7 files changed, 141 insertions, 15 deletions
diff --git a/scalalib/src/mill/scalalib/Dep.scala b/scalalib/src/mill/scalalib/Dep.scala
index 78f454f2..f20480b7 100644
--- a/scalalib/src/mill/scalalib/Dep.scala
+++ b/scalalib/src/mill/scalalib/Dep.scala
@@ -3,6 +3,20 @@ import mill.util.JsonFormatters._
import upickle.default.{macroRW, ReadWriter => RW}
sealed trait Dep {
def configure(attributes: coursier.Attributes): Dep
+ def exclude(exclusions: (String, String)*): Dep =
+ this match {
+ case dep : Dep.Java => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ case dep : Dep.Point => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ }
+ def excludeOrg(organizations: String*): Dep = exclude(organizations.map(_ -> "*"): _*)
+ def excludeName(names: String*): Dep = exclude(names.map("*" -> _): _*)
+ def withConfiguration(configuration: String): Dep =
+ this match {
+ case dep : Dep.Java => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ case dep : Dep.Point => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ }
}
object Dep{
diff --git a/scalalib/src/mill/scalalib/publish/Ivy.scala b/scalalib/src/mill/scalalib/publish/Ivy.scala
index 644e2c53..3b271fa8 100644
--- a/scalalib/src/mill/scalalib/publish/Ivy.scala
+++ b/scalalib/src/mill/scalalib/publish/Ivy.scala
@@ -41,8 +41,12 @@ object Ivy {
}
private def renderDependency(dep: Dependency) = {
- val scope = scopeToConf(dep.scope)
- <dependency org={dep.artifact.group} name={dep.artifact.id} rev={dep.artifact.version} conf={s"$scope->default(compile)"}></dependency>
+ if (dep.exclusions.isEmpty)
+ <dependency org={dep.artifact.group} name={dep.artifact.id} rev={dep.artifact.version} conf={s"${dep.scope}->default(${dep.configuration.getOrElse("compile")})"} />
+ else
+ <dependency org={dep.artifact.group} name={dep.artifact.id} rev={dep.artifact.version} conf={s"${dep.scope}->default(${dep.configuration.getOrElse("compile")})"}>
+ {dep.exclusions.map(ex => <exclude org={ex._1} name={ex._2} matcher="exact"/>).toSeq}
+ </dependency>
}
private def scopeToConf(s: Scope): String = s match {
diff --git a/scalalib/src/mill/scalalib/publish/Pom.scala b/scalalib/src/mill/scalalib/publish/Pom.scala
index 1a86e7de..3c8ba4dc 100644
--- a/scalalib/src/mill/scalalib/publish/Pom.scala
+++ b/scalalib/src/mill/scalalib/publish/Pom.scala
@@ -90,12 +90,28 @@ object Pom {
case Scope.Test => <scope>test</scope>
case Scope.Runtime => <scope>runtime</scope>
}
- <dependency>
- <groupId>{d.artifact.group}</groupId>
- <artifactId>{d.artifact.id}</artifactId>
- <version>{d.artifact.version}</version>
- {scope}
- </dependency>
+ if (d.exclusions.isEmpty)
+ <dependency>
+ <groupId>{d.artifact.group}</groupId>
+ <artifactId>{d.artifact.id}</artifactId>
+ <version>{d.artifact.version}</version>
+ {scope}
+ </dependency>
+ else
+ <dependency>
+ <groupId>{d.artifact.group}</groupId>
+ <artifactId>{d.artifact.id}</artifactId>
+ <version>{d.artifact.version}</version>
+ <exclusions>
+ {d.exclusions.map(ex =>
+ <exclude>
+ <groupId>{ex._1}</groupId>
+ <artifactId>{ex._2}</artifactId>
+ </exclude>
+ )}.toSeq
+ </exclusions>
+ {scope}
+ </dependency>
}
}
diff --git a/scalalib/src/mill/scalalib/publish/settings.scala b/scalalib/src/mill/scalalib/publish/settings.scala
index 1076fb41..34f7e7ad 100644
--- a/scalalib/src/mill/scalalib/publish/settings.scala
+++ b/scalalib/src/mill/scalalib/publish/settings.scala
@@ -15,7 +15,9 @@ object Artifact {
case Dep.Java(dep, cross) =>
Dependency(
Artifact(dep.module.organization, dep.module.name, dep.version),
- Scope.Compile
+ Scope.Compile,
+ if (dep.configuration == "" ) None else Some(dep.configuration),
+ dep.exclusions.toList
)
case Dep.Scala(dep, cross) =>
Dependency(
@@ -24,7 +26,9 @@ object Artifact {
s"${dep.module.name}_${scalaBin}",
dep.version
),
- Scope.Compile
+ Scope.Compile,
+ if (dep.configuration == "") None else Some(dep.configuration),
+ dep.exclusions.toList
)
case Dep.Point(dep, cross) =>
Dependency(
@@ -33,7 +37,9 @@ object Artifact {
s"${dep.module.name}_${scalaFull}",
dep.version
),
- Scope.Compile
+ Scope.Compile,
+ if (dep.configuration == "") None else Some(dep.configuration),
+ dep.exclusions.toList
)
}
}
@@ -49,7 +55,9 @@ object Scope {
case class Dependency(
artifact: Artifact,
- scope: Scope
+ scope: Scope,
+ configuration: Option[String] = None,
+ exclusions: Seq[(String, String)] = Nil
)
case class Developer(
diff --git a/scalalib/test/src/mill/scalalib/ResolveDepsTests.scala b/scalalib/test/src/mill/scalalib/ResolveDepsTests.scala
index e9734557..b1fcec3e 100644
--- a/scalalib/test/src/mill/scalalib/ResolveDepsTests.scala
+++ b/scalalib/test/src/mill/scalalib/ResolveDepsTests.scala
@@ -26,6 +26,24 @@ object ResolveDepsTests extends TestSuite {
assert(paths.items.next.path.toString.contains("natives-macos"))
}
+ 'excludeTransitiveDeps - {
+ val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".exclude("com.lihaoyi" -> "fansi_2.12"))
+ val Success(paths) = evalDeps(deps)
+ assert(!paths.exists(_.path.toString.contains("fansi_2.12")))
+ }
+
+ 'excludeTransitiveDepsByOrg - {
+ val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".excludeOrg("com.lihaoyi"))
+ val Success(paths) = evalDeps(deps)
+ assert(!paths.exists(path => path.path.toString.contains("com/lihaoyi") && !path.path.toString.contains("pprint_2.12")))
+ }
+
+ 'excludeTransitiveDepsByName - {
+ val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".excludeName("fansi_2.12"))
+ val Success(paths) = evalDeps(deps)
+ assert(!paths.exists(_.path.toString.contains("fansi_2.12")))
+ }
+
'errOnInvalidOrgDeps - {
val deps = Agg(ivy"xxx.yyy.invalid::pprint:0.5.3")
val Failure(errMsg, _) = evalDeps(deps)
diff --git a/scalalib/test/src/mill/scalalib/publish/IvyTests.scala b/scalalib/test/src/mill/scalalib/publish/IvyTests.scala
new file mode 100644
index 00000000..0f275dd9
--- /dev/null
+++ b/scalalib/test/src/mill/scalalib/publish/IvyTests.scala
@@ -0,0 +1,60 @@
+package mill.scalalib.publish
+
+import utest._
+import mill._
+
+import scala.xml.{Node, NodeSeq, XML}
+
+object IvyTests extends TestSuite {
+
+ def tests: Tests = Tests {
+ val artifactId = "mill-scalalib_2.12"
+ val artifact =
+ Artifact("com.lihaoyi", "mill-scalalib_2.12", "0.0.1")
+ val deps = Agg(
+ Dependency(Artifact("com.lihaoyi", "mill-main_2.12", "0.1.4"),
+ Scope.Compile),
+ Dependency(Artifact("org.scala-sbt", "test-interface", "1.0"),
+ Scope.Compile),
+ Dependency(Artifact("com.lihaoyi", "pprint_2.12", "0.5.3"),
+ Scope.Compile, exclusions = List("com.lihaoyi" -> "fansi_2.12", "*" -> "sourcecode_2.12"))
+ )
+
+ 'fullIvy - {
+ val fullIvy = XML.loadString(Ivy(artifact, deps))
+
+ 'topLevel - {
+ val info = singleNode(fullIvy \ "info")
+ assert(
+ singleAttr(info, "organisation") == artifact.group
+ , singleAttr(info, "module") == artifact.id
+ , singleAttr(info, "revision") == artifact.version
+ )
+ }
+
+ 'dependencies - {
+ val dependencies = fullIvy \ "dependencies" \ "dependency"
+ val ivyDeps = deps.indexed
+
+ assert(dependencies.size == ivyDeps.size)
+
+ dependencies.zipWithIndex.foreach { case (dep, index) =>
+ assert(
+ singleAttr(dep, "org") == ivyDeps(index).artifact.group
+ , singleAttr(dep, "name") == ivyDeps(index).artifact.id
+ , singleAttr(dep, "rev") == ivyDeps(index).artifact.version
+ , (dep \ "exclude").zipWithIndex forall { case (exclude, j) =>
+ singleAttr(exclude, "org") == ivyDeps(index).exclusions(j)._1 &&
+ singleAttr(exclude, "name") == ivyDeps(index).exclusions(j)._2
+ }
+ )
+ }
+ }
+ }
+ }
+
+ def singleNode(seq: NodeSeq): Node =
+ seq.headOption.getOrElse(throw new RuntimeException("empty seq"))
+ def singleAttr(node: Node, attr: String): String =
+ node.attribute(attr).flatMap(_.headOption.map(_.text)).getOrElse(throw new RuntimeException(s"empty attr $attr"))
+}
diff --git a/scalalib/test/src/mill/scalalib/publish/PomTests.scala b/scalalib/test/src/mill/scalalib/publish/PomTests.scala
index 31e87446..c15ff172 100644
--- a/scalalib/test/src/mill/scalalib/publish/PomTests.scala
+++ b/scalalib/test/src/mill/scalalib/publish/PomTests.scala
@@ -15,7 +15,9 @@ object PomTests extends TestSuite {
Dependency(Artifact("com.lihaoyi", "mill-main_2.12", "0.1.4"),
Scope.Compile),
Dependency(Artifact("org.scala-sbt", "test-interface", "1.0"),
- Scope.Compile)
+ Scope.Compile),
+ Dependency(Artifact("com.lihaoyi", "pprint_2.12", "0.5.3"),
+ Scope.Compile, exclusions = List("com.lihaoyi" -> "fansi_2.12", "*" -> "sourcecode_2.12"))
)
val settings = PomSettings(
description = "mill-scalalib",
@@ -104,7 +106,7 @@ object PomTests extends TestSuite {
'dependencies - {
val dependencies = fullPom \ "dependencies" \ "dependency"
- assert(dependencies.size == 2)
+ assert(dependencies.size == 3)
val pomDeps = deps.indexed
@@ -114,7 +116,11 @@ object PomTests extends TestSuite {
singleText(dep \ "groupId") == pomDeps(index).artifact.group,
singleText(dep \ "artifactId") == pomDeps(index).artifact.id,
singleText(dep \ "version") == pomDeps(index).artifact.version,
- optText(dep \ "scope").isEmpty
+ optText(dep \ "scope").isEmpty,
+ (dep \ "exclusions").zipWithIndex.forall { case (node, j) =>
+ singleText(node \ "exclude" \ "groupId") == pomDeps(index).exclusions(j)._1 &&
+ singleText(node \ "exclude" \ "artifactId") == pomDeps(index).exclusions(j)._2
+ }
)
}
}