From 8aa40d1f21d3e47ee917d45f02e35a88c47ab3ed Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Mon, 18 May 2020 19:42:37 +0200 Subject: [PATCH] Move ivy.xml generation stuff to lm-coursier So that it can be re-used from sbt --- .../src/main/scala/lmcoursier}/IvyXml.scala | 93 +---------------- .../test/scala/lmcoursier/IvyXmlTests.scala | 27 +++++ .../sbtcoursiershared/IvyXmlGeneration.scala | 99 +++++++++++++++++++ .../sbtcoursiershared/SbtCoursierShared.scala | 2 +- .../sbtcoursiershared/IvyXmlTests.scala | 30 ------ 5 files changed, 129 insertions(+), 122 deletions(-) rename modules/{sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared => lm-coursier/src/main/scala/lmcoursier}/IvyXml.scala (55%) create mode 100644 modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala create mode 100644 modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala delete mode 100644 modules/sbt-coursier-shared/src/test/scala/coursier/sbtcoursiershared/IvyXmlTests.scala diff --git a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXml.scala b/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala similarity index 55% rename from modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXml.scala rename to modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala index 9369a42fd..b55dc1d16 100644 --- a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXml.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/IvyXml.scala @@ -1,21 +1,13 @@ -package coursier.sbtcoursiershared - -import java.nio.charset.StandardCharsets.UTF_8 -import java.nio.file.Files +package lmcoursier import lmcoursier.Inputs import lmcoursier.definitions.{Configuration, Project} -import org.apache.ivy.core.module.id.ModuleRevisionId -import sbt.{Def, Setting, Task, TaskKey} -import sbt.internal.librarymanagement.IvySbt -import sbt.librarymanagement.{CrossVersion, PublishConfiguration} -import scala.collection.JavaConverters._ import scala.xml.{Node, PrefixedAttribute} object IvyXml { - private[sbtcoursiershared] def rawContent( + def apply( currentProject: Project, exclusions: Seq[(String, String)], shadedConfigOpt: Option[Configuration] @@ -34,38 +26,6 @@ object IvyXml { } // These are required for publish to be fine, later on. - private def writeFiles( - currentProject: Project, - exclusions: Seq[(String, String)], - shadedConfigOpt: Option[Configuration], - ivySbt: IvySbt, - log: sbt.util.Logger - ): Unit = { - - val ivyCacheManager = ivySbt.withIvy(log)(ivy => - ivy.getResolutionCacheManager - ) - - val ivyModule = ModuleRevisionId.newInstance( - currentProject.module.organization.value, - currentProject.module.name.value, - currentProject.version, - currentProject.module.attributes.asJava - ) - - val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule) - val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule) - - val content0 = rawContent(currentProject, exclusions, shadedConfigOpt) - cacheIvyFile.getParentFile.mkdirs() - log.info(s"Writing Ivy file $cacheIvyFile") - Files.write(cacheIvyFile.toPath, content0.getBytes(UTF_8)) - - // Just writing an empty file here... Are these only used? - cacheIvyPropertiesFile.getParentFile.mkdirs() - Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray) - } - private def content( project0: Project, exclusions: Seq[(String, String)], @@ -168,53 +128,4 @@ object IvyXml { } - private def makeIvyXmlBefore[T]( - task: TaskKey[T], - shadedConfigOpt: Option[Configuration] - ): Setting[Task[T]] = - task := task.dependsOn { - Def.taskDyn { - import SbtCoursierShared.autoImport._ - 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, shadedConfigOpt, sbt.Keys.ivySbt.value, log) - } - else - Def.task(()) - } - }.value - - private lazy val needsIvyXmlLocal = Seq(sbt.Keys.publishLocalConfiguration) ++ getPubConf("makeIvyXmlLocalConfiguration") - private lazy val needsIvyXml = Seq(sbt.Keys.publishConfiguration) ++ getPubConf("makeIvyXmlConfiguration") - - private[this] def getPubConf(method: String): List[TaskKey[PublishConfiguration]] = - try { - val cls = sbt.Keys.getClass - val m = cls.getMethod(method) - val task = m.invoke(sbt.Keys).asInstanceOf[TaskKey[PublishConfiguration]] - List(task) - } catch { - case _: Throwable => // FIXME Too wide - Nil - } - - def generateIvyXmlSettings( - shadedConfigOpt: Option[Configuration] = None - ): Seq[Setting[_]] = - (needsIvyXml ++ needsIvyXmlLocal).map(makeIvyXmlBefore(_, shadedConfigOpt)) - } diff --git a/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala b/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala new file mode 100644 index 000000000..ad0ae6818 --- /dev/null +++ b/modules/lm-coursier/src/test/scala/lmcoursier/IvyXmlTests.scala @@ -0,0 +1,27 @@ +package lmcoursier + +import lmcoursier.definitions.{Configuration, Info, Module, ModuleName, Organization, Project} +import org.scalatest.{Matchers, PropSpec} + +object IvyXmlTests extends PropSpec with Matchers { + + property("no truncation") { + val project = Project( + Module(Organization("org"), ModuleName("name"), Map()), + "ver", + Nil, + Map( + Configuration("foo") -> (1 to 80).map(n => Configuration("bar" + n)) // long list of configurations -> no truncation any way + ), + Nil, + None, + Nil, + Info("", "", Nil, Nil, None) + ) + + val content = IvyXml(project, Nil, None) + + 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 new file mode 100644 index 000000000..35c681662 --- /dev/null +++ b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/IvyXmlGeneration.scala @@ -0,0 +1,99 @@ +package coursier.sbtcoursiershared + +import java.nio.charset.StandardCharsets.UTF_8 +import java.nio.file.Files + +import lmcoursier.{Inputs, IvyXml} +import lmcoursier.definitions.{Configuration, Project} +import org.apache.ivy.core.module.id.ModuleRevisionId +import sbt.{Def, Setting, Task, TaskKey} +import sbt.internal.librarymanagement.IvySbt +import sbt.librarymanagement.{CrossVersion, PublishConfiguration} + +import scala.collection.JavaConverters._ + +object IvyXmlGeneration { + + // These are required for publish to be fine, later on. + private def writeFiles( + currentProject: Project, + exclusions: Seq[(String, String)], + shadedConfigOpt: Option[Configuration], + ivySbt: IvySbt, + log: sbt.util.Logger + ): Unit = { + + val ivyCacheManager = ivySbt.withIvy(log)(ivy => + ivy.getResolutionCacheManager + ) + + val ivyModule = ModuleRevisionId.newInstance( + currentProject.module.organization.value, + currentProject.module.name.value, + currentProject.version, + currentProject.module.attributes.asJava + ) + + val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule) + val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule) + + val content0 = IvyXml(currentProject, exclusions, shadedConfigOpt) + cacheIvyFile.getParentFile.mkdirs() + log.info(s"Writing Ivy file $cacheIvyFile") + Files.write(cacheIvyFile.toPath, content0.getBytes(UTF_8)) + + // Just writing an empty file here... Are these only used? + cacheIvyPropertiesFile.getParentFile.mkdirs() + Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray) + } + + private def makeIvyXmlBefore[T]( + task: TaskKey[T], + shadedConfigOpt: Option[Configuration] + ): Setting[Task[T]] = + task := task.dependsOn { + Def.taskDyn { + import SbtCoursierShared.autoImport._ + 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, shadedConfigOpt, sbt.Keys.ivySbt.value, log) + } + else + Def.task(()) + } + }.value + + private lazy val needsIvyXmlLocal = Seq(sbt.Keys.publishLocalConfiguration) ++ getPubConf("makeIvyXmlLocalConfiguration") + private lazy val needsIvyXml = Seq(sbt.Keys.publishConfiguration) ++ getPubConf("makeIvyXmlConfiguration") + + private[this] def getPubConf(method: String): List[TaskKey[PublishConfiguration]] = + try { + val cls = sbt.Keys.getClass + val m = cls.getMethod(method) + val task = m.invoke(sbt.Keys).asInstanceOf[TaskKey[PublishConfiguration]] + List(task) + } catch { + case _: Throwable => // FIXME Too wide + Nil + } + + def generateIvyXmlSettings( + shadedConfigOpt: Option[Configuration] = None + ): Seq[Setting[_]] = + (needsIvyXml ++ needsIvyXmlLocal).map(makeIvyXmlBefore(_, shadedConfigOpt)) + +} 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 1f896c1b5..174042d62 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 @@ -174,7 +174,7 @@ object SbtCoursierShared extends AutoPlugin { versionReconciliation := Seq.empty ) ++ { if (pubSettings) - IvyXml.generateIvyXmlSettings() + IvyXmlGeneration.generateIvyXmlSettings() else Nil } diff --git a/modules/sbt-coursier-shared/src/test/scala/coursier/sbtcoursiershared/IvyXmlTests.scala b/modules/sbt-coursier-shared/src/test/scala/coursier/sbtcoursiershared/IvyXmlTests.scala deleted file mode 100644 index 3085d849a..000000000 --- a/modules/sbt-coursier-shared/src/test/scala/coursier/sbtcoursiershared/IvyXmlTests.scala +++ /dev/null @@ -1,30 +0,0 @@ -package coursier.sbtcoursiershared - -import lmcoursier.definitions.{Configuration, Info, Module, ModuleName, Organization, Project} -import utest._ - -object IvyXmlTests extends TestSuite { - - val tests = Tests { - "no truncation" - { - - val project = Project( - Module(Organization("org"), ModuleName("name"), Map()), - "ver", - Nil, - Map( - Configuration("foo") -> (1 to 80).map(n => Configuration("bar" + n)) // long list of configurations -> no truncation any way - ), - Nil, - None, - Nil, - Info("", "", Nil, Nil, None) - ) - - val content = IvyXml.rawContent(project, Nil, None) - - assert(!content.contains("")) - } - } - -}