diff --git a/plugin/src/main/scala/coursier/CoursierPlugin.scala b/plugin/src/main/scala/coursier/CoursierPlugin.scala
index cd9e4ebc3..7d617f7f4 100644
--- a/plugin/src/main/scala/coursier/CoursierPlugin.scala
+++ b/plugin/src/main/scala/coursier/CoursierPlugin.scala
@@ -23,6 +23,7 @@ object CoursierPlugin extends AutoPlugin {
val coursierCache = Keys.coursierCache
val coursierProject = Keys.coursierProject
val coursierProjects = Keys.coursierProjects
+ val coursierPublications = Keys.coursierPublications
val coursierSbtClassifiersModule = Keys.coursierSbtClassifiersModule
}
@@ -44,6 +45,7 @@ object CoursierPlugin extends AutoPlugin {
updateSbtClassifiers in Defaults.TaskGlobal <<= Tasks.updateTask(withClassifiers = true, sbtClassifiers = true),
coursierProject <<= Tasks.coursierProjectTask,
coursierProjects <<= Tasks.coursierProjectsTask,
+ coursierPublications <<= Tasks.coursierPublicationsTask,
coursierSbtClassifiersModule <<= classifiersModule in updateSbtClassifiers
)
diff --git a/plugin/src/main/scala/coursier/FromSbt.scala b/plugin/src/main/scala/coursier/FromSbt.scala
index ee4940471..0611e2ed2 100644
--- a/plugin/src/main/scala/coursier/FromSbt.scala
+++ b/plugin/src/main/scala/coursier/FromSbt.scala
@@ -10,10 +10,18 @@ object FromSbt {
moduleId: ModuleID,
scalaVersion: => String,
scalaBinaryVersion: => String
- ): String = moduleId.crossVersion match {
- case CrossVersion.Disabled => moduleId.name
- case f: CrossVersion.Full => moduleId.name + "_" + f.remapVersion(scalaVersion)
- case f: CrossVersion.Binary => moduleId.name + "_" + f.remapVersion(scalaBinaryVersion)
+ ): String =
+ sbtCrossVersionName(moduleId.name, moduleId.crossVersion, scalaVersion, scalaBinaryVersion)
+
+ def sbtCrossVersionName(
+ name: String,
+ crossVersion: CrossVersion,
+ scalaVersion: => String,
+ scalaBinaryVersion: => String
+ ): String = crossVersion match {
+ case CrossVersion.Disabled => name
+ case f: CrossVersion.Full => name + "_" + f.remapVersion(scalaVersion)
+ case f: CrossVersion.Binary => name + "_" + f.remapVersion(scalaBinaryVersion)
}
def mappings(mapping: String): Seq[(String, String)] =
diff --git a/plugin/src/main/scala/coursier/Keys.scala b/plugin/src/main/scala/coursier/Keys.scala
index 6fa28d804..3ae648fe3 100644
--- a/plugin/src/main/scala/coursier/Keys.scala
+++ b/plugin/src/main/scala/coursier/Keys.scala
@@ -1,6 +1,7 @@
package coursier
import java.io.File
+import coursier.core.Publication
import sbt.{ GetClassifiersModule, Resolver, SettingKey, TaskKey }
object Keys {
@@ -19,6 +20,7 @@ object Keys {
val coursierProject = TaskKey[(Project, Seq[(String, Seq[Artifact])])]("coursier-project", "")
val coursierProjects = TaskKey[Seq[(Project, Seq[(String, Seq[Artifact])])]]("coursier-projects", "")
+ val coursierPublications = TaskKey[Seq[(String, Publication)]]("coursier-publications", "")
val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module", "")
}
diff --git a/plugin/src/main/scala/coursier/MakeIvyXml.scala b/plugin/src/main/scala/coursier/MakeIvyXml.scala
new file mode 100644
index 000000000..405e69af4
--- /dev/null
+++ b/plugin/src/main/scala/coursier/MakeIvyXml.scala
@@ -0,0 +1,64 @@
+package coursier
+
+import scala.xml.{ Node, PrefixedAttribute }
+
+object MakeIvyXml {
+
+ def apply(project: Project): Node = {
+
+ val baseInfoAttrs = .attributes
+
+ val infoAttrs = project.module.attributes.foldLeft(baseInfoAttrs) {
+ case (acc, (k, v)) =>
+ new PrefixedAttribute("e", k, v, acc)
+ }
+
+ val licenseElems = project.info.licenses.map {
+ case (name, urlOpt) =>
+ var n =
+ for (url <- urlOpt)
+ n = n % .attributes
+ n
+ }
+
+ val infoElem = {
+
+ {licenseElems}
+ {project.info.description}
+
+ } % infoAttrs
+
+ val confElems = project.configurations.toVector.map {
+ case (name, extends0) =>
+ var n =
+ if (extends0.nonEmpty)
+ n = n % .attributes
+ n
+ }
+
+ val publicationElems = project.publications.map {
+ case (conf, pub) =>
+ var n =
+ if (pub.classifier.nonEmpty)
+ n = n % .attributes
+ n
+ }
+
+ val dependencyElems = project.dependencies.toVector.map {
+ case (conf, dep) =>
+ ${dep.configuration}"} />
+ }
+
+
+ {infoElem}
+ {confElems}
+ {publicationElems}
+ {dependencyElems}
+
+ }
+
+}
diff --git a/plugin/src/main/scala/coursier/Tasks.scala b/plugin/src/main/scala/coursier/Tasks.scala
index 1e6290565..6a079ba00 100644
--- a/plugin/src/main/scala/coursier/Tasks.scala
+++ b/plugin/src/main/scala/coursier/Tasks.scala
@@ -1,16 +1,21 @@
package coursier
import java.io.{ OutputStreamWriter, File }
+import java.nio.file.Files
import java.util.concurrent.Executors
+import coursier.core.Publication
import coursier.ivy.IvyRepository
import coursier.Keys._
import coursier.Structure._
+import org.apache.ivy.core.module.id.ModuleRevisionId
import sbt.{ UpdateReport, Classpaths, Resolver, Def }
+import sbt.Configurations.{ Compile, Test }
import sbt.Keys._
import scala.collection.mutable
+import scala.collection.JavaConverters._
import scalaz.{ \/-, -\/ }
import scalaz.concurrent.{ Task, Strategy }
@@ -76,6 +81,51 @@ object Tasks {
coursierProject.forAllProjects(state, projects).map(_.values.toVector)
}
+ def coursierPublicationsTask: Def.Initialize[sbt.Task[Seq[(String, Publication)]]] =
+ (
+ sbt.Keys.state,
+ sbt.Keys.thisProjectRef,
+ sbt.Keys.projectID,
+ sbt.Keys.scalaVersion,
+ sbt.Keys.scalaBinaryVersion
+ ).map { (state, projectRef, projId, sv, sbv) =>
+
+ val packageTasks = Seq(packageBin, packageSrc, packageDoc)
+ val configs = Seq(Compile, Test)
+
+ val sbtArtifacts =
+ for {
+ pkgTask <- packageTasks
+ config <- configs
+ } yield {
+ val publish = publishArtifact.in(projectRef).in(pkgTask).in(config).getOrElse(state, false)
+ if (publish)
+ Option(artifact.in(projectRef).in(pkgTask).in(config).getOrElse(state, null))
+ .map(config.name -> _)
+ else
+ None
+ }
+
+ sbtArtifacts.collect {
+ case Some((config, artifact)) =>
+ val name = FromSbt.sbtCrossVersionName(
+ artifact.name,
+ projId.crossVersion,
+ sv,
+ sbv
+ )
+
+ val publication = Publication(
+ name,
+ artifact.`type`,
+ artifact.extension,
+ artifact.classifier.getOrElse("")
+ )
+
+ config -> publication
+ }
+ }
+
// FIXME More things should possibly be put here too (resolvers, etc.)
private case class CacheKey(
resolution: Resolution,
@@ -112,10 +162,25 @@ object Tasks {
scalaBinaryVersion.value
)
else {
- val (p, _) = coursierProject.value
- p
+ val (proj, _) = coursierProject.value
+ val publications = coursierPublications.value
+ proj.copy(publications = publications)
}
+ val ivySbt0 = ivySbt.value
+ val ivyCacheManager = ivySbt0.withIvy(streams.value.log)(ivy =>
+ ivy.getResolutionCacheManager
+ )
+
+ val ivyModule = ModuleRevisionId.newInstance(
+ currentProject.module.organization,
+ currentProject.module.name,
+ currentProject.version,
+ currentProject.module.attributes.asJava
+ )
+ val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule)
+ val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule)
+
val projects = coursierProjects.value
val parallelDownloads = coursierParallelDownloads.value
@@ -140,6 +205,22 @@ object Tasks {
forceVersions = projects.map { case (proj, _) => proj.moduleVersion }.toMap
)
+ // required for publish to be fine, later on
+ def writeIvyFiles() = {
+ val printer = new scala.xml.PrettyPrinter(80, 2)
+
+ val b = new StringBuilder
+ b ++= """"""
+ b += '\n'
+ b ++= printer.format(MakeIvyXml(currentProject))
+ cacheIvyFile.getParentFile.mkdirs()
+ Files.write(cacheIvyFile.toPath, b.result().getBytes("UTF-8"))
+
+ // Just writing an empty file here... Are these only used?
+ cacheIvyPropertiesFile.getParentFile.mkdirs()
+ Files.write(cacheIvyPropertiesFile.toPath, "".getBytes("UTF-8"))
+ }
+
def report = {
if (verbosity >= 1) {
println("InterProjectRepository")
@@ -320,6 +401,8 @@ object Tasks {
val depsByConfig = grouped(currentProject.dependencies)
+ writeIvyFiles()
+
ToSbt.updateReport(
depsByConfig,
res,