diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala
index 66cf5169b..f45c3bc4a 100644
--- a/core/shared/src/main/scala/coursier/core/Resolution.scala
+++ b/core/shared/src/main/scala/coursier/core/Resolution.scala
@@ -258,7 +258,7 @@ object Resolution {
if (mgmtDep.optional)
dep = dep.copy(optional = mgmtDep.optional)
}
-
+
(config, dep)
}
}
@@ -448,12 +448,16 @@ object Resolution {
activation.properties.nonEmpty &&
activation.properties.forall {
case (name, valueOpt) =>
- props.get(name).exists { v =>
- valueOpt.forall { reqValue =>
- if (reqValue.startsWith("!"))
- v != reqValue.drop(1)
- else
- v == reqValue
+ if (name.startsWith("!")) {
+ props.get(name.drop(1)).isEmpty
+ } else {
+ props.get(name).exists { v =>
+ valueOpt.forall { reqValue =>
+ if (reqValue.startsWith("!"))
+ v != reqValue.drop(1)
+ else
+ v == reqValue
+ }
}
}
}
diff --git a/tests/shared/src/test/scala/coursier/test/PomParsingTests.scala b/tests/shared/src/test/scala/coursier/test/PomParsingTests.scala
index 290c968cb..f4193b86b 100644
--- a/tests/shared/src/test/scala/coursier/test/PomParsingTests.scala
+++ b/tests/shared/src/test/scala/coursier/test/PomParsingTests.scala
@@ -77,6 +77,41 @@ object PomParsingTests extends TestSuite {
assert(result == expected)
}
+ 'readProfileActiveByPropertyWithoutValue{
+ val profileNode ="""
+
+ profile1
+
+
+ hadoop.profile
+
+
+
+ """
+ val expected = \/-(Profile("profile1", None, Profile.Activation(List("hadoop.profile" -> None)), Nil, Nil, Map.empty))
+ val result = Pom.profile(xmlParse(profileNode).right.get)
+
+ assert(result == expected)
+ }
+
+ 'readProfileActiveByPropertyWithValue{
+ val profileNode ="""
+
+ profile1
+
+
+ hadoop.profile
+ yes
+
+
+
+ """
+ val expected = \/-(Profile("profile1", None, Profile.Activation(List("hadoop.profile" -> Some("yes"))), Nil, Nil, Map.empty))
+ val result = Pom.profile(xmlParse(profileNode).right.get)
+
+ assert(result == expected)
+ }
+
'readProfileDependencies{
val profileNode ="""
diff --git a/tests/shared/src/test/scala/coursier/test/ResolutionTests.scala b/tests/shared/src/test/scala/coursier/test/ResolutionTests.scala
index 87a2dc1e0..7ed092605 100644
--- a/tests/shared/src/test/scala/coursier/test/ResolutionTests.scala
+++ b/tests/shared/src/test/scala/coursier/test/ResolutionTests.scala
@@ -26,12 +26,12 @@ object ResolutionTests extends TestSuite {
val projects = Seq(
Project(Module("acme", "config"), "1.3.0"),
-
+
Project(Module("acme", "play"), "2.4.0", Seq(
"" -> Dependency(Module("acme", "play-json"), "2.4.0"))),
-
+
Project(Module("acme", "play-json"), "2.4.0"),
-
+
Project(Module("acme", "play"), "2.4.1",
dependencies = Seq(
"" -> Dependency(Module("acme", "play-json"), "${play_json_version}"),
@@ -39,7 +39,7 @@ object ResolutionTests extends TestSuite {
properties = Seq(
"play_json_version" -> "2.4.0",
"WithSpecialChar©" -> "config")),
-
+
Project(Module("acme", "play-extra-no-config"), "2.4.1",
Seq(
"" -> Dependency(Module("acme", "play"), "2.4.1",
@@ -135,6 +135,36 @@ object ResolutionTests extends TestSuite {
Profile("default", activation = Profile.Activation(properties = Seq("special" -> Some("!false"))), dependencies = Seq(
"" -> Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
+ Project(Module("com.github.dummy", "libb"), "0.5.7",
+ // This project demonstrates a build profile that activates only when
+ // the property "special" is unset. Because "special" is set to "true"
+ // here, the build profile should not be active and "librairie-standard"
+ // should not be provided as a transitive dependency when resolved.
+ //
+ // We additionally include the property "!special" -> "true" to
+ // disambiguate the absence of the "special" property versus
+ // the presence of the "!special" property (which is probably not valid pom
+ // anyways)
+ properties = Seq("special" -> "true", "!special" -> "true"),
+ profiles = Seq(
+ Profile("default", activation = Profile.Activation(properties = Seq("!special" -> None)), dependencies = Seq(
+ "" -> Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
+
+ Project(Module("com.github.dummy", "libb"), "0.5.8",
+ // This project demonstrates a build profile that activates only when
+ // the property "special" is unset. Because that is the case here,
+ // the "default" build profile should be active and "librairie-standard"
+ // should be provided as a transitive dependency when resolved.
+ //
+ // We additionally include the property "!special" -> "true" to
+ // disambiguate the absence of the "special" property versus
+ // the presence of the "!special" property (which is probably not valid pom
+ // anyways)
+ properties = Seq("!special" -> "true"),
+ profiles = Seq(
+ Profile("default", activation = Profile.Activation(properties = Seq("!special" -> None)), dependencies = Seq(
+ "" -> Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
+
Project(Module("an-org", "a-name"), "1.0"),
Project(Module("an-org", "a-name"), "1.2"),
@@ -398,7 +428,7 @@ object ResolutionTests extends TestSuite {
}
'depsFromPropertyActivatedProfile{
val f =
- for (version <- Seq("0.5.3", "0.5.4", "0.5.5", "0.5.6")) yield {
+ for (version <- Seq("0.5.3", "0.5.4", "0.5.5", "0.5.6", "0.5.8")) yield {
async {
val dep = Dependency(Module("com.github.dummy", "libb"), version)
val trDeps = Seq(
@@ -418,6 +448,30 @@ object ResolutionTests extends TestSuite {
scala.concurrent.Future.sequence(f)
}
+ 'depsFromProfileDisactivatedByPropertyAbsence{
+ // A build profile only activates in the absence of some property should
+ // not be activated when that property is present.
+ // ---
+ // The target dependency in this test (com.github.dummy % libb % 0.5.7)
+ // declares a profile that is only active when name=!special,
+ // and names a transitive dependency (librairie-standard) that is only
+ // active under that build profile. When we resolve a module with
+ // the "special" attribute set to "true", the transitive dependency
+ // should not appear.
+ async {
+ val dep = Dependency(Module("com.github.dummy", "libb"), "0.5.7")
+ val res = await(resolve0(
+ Set(dep)
+ )).clearCaches
+
+ val expected = Resolution(
+ rootDependencies = Set(dep),
+ dependencies = Set(dep.withCompileScope)
+ )
+
+ assert(res == expected)
+ }
+ }
'depsScopeOverrideFromProfile{
async {
// Like com.google.inject:guice:3.0 with org.sonatype.sisu.inject:cglib