mirror of https://github.com/sbt/sbt.git
Move ivy.xml generation stuff to lm-coursier
So that it can be re-used from sbt
This commit is contained in:
parent
6cebc8fe7a
commit
8aa40d1f21
|
|
@ -1,21 +1,13 @@
|
||||||
package coursier.sbtcoursiershared
|
package lmcoursier
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets.UTF_8
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
import lmcoursier.Inputs
|
import lmcoursier.Inputs
|
||||||
import lmcoursier.definitions.{Configuration, Project}
|
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}
|
import scala.xml.{Node, PrefixedAttribute}
|
||||||
|
|
||||||
object IvyXml {
|
object IvyXml {
|
||||||
|
|
||||||
private[sbtcoursiershared] def rawContent(
|
def apply(
|
||||||
currentProject: Project,
|
currentProject: Project,
|
||||||
exclusions: Seq[(String, String)],
|
exclusions: Seq[(String, String)],
|
||||||
shadedConfigOpt: Option[Configuration]
|
shadedConfigOpt: Option[Configuration]
|
||||||
|
|
@ -34,38 +26,6 @@ object IvyXml {
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are required for publish to be fine, later on.
|
// 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(
|
private def content(
|
||||||
project0: Project,
|
project0: Project,
|
||||||
exclusions: Seq[(String, String)],
|
exclusions: Seq[(String, String)],
|
||||||
|
|
@ -168,53 +128,4 @@ object IvyXml {
|
||||||
</ivy-module>
|
</ivy-module>
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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("</conf>"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -174,7 +174,7 @@ object SbtCoursierShared extends AutoPlugin {
|
||||||
versionReconciliation := Seq.empty
|
versionReconciliation := Seq.empty
|
||||||
) ++ {
|
) ++ {
|
||||||
if (pubSettings)
|
if (pubSettings)
|
||||||
IvyXml.generateIvyXmlSettings()
|
IvyXmlGeneration.generateIvyXmlSettings()
|
||||||
else
|
else
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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("</conf>"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue