From f4dc1044e310212f100802dbd25f5ce53f8fc233 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:32:57 +0200 Subject: [PATCH 1/6] Add non regression test --- .../src/main/scala/coursier/core/Resolution.scala | 2 -- .../org.glassfish.jersey.core/jersey-client/2.19 | 13 +++++++++++++ .../src/test/scala/coursier/test/CentralTests.scala | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/shared/src/test/resources/resolutions/org.glassfish.jersey.core/jersey-client/2.19 diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index a8a031d50..c65d06acf 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -820,8 +820,6 @@ final case class Resolution( */ // A bit fragile, but seems to work - // TODO Add non regression test for the touchy org.glassfish.jersey.core:jersey-client:2.19 - // (for the way it uses org.glassfish.hk2:hk2-bom,2.4.0-b25) val approxProperties0 = project.parent diff --git a/tests/shared/src/test/resources/resolutions/org.glassfish.jersey.core/jersey-client/2.19 b/tests/shared/src/test/resources/resolutions/org.glassfish.jersey.core/jersey-client/2.19 new file mode 100644 index 000000000..1e76f8ad5 --- /dev/null +++ b/tests/shared/src/test/resources/resolutions/org.glassfish.jersey.core/jersey-client/2.19 @@ -0,0 +1,13 @@ +javax.annotation:javax.annotation-api:1.2:compile +javax.inject:javax.inject:1:compile +javax.ws.rs:javax.ws.rs-api:2.0.1:compile +org.glassfish.hk2:hk2-api:2.4.0-b25:compile +org.glassfish.hk2:hk2-locator:2.4.0-b25:compile +org.glassfish.hk2:hk2-utils:2.4.0-b25:compile +org.glassfish.hk2:osgi-resource-locator:1.0.1:compile +org.glassfish.hk2.external:aopalliance-repackaged:2.4.0-b25:compile +org.glassfish.hk2.external:javax.inject:2.4.0-b25:compile +org.glassfish.jersey.bundles.repackaged:jersey-guava:2.19:compile +org.glassfish.jersey.core:jersey-client:2.19:compile +org.glassfish.jersey.core:jersey-common:2.19:compile +org.javassist:javassist:3.18.1-GA:compile diff --git a/tests/shared/src/test/scala/coursier/test/CentralTests.scala b/tests/shared/src/test/scala/coursier/test/CentralTests.scala index 2edc9a7bd..5734dbd47 100644 --- a/tests/shared/src/test/scala/coursier/test/CentralTests.scala +++ b/tests/shared/src/test/scala/coursier/test/CentralTests.scala @@ -207,6 +207,13 @@ object CentralTests extends TestSuite { ) } + 'projectProperties - { + resolutionCheck( + Module("org.glassfish.jersey.core", "jersey-client"), + "2.19" + ) + } + 'parentDependencyManagementProperties - { resolutionCheck( Module("com.nativelibs4java", "jnaerator-runtime"), From efb4f6c5c0893030d4855e6003943c9611cd7e4c Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:33:01 +0200 Subject: [PATCH 2/6] Allow to specify Maven profiles via the CLI app --- cli/src/main/scala-2.11/coursier/cli/Helper.scala | 4 +++- cli/src/main/scala-2.11/coursier/cli/Options.scala | 4 ++++ core/shared/src/main/scala/coursier/core/Resolution.scala | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cli/src/main/scala-2.11/coursier/cli/Helper.scala b/cli/src/main/scala-2.11/coursier/cli/Helper.scala index fdd230cbe..571885178 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Helper.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Helper.scala @@ -273,11 +273,13 @@ class Helper( } } + val userEnabledProfiles = profile.toSet val startRes = Resolution( dependencies.toSet, forceVersions = forceVersions, - filter = Some(dep => keepOptional || !dep.optional) + filter = Some(dep => keepOptional || !dep.optional), + profileActivation = Some(core.Resolution.userProfileActivation(userEnabledProfiles)) ) val loggerFallbackMode = diff --git a/cli/src/main/scala-2.11/coursier/cli/Options.scala b/cli/src/main/scala-2.11/coursier/cli/Options.scala index 5439722a2..4fa545714 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Options.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Options.scala @@ -74,6 +74,10 @@ case class CommonOptions( @Help("Print dependencies as an inversed tree (dependees as children)") @Short("T") reverseTree: Boolean, + @Help("Enable profile") + @Value("profile") + @Short("F") + profile: List[String], @Recurse cacheOptions: CacheOptions ) { diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index c65d06acf..466e273ed 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -453,6 +453,14 @@ object Resolution { } } + def userProfileActivation(userProfiles: Set[String])( + id: String, + activation: Activation, + props: Map[String, String] + ): Boolean = + userProfiles(id) || + defaultProfileActivation(id, activation, props) + /** * Default dependency filter used during resolution. * From ffd58b51b0b156a93c1707c5402758070900442d Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:33:04 +0200 Subject: [PATCH 3/6] Minor refacto --- .../main/scala/coursier/core/Resolution.scala | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index 466e273ed..9fd62c762 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -434,24 +434,18 @@ object Resolution { activation: Activation, props: Map[String, String] ): Boolean = - if (activation.properties.isEmpty) - false - else - activation - .properties - .forall {case (name, valueOpt) => - props - .get(name) - .exists{ v => - valueOpt - .forall { reqValue => - if (reqValue.startsWith("!")) - v != reqValue.drop(1) - else - v == reqValue - } + 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 } - } + } + } def userProfileActivation(userProfiles: Set[String])( id: String, From 5146be5c398e9af0ee48fd21c673530d72d150ab Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:34:09 +0200 Subject: [PATCH 4/6] Major / important fix in dependency management handling Version and scope from dependency management now override the ones from the dependencies no matter what. For spark 1.3 (a bit old now, but unit tested in CentralTests), this makes spark-core depend on hadoop 1.x by default (because of dependency management), instead of hadoop 2.2 whose versions appear in the dependency sections of it (but are now overridden by those in dependency management). Enabling the hadoop-2.2 profile reestablishes the former hadoop 2.2 versions. This commit breaks the spark related test in CentralTests, repaired by the next two commits. --- .../src/main/scala/coursier/core/Resolution.scala | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index 9fd62c762..2cbdd4850 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -239,13 +239,23 @@ object Resolution { var dep = dep0 for ((mgmtConfig, mgmtDep) <- dict.get(DepMgmt.key(dep0))) { - if (dep.version.isEmpty) + + if (mgmtDep.version.nonEmpty) dep = dep.copy(version = mgmtDep.version) - if (config.isEmpty) + + if (mgmtConfig.nonEmpty) config = mgmtConfig + // FIXME The version and scope/config from dependency management, if any, are substituted + // no matter what. The same is not done for the exclusions and optionality, for a lack of + // way of distinguishing empty exclusions from no exclusion section and optional set to + // false from no optional section in the dependency management for now. + if (dep.exclusions.isEmpty) dep = dep.copy(exclusions = mgmtDep.exclusions) + + if (mgmtDep.optional) + dep = dep.copy(optional = mgmtDep.optional) } (config, dep) From 3a6cdb20fb52827103b6fb84dcf3ccb31b30596a Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:34:12 +0200 Subject: [PATCH 5/6] Better handling of properties in dependency management / profiles Test fix in the next commit prevents regressions --- .../main/scala/coursier/core/Resolution.scala | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index 2cbdd4850..5241a3335 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -851,17 +851,27 @@ final case class Resolution( // 1.2 made from Pom.scala (TODO look at the very details?) // 1.3 & 1.4 (if only vaguely so) - val dependencies0 = addDependencies( - (project.dependencies +: profiles0.map(_.dependencies)).map(withProperties(_, approxProperties)) - ) - val dependenciesMgmt0 = addDependencies( - (project.dependencyManagement +: profiles0.map(_.dependencyManagement)).map(withProperties(_, approxProperties)) - ) val properties0 = (project.properties /: profiles0) { (acc, p) => acc ++ p.properties } + val project0 = project.copy( + properties = project.parent // belongs to 1.5 & 1.6 + .filter(projectCache.contains) + .map(projectCache(_)._2.properties) + .fold(properties0)(_ ++ properties0) + ) + + val propertiesMap0 = propertiesMap(projectProperties(project0)) + + val dependencies0 = addDependencies( + (project0.dependencies +: profiles0.map(_.dependencies)).map(withProperties(_, propertiesMap0)) + ) + val dependenciesMgmt0 = addDependencies( + (project0.dependencyManagement +: profiles0.map(_.dependencyManagement)).map(withProperties(_, propertiesMap0)) + ) + val deps0 = dependencies0 .collect { case ("import", dep) => @@ -871,7 +881,7 @@ final case class Resolution( .collect { case ("import", dep) => dep.moduleVersion } ++ - project.parent // belongs to 1.5 & 1.6 + project0.parent // belongs to 1.5 & 1.6 val deps = deps0.filter(projectCache.contains) @@ -879,35 +889,31 @@ final case class Resolution( .map(projectCache(_)._2) val depMgmt = ( - project.dependencyManagement +: ( + project0.dependencyManagement +: ( profiles0.map(_.dependencyManagement) ++ projs.map(_.dependencyManagement) ) ) - .map(withProperties(_, approxProperties)) + .map(withProperties(_, propertiesMap0)) .foldLeft(Map.empty[DepMgmt.Key, (String, Dependency)])(DepMgmt.addSeq) val depsSet = deps.toSet - project.copy( - version = substituteProps(project.version, approxProperties), + project0.copy( + version = substituteProps(project0.version, propertiesMap0), dependencies = dependencies0 .filterNot{case (config, dep) => config == "import" && depsSet(dep.moduleVersion) } ++ - project.parent // belongs to 1.5 & 1.6 + project0.parent // belongs to 1.5 & 1.6 .filter(projectCache.contains) .toSeq .flatMap(projectCache(_)._2.dependencies), dependencyManagement = depMgmt.values.toSeq .filterNot{case (config, dep) => config == "import" && depsSet(dep.moduleVersion) - }, - properties = project.parent // belongs to 1.5 & 1.6 - .filter(projectCache.contains) - .map(projectCache(_)._2.properties) - .fold(properties0)(properties0 ++ _) + } ) } From d0e11c91532a48f39e4054fc8d6aead5ef5f5249 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 3 Jul 2016 16:34:18 +0200 Subject: [PATCH 6/6] Fix tests after recent changes / fixes in dependency management / profiles handling --- .../scala/coursier/test/CentralTests.scala | 25 +++++++++++++------ .../test/scala/coursier/test/package.scala | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/tests/shared/src/test/scala/coursier/test/CentralTests.scala b/tests/shared/src/test/scala/coursier/test/CentralTests.scala index 5734dbd47..bc1fef336 100644 --- a/tests/shared/src/test/scala/coursier/test/CentralTests.scala +++ b/tests/shared/src/test/scala/coursier/test/CentralTests.scala @@ -18,11 +18,18 @@ object CentralTests extends TestSuite { def resolve( deps: Set[Dependency], filter: Option[Dependency => Boolean] = None, - extraRepo: Option[Repository] = None + extraRepo: Option[Repository] = None, + profiles: Set[String] = Set.empty ) = { val repositories0 = extraRepo.toSeq ++ repositories - Resolution(deps, filter = filter) + Resolution( + deps, + filter = filter, + profileActivation = Some( + core.Resolution.userProfileActivation(profiles) + ) + ) .process .run(repositories0) .runF @@ -32,7 +39,8 @@ object CentralTests extends TestSuite { module: Module, version: String, extraRepo: Option[Repository] = None, - configuration: String = "" + configuration: String = "", + profiles: Set[String] = Set.empty ) = async { val attrPathPart = @@ -62,7 +70,7 @@ object CentralTests extends TestSuite { ).split('\n').toSeq val dep = Dependency(module, version, configuration = configuration) - val res = await(resolve(Set(dep), extraRepo = extraRepo)) + val res = await(resolve(Set(dep), extraRepo = extraRepo, profiles = profiles)) val result = res .minDependencies @@ -120,7 +128,7 @@ object CentralTests extends TestSuite { 'logback - { async { val dep = Dependency(Module("ch.qos.logback", "logback-classic"), "1.1.3") - val res = await(resolve(Set(dep))).clearCaches + val res = await(resolve(Set(dep))).clearCaches.clearProfileActivation val expected = Resolution( rootDependencies = Set(dep), @@ -136,7 +144,7 @@ object CentralTests extends TestSuite { 'asm - { async { val dep = Dependency(Module("org.ow2.asm", "asm-commons"), "5.0.2") - val res = await(resolve(Set(dep))).clearCaches + val res = await(resolve(Set(dep))).clearCaches.clearProfileActivation val expected = Resolution( rootDependencies = Set(dep), @@ -153,7 +161,7 @@ object CentralTests extends TestSuite { async { val dep = Dependency(Module("joda-time", "joda-time"), "[2.2,2.8]") val res0 = await(resolve(Set(dep))) - val res = res0.clearCaches + val res = res0.clearCaches.clearProfileActivation val expected = Resolution( rootDependencies = Set(dep), @@ -171,7 +179,8 @@ object CentralTests extends TestSuite { 'spark - { resolutionCheck( Module("org.apache.spark", "spark-core_2.11"), - "1.3.1" + "1.3.1", + profiles = Set("hadoop-2.2") ) } diff --git a/tests/shared/src/test/scala/coursier/test/package.scala b/tests/shared/src/test/scala/coursier/test/package.scala index e3dc40cfa..7a2266b6d 100644 --- a/tests/shared/src/test/scala/coursier/test/package.scala +++ b/tests/shared/src/test/scala/coursier/test/package.scala @@ -23,6 +23,8 @@ package object test { ) def clearFilter: Resolution = underlying.copy(filter = None) + def clearProfileActivation: Resolution = + underlying.copy(profileActivation = None) } object Profile {