Better handling of Maven scopes

Actually a regression introduced when Ivy support was added

Fixes https://github.com/alexarchambault/coursier/issues/178,
https://github.com/alexarchambault/coursier/issues/177
This commit is contained in:
Alexandre Archambault 2016-02-28 16:36:58 +01:00
parent b9895ce801
commit 5bbe01bfdd
14 changed files with 134 additions and 59 deletions

View File

@ -147,6 +147,7 @@ lazy val core = crossProject
Seq(
// Since 1.0.0-M10
ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.core.Resolution.withParentConfigurations"),
// New singleton object, problem for forward compatibility only
ProblemFilters.exclude[MissingTypesProblem]("coursier.maven.MavenSource$")
)

View File

@ -25,9 +25,11 @@ final case class Module(
.map { case (k, v) => s"$k=$v" }
.mkString(";")
override def toString =
s"$organization:$name" +
(if (attributes.nonEmpty) s";$attributesStr" else "")
def nameWithAttributes: String =
name + (if (attributes.nonEmpty) s";$attributesStr" else "")
override def toString: String =
s"$organization:$nameWithAttributes"
override final lazy val hashCode = Module.unapply(this).get.hashCode()
}

View File

@ -280,7 +280,7 @@ object Resolution {
}
}
def withParentConfigurations(config: String, configurations: Map[String, Seq[String]]): Set[String] = {
def withParentConfigurations(config: String, configurations: Map[String, Seq[String]]): (String, Set[String]) = {
@tailrec
def helper(configs: Set[String], acc: Set[String]): Set[String] =
if (configs.isEmpty)
@ -306,7 +306,20 @@ object Resolution {
case None => config
}
helper(Set(config0), Set.empty)
(config0, helper(Set(config0), Set.empty))
}
private val mavenScopes = {
val base = Map[String, Set[String]](
"compile" -> Set("compile"),
"provided" -> Set(),
"runtime" -> Set("compile", "runtime"),
"test" -> Set()
)
base ++ Seq(
"default" -> base("runtime")
)
}
/**
@ -347,7 +360,12 @@ object Resolution {
val properties = propertiesMap(properties0)
val configurations = withParentConfigurations(from.configuration, project.configurations)
val (actualConfig, configurations) = withParentConfigurations(from.configuration, project.configurations)
// Vague attempt at making the Maven scope model fit into the Ivy configuration one
val config = if (actualConfig.isEmpty) defaultConfiguration else actualConfig
val keepOpt = mavenScopes.get(config)
withExclusions(
depsWithDependencyManagement(
@ -359,20 +377,36 @@ object Resolution {
),
from.exclusions
)
.map{
case (config, dep) =>
(if (config.isEmpty) defaultConfiguration else config) -> {
if (dep.configuration.isEmpty)
dep.copy(configuration = defaultConfiguration)
.flatMap {
case (config0, dep0) =>
// Dependencies from Maven verify
// dep.configuration.isEmpty
// and expect dep.configuration to be filled here
val dep =
if (from.optional)
dep0.copy(optional = true)
else
dep
}
}
.collect{case (config, dep) if configurations(config) =>
if (from.optional)
dep.copy(optional = true)
else
dep
dep0
val config = if (config0.isEmpty) defaultConfiguration else config0
def default =
if (configurations(config))
Seq(dep)
else
Nil
if (dep.configuration.nonEmpty)
default
else
keepOpt.fold(default) { keep =>
if (keep(config))
// really keeping the from.configuration, with its fallback config part
Seq(dep.copy(configuration = from.configuration))
else
Nil
}
}
}

View File

@ -12,18 +12,18 @@ object IvyLocalTests extends TestSuite {
val tests = TestSuite{
'coursier{
val module = Module("com.github.alexarchambault", "coursier_2.11")
val version = "1.0.0-M5"
val version = coursier.util.Properties.version
val extraRepo = Some(Cache.ivy2Local)
// Assume this module (and the sub-projects it depends on) is published locally
CentralTests.resolutionCheck(
// Assuming this module (and the sub-projects it depends on) is published locally
* - CentralTests.resolutionCheck(
module, version,
extraRepo
)
async {
* - async {
val res = await(CentralTests.resolve(
Set(Dependency(module, version)),
extraRepo = extraRepo

View File

@ -7,7 +7,7 @@ import utest._
object IvyTests extends TestSuite {
// only tested on the JVM for lack of support of XML attributes in our XML wrappers
// only tested on the JVM for lack of support of XML attributes in the platform-dependent XML stubs
val tests = TestSuite {
'dropInfoAttributes - {
@ -23,7 +23,8 @@ object IvyTests extends TestSuite {
"[revision]/[type]s/[artifact](-[classifier]).[ext]",
dropInfoAttributes = true
)
)
),
configuration = "default(compile)"
)
}
}

View File

@ -0,0 +1 @@
com.android.tools:sdklib:24.5.0:compile

View File

@ -0,0 +1,15 @@
com.android.tools:annotations:24.5.0:runtime
com.android.tools:common:24.5.0:runtime
com.android.tools:dvlib:24.5.0:runtime
com.android.tools:sdklib:24.5.0:runtime
com.android.tools.layoutlib:layoutlib-api:24.5.0:runtime
com.google.code.gson:gson:2.2.4:runtime
com.google.guava:guava:17.0:runtime
com.intellij:annotations:12.0:runtime
commons-codec:commons-codec:1.4:runtime
commons-logging:commons-logging:1.1.1:runtime
net.sf.kxml:kxml2:2.3.0:runtime
org.apache.commons:commons-compress:1.8.1:runtime
org.apache.httpcomponents:httpclient:4.1.1:runtime
org.apache.httpcomponents:httpcore:4.1:runtime
org.apache.httpcomponents:httpmime:4.1:runtime

View File

@ -1,5 +0,0 @@
com.github.alexarchambault:coursier_2.11:1.0.0-M5:compile
org.scala-lang.modules:scala-parser-combinators_2.11:1.0.4:compile
org.scala-lang.modules:scala-xml_2.11:1.0.4:compile
org.scala-lang:scala-library:2.11.7:compile
org.scalaz:scalaz-core_2.11:7.1.2:compile

View File

@ -0,0 +1,5 @@
com.github.alexarchambault:coursier_2.11:1.0.0-SNAPSHOT:compile
org.scala-lang:scala-library:2.11.7:default
org.scala-lang.modules:scala-parser-combinators_2.11:1.0.4:default
org.scala-lang.modules:scala-xml_2.11:1.0.4:default
org.scalaz:scalaz-core_2.11:7.1.2:default

View File

@ -1,5 +0,0 @@
com.github.fommil:java-logging:1.2-SNAPSHOT:runtime
org.slf4j:jcl-over-slf4j:1.7.5:compile
org.slf4j:log4j-over-slf4j:1.7.5:compile
org.slf4j:slf4j-api:1.7.5:compile
org.slf4j:slf4j-jdk14:1.7.5:compile

View File

@ -0,0 +1,5 @@
com.github.fommil:java-logging:1.2-SNAPSHOT:runtime
org.slf4j:jcl-over-slf4j:1.7.5:runtime
org.slf4j:log4j-over-slf4j:1.7.5:runtime
org.slf4j:slf4j-api:1.7.5:runtime
org.slf4j:slf4j-jdk14:1.7.5:runtime

View File

@ -1,18 +0,0 @@
args4j:args4j:2.0.16:compile
com.google.code.findbugs:jsr305:1.3.9:compile
com.google.guava:guava:14.0.1:compile
com.google.javascript:closure-compiler:v20130603:compile
com.google.protobuf:protobuf-java:2.4.1:compile
com.googlecode.json-simple:json-simple:1.1.1:compile
io.apigee:rhino:1.7R5pre4:compile
junit:junit:4.10:compile
org.hamcrest:hamcrest-core:1.1:compile
org.json:json:20090211:compile
org.scala-js:sbt-scalajs;sbtVersion=0.13;scalaVersion=2.10:0.6.6:compile
org.scala-js:scalajs-ir_2.10:0.6.6:compile
org.scala-js:scalajs-js-envs_2.10:0.6.6:compile
org.scala-js:scalajs-sbt-test-adapter_2.10:0.6.6:compile
org.scala-js:scalajs-tools_2.10:0.6.6:compile
org.scala-lang:scala-library:2.10.6:compile
org.scala-sbt:test-interface:1.0:compile
org.webjars:envjs:1.2:compile

View File

@ -0,0 +1,18 @@
args4j:args4j:2.0.16:default
com.google.code.findbugs:jsr305:1.3.9:default
com.google.guava:guava:14.0.1:default
com.google.javascript:closure-compiler:v20130603:default
com.google.protobuf:protobuf-java:2.4.1:default
com.googlecode.json-simple:json-simple:1.1.1:default
io.apigee:rhino:1.7R5pre4:default
junit:junit:4.10:default
org.hamcrest:hamcrest-core:1.1:default
org.json:json:20090211:default
org.scala-js:sbt-scalajs;sbtVersion=0.13;scalaVersion=2.10:0.6.6:compile
org.scala-js:scalajs-ir_2.10:0.6.6:default
org.scala-js:scalajs-js-envs_2.10:0.6.6:default
org.scala-js:scalajs-sbt-test-adapter_2.10:0.6.6:default
org.scala-js:scalajs-tools_2.10:0.6.6:default
org.scala-lang:scala-library:2.10.6:default
org.scala-sbt:test-interface:1.0:default
org.webjars:envjs:1.2:default

View File

@ -45,16 +45,27 @@ object CentralTests extends TestSuite {
val expected =
await(
textResource(s"resolutions/${module.organization}/${module.name}$attrPathPart/$version")
)
.split('\n')
.toSeq
textResource(
Seq(
"resolutions",
module.organization,
module.name,
attrPathPart,
version + (
if (configuration.isEmpty)
""
else
"_" + configuration.replace('(', '_').replace(')', '_')
)
).filter(_.nonEmpty).mkString("/")
)
).split('\n').toSeq
val dep = Dependency(module, version, configuration = configuration)
val res = await(resolve(Set(dep), extraRepo = extraRepo))
val result = res
.dependencies
.minDependencies
.toVector
.map { dep =>
val projOpt = res.projectCache
@ -63,7 +74,7 @@ object CentralTests extends TestSuite {
val dep0 = dep.copy(
version = projOpt.fold(dep.version)(_.version)
)
(dep0.module.organization, dep0.module.name, dep0.version, dep0.configuration)
(dep0.module.organization, dep0.module.nameWithAttributes, dep0.version, dep0.configuration)
}
.sorted
.distinct
@ -190,6 +201,16 @@ object CentralTests extends TestSuite {
"7.0.+"
)
}
'mavenScopes - {
def check(config: String) = resolutionCheck(
Module("com.android.tools", "sdklib"),
"24.5.0",
configuration = config
)
'compile - check("compile")
'runtime - check("runtime")
}
'packaging - {
* - {