diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala b/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala index e9ac86ffe..bfdbe5439 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala @@ -6,9 +6,17 @@ import scala.xml.{Node, PrefixedAttribute} object IvyXml { + @deprecated("Use the override accepting 3 arguments", "2.0.0-RC6-6") def apply( currentProject: Project, exclusions: Seq[(String, String)] + ): String = + apply(currentProject, exclusions, Nil) + + def apply( + currentProject: Project, + exclusions: Seq[(String, String)], + overrides: Seq[(String, String, String)] ): String = { // Important: width = Int.MaxValue, so that no tag gets truncated. @@ -20,13 +28,14 @@ object IvyXml { val printer = new scala.xml.PrettyPrinter(Int.MaxValue, 2) """""" + '\n' + - printer.format(content(currentProject, exclusions)) + printer.format(content(currentProject, exclusions, overrides)) } // These are required for publish to be fine, later on. private def content( project: Project, - exclusions: Seq[(String, String)] + exclusions: Seq[(String, String)], + overrides: Seq[(String, String, String)] ): Node = { val props = project.module.attributes.toSeq ++ project.properties @@ -103,11 +112,16 @@ object IvyXml { } + val overrideElems = overrides.toVector.map { + case (org, name, ver) => + + } + {infoElem} {confElems} {publicationElems} - {dependencyElems}{excludeElems} + {dependencyElems}{excludeElems}{overrideElems} } diff --git a/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala b/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala index 3ba8c49e2..131b3eba8 100644 --- a/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala +++ b/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala @@ -20,7 +20,7 @@ object IvyXmlTests extends AnyPropSpec with Matchers { Info("", "", Nil, Nil, None) ) - val content = IvyXml(project, Nil) + val content = IvyXml(project, Nil, Nil) assert(!content.contains("")) } diff --git a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala index bd8a295ba..1714fe64b 100644 --- a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala +++ b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala @@ -1,5 +1,6 @@ package coursier.sbtcoursiershared +import java.io.File import java.nio.charset.StandardCharsets.UTF_8 import java.nio.file.Files @@ -18,9 +19,10 @@ object IvyXmlGeneration { private def writeFiles( currentProject: Project, exclusions: Seq[(String, String)], + overrides: Seq[(String, String, String)], ivySbt: IvySbt, log: sbt.util.Logger - ): Unit = { + ): File = { val ivyCacheManager = ivySbt.withIvy(log)(ivy => ivy.getResolutionCacheManager @@ -36,7 +38,7 @@ object IvyXmlGeneration { val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule) val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule) - val content0 = IvyXml(currentProject, exclusions) + val content0 = IvyXml(currentProject, exclusions, overrides) cacheIvyFile.getParentFile.mkdirs() log.info(s"Writing Ivy file $cacheIvyFile") Files.write(cacheIvyFile.toPath, content0.getBytes(UTF_8)) @@ -44,8 +46,34 @@ object IvyXmlGeneration { // Just writing an empty file here... Are these only used? cacheIvyPropertiesFile.getParentFile.mkdirs() Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray) + + cacheIvyFile } + def writeIvyXml: Def.Initialize[Task[File]] = + Def.task { + import SbtCoursierShared.autoImport._ + + val sv = sbt.Keys.scalaVersion.value + val sbv = sbt.Keys.scalaBinaryVersion.value + val log = sbt.Keys.streams.value.log + val currentProject = { + val proj = coursierProject.value + val publications = coursierPublications.value + proj.withPublications(publications) + } + val overrides = Inputs.forceVersions(sbt.Keys.dependencyOverrides.value, sv, sbv).map { + case (mod, ver) => + (mod.organization.value, mod.name.value, ver) + } + val excludeDeps = Inputs.exclusionsSeq(InputsTasks.actualExcludeDependencies.value, sv, sbv, log) + .map { + case (org, name) => + (org.value, name.value) + } + writeFiles(currentProject, excludeDeps, overrides, sbt.Keys.ivySbt.value, log) + } + private def makeIvyXmlBefore[T](task: TaskKey[T]): Setting[Task[T]] = task := task.dependsOn { Def.taskDyn { @@ -53,20 +81,8 @@ object IvyXmlGeneration { val doGen = coursierGenerateIvyXml.value if (doGen) Def.task { - val sv = sbt.Keys.scalaVersion.value - val sbv = sbt.Keys.scalaBinaryVersion.value - val log = sbt.Keys.streams.value.log - val currentProject = { - val proj = coursierProject.value - val publications = coursierPublications.value - proj.withPublications(publications) - } - val excludeDeps = Inputs.exclusionsSeq(InputsTasks.actualExcludeDependencies.value, sv, sbv, log) - .map { - case (org, name) => - (org.value, name.value) - } - writeFiles(currentProject, excludeDeps, sbt.Keys.ivySbt.value, log) + coursierWriteIvyXml.value + () } else Def.task(()) diff --git a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala index 6ed65f7f3..9156660ec 100644 --- a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala +++ b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala @@ -22,6 +22,7 @@ object SbtCoursierShared extends AutoPlugin { object autoImport { val coursierGenerateIvyXml = settingKey[Boolean]("") + val coursierWriteIvyXml = taskKey[File]("") val coursierProject = TaskKey[Project]("coursier-project") val coursierInterProjectDependencies = TaskKey[Seq[Project]]("coursier-inter-project-dependencies", "Projects the current project depends on, possibly transitively") val coursierExtraProjects = TaskKey[Seq[Project]]("coursier-extra-projects", "") @@ -85,6 +86,7 @@ object SbtCoursierShared extends AutoPlugin { SbtCoursierCache.default.clear() }, coursierGenerateIvyXml := true, + coursierWriteIvyXml := IvyXmlGeneration.writeIvyXml.value, coursierProject := InputsTasks.coursierProjectTask.value, coursierInterProjectDependencies := InputsTasks.coursierInterProjectDependenciesTask.value, coursierExtraProjects := InputsTasks.coursierExtraProjectsTask.value diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dependency-overrides/build.sbt b/modules/sbt-coursier/src/sbt-test/shared-1/dependency-overrides/build.sbt index 834048659..5740f479e 100644 --- a/modules/sbt-coursier/src/sbt-test/shared-1/dependency-overrides/build.sbt +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dependency-overrides/build.sbt @@ -1,3 +1,17 @@ scalaVersion := "2.12.8" + +organization := "io.get-coursier.test" +name := "dependency-overrides" +version := "0.1.0-SNAPSHOT" + libraryDependencies += "io.get-coursier" %% "coursier" % "2.0.0-RC2-6" dependencyOverrides += "io.get-coursier" %% "coursier-core" % "1.1.0-M14-7" + +lazy val check = taskKey[Unit]("") + +check := { + val f = coursierWriteIvyXml.value + val content = new String(java.nio.file.Files.readAllBytes(f.toPath), "UTF-8") + System.err.println(s"ivy.xml:\n'$content'") + assert(content.contains(" run +> check