mirror of https://github.com/sbt/sbt.git
Move thing around, add support for updateSbtClassifiers
This commit is contained in:
parent
24f8c430a4
commit
9bab2d9178
|
|
@ -12,6 +12,12 @@ import scalaz.concurrent.Task
|
|||
|
||||
object CoursierPlugin extends AutoPlugin {
|
||||
|
||||
private def grouped[K, V](map: Seq[(K, V)]): Map[K, Seq[V]] =
|
||||
map.groupBy { case (k, _) => k }.map {
|
||||
case (k, l) =>
|
||||
k -> l.map { case (_, v) => v }
|
||||
}
|
||||
|
||||
override def trigger = allRequirements
|
||||
|
||||
override def requires = sbt.plugins.IvyPlugin
|
||||
|
|
@ -28,6 +34,7 @@ object CoursierPlugin extends AutoPlugin {
|
|||
val coursierCache = Keys.coursierCache
|
||||
val coursierProject = Keys.coursierProject
|
||||
val coursierProjects = Keys.coursierProjects
|
||||
val coursierSbtClassifiersModule = Keys.coursierSbtClassifiersModule
|
||||
}
|
||||
|
||||
import autoImport._
|
||||
|
|
@ -45,13 +52,28 @@ object CoursierPlugin extends AutoPlugin {
|
|||
}
|
||||
|
||||
|
||||
private def updateTask(withClassifiers: Boolean) = Def.task {
|
||||
private def updateTask(withClassifiers: Boolean, sbtClassifiers: Boolean = false) = Def.task {
|
||||
|
||||
// let's update only one module at once, for a better output
|
||||
// Downloads are already parallel, no need to parallelize further anyway
|
||||
synchronized {
|
||||
|
||||
val (currentProject, _) = coursierProject.value
|
||||
lazy val cm = coursierSbtClassifiersModule.value
|
||||
|
||||
val currentProject =
|
||||
if (sbtClassifiers) {
|
||||
FromSbt.project(
|
||||
cm.id,
|
||||
cm.modules,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
scalaVersion.value,
|
||||
scalaBinaryVersion.value
|
||||
)
|
||||
} else {
|
||||
val (p, _) = coursierProject.value
|
||||
p
|
||||
}
|
||||
|
||||
val projects = coursierProjects.value
|
||||
|
||||
val parallelDownloads = coursierParallelDownloads.value
|
||||
|
|
@ -157,6 +179,7 @@ object CoursierPlugin extends AutoPlugin {
|
|||
}
|
||||
|
||||
val errors = res.errors
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
println(s"\n${errors.size} error(s):")
|
||||
for ((dep, errs) <- errors) {
|
||||
|
|
@ -166,7 +189,12 @@ object CoursierPlugin extends AutoPlugin {
|
|||
|
||||
val classifiers =
|
||||
if (withClassifiers)
|
||||
Some(transitiveClassifiers.value)
|
||||
Some {
|
||||
if (sbtClassifiers)
|
||||
cm.classifiers
|
||||
else
|
||||
transitiveClassifiers.value
|
||||
}
|
||||
else
|
||||
None
|
||||
|
||||
|
|
@ -176,102 +204,69 @@ object CoursierPlugin extends AutoPlugin {
|
|||
case Some(cl) => res.classifiersArtifacts(cl)
|
||||
}
|
||||
|
||||
val trDepsWithArtifactsTasks = allArtifacts
|
||||
.toVector
|
||||
.map { a =>
|
||||
files.file(a, checksums = checksums, logger = logger)(cachePolicy = cachePolicy).run.map((a, _))
|
||||
}
|
||||
val artifactFileOrErrorTasks = allArtifacts.toVector.map { a =>
|
||||
files.file(a, checksums = checksums, logger = logger)(cachePolicy = cachePolicy).run.map((a, _))
|
||||
}
|
||||
|
||||
if (verbosity >= 0)
|
||||
errPrintln(s"Fetching artifacts")
|
||||
// rename
|
||||
val trDepsWithArtifacts = Task.gatherUnordered(trDepsWithArtifactsTasks).attemptRun match {
|
||||
|
||||
val artifactFilesOrErrors = Task.gatherUnordered(artifactFileOrErrorTasks).attemptRun match {
|
||||
case -\/(ex) =>
|
||||
throw new Exception(s"Error while downloading / verifying artifacts", ex)
|
||||
case \/-(l) => l.toMap
|
||||
case \/-(l) =>
|
||||
l.toMap
|
||||
}
|
||||
|
||||
if (verbosity >= 0)
|
||||
errPrintln(s"Fetching artifacts: done")
|
||||
|
||||
val configs = ivyConfigurations.value.map(c => c.name -> c.extendsConfigs.map(_.name)).toMap
|
||||
def allExtends(c: String) = {
|
||||
// possibly bad complexity
|
||||
def helper(current: Set[String]): Set[String] = {
|
||||
val newSet = current ++ current.flatMap(configs.getOrElse(_, Nil))
|
||||
if ((newSet -- current).nonEmpty)
|
||||
helper(newSet)
|
||||
else
|
||||
newSet
|
||||
val configs = {
|
||||
val configs0 = ivyConfigurations.value.map { config =>
|
||||
config.name -> config.extendsConfigs.map(_.name)
|
||||
}.toMap
|
||||
|
||||
def allExtends(c: String) = {
|
||||
// possibly bad complexity
|
||||
def helper(current: Set[String]): Set[String] = {
|
||||
val newSet = current ++ current.flatMap(configs0.getOrElse(_, Nil))
|
||||
if ((newSet -- current).nonEmpty)
|
||||
helper(newSet)
|
||||
else
|
||||
newSet
|
||||
}
|
||||
|
||||
helper(Set(c))
|
||||
}
|
||||
|
||||
helper(Set(c))
|
||||
configs0.map {
|
||||
case (config, _) =>
|
||||
config -> allExtends(config)
|
||||
}
|
||||
}
|
||||
|
||||
val depsByConfig = currentProject
|
||||
.dependencies
|
||||
.groupBy { case (c, _) => c }
|
||||
.map { case (c, l) =>
|
||||
c -> l.map { case (_, d) => d }
|
||||
def artifactFileOpt(artifact: Artifact) = {
|
||||
val fileOrError = artifactFilesOrErrors.getOrElse(artifact, -\/("Not downloaded"))
|
||||
|
||||
fileOrError match {
|
||||
case \/-(file) =>
|
||||
if (file.toString.contains("file:/"))
|
||||
throw new Exception(s"Wrong path: $file")
|
||||
Some(file)
|
||||
case -\/(err) =>
|
||||
errPrintln(s"${artifact.url}: $err")
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
val sbtModuleReportsPerScope = configs.map { case (c, _) => c -> {
|
||||
val a = allExtends(c).flatMap(depsByConfig.getOrElse(_, Nil))
|
||||
val partialRes = res.part(a)
|
||||
val depArtifacts =
|
||||
classifiers match {
|
||||
case None => partialRes.dependencyArtifacts
|
||||
case Some(cl) => partialRes.dependencyClassifiersArtifacts(cl)
|
||||
}
|
||||
val depsByConfig = grouped(currentProject.dependencies)
|
||||
|
||||
depArtifacts
|
||||
.groupBy { case (dep, _) => dep }
|
||||
.map { case (dep, l) => dep -> l.map { case (_, a) => a } }
|
||||
.map { case (dep, artifacts) =>
|
||||
val fe = artifacts.map { a =>
|
||||
a -> trDepsWithArtifacts.getOrElse(a, -\/("Not downloaded"))
|
||||
}
|
||||
new ModuleReport(
|
||||
ModuleID(dep.module.organization, dep.module.name, dep.version, configurations = Some(dep.configuration)),
|
||||
fe.collect { case (artifact, \/-(file)) =>
|
||||
if (file.toString.contains("file:/"))
|
||||
throw new Exception(s"Wrong path: $file")
|
||||
ToSbt.artifact(dep.module, artifact) -> file
|
||||
},
|
||||
fe.collect { case (artifact, -\/(e)) =>
|
||||
errPrintln(s"${artifact.url}: $e")
|
||||
ToSbt.artifact(dep.module, artifact)
|
||||
},
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Map.empty,
|
||||
None,
|
||||
None,
|
||||
Nil,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
}
|
||||
}}
|
||||
|
||||
new UpdateReport(
|
||||
null,
|
||||
sbtModuleReportsPerScope.toVector.map { case (c, r) =>
|
||||
new ConfigurationReport(
|
||||
c,
|
||||
r.toVector,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
},
|
||||
new UpdateStats(-1L, -1L, -1L, cached = false),
|
||||
Map.empty
|
||||
ToSbt.updateReport(
|
||||
depsByConfig,
|
||||
res,
|
||||
configs,
|
||||
classifiers,
|
||||
artifactFileOpt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -286,8 +281,10 @@ object CoursierPlugin extends AutoPlugin {
|
|||
coursierCache := new File(sys.props("user.home") + "/.coursier/sbt"),
|
||||
update <<= updateTask(withClassifiers = false),
|
||||
updateClassifiers <<= updateTask(withClassifiers = true),
|
||||
updateSbtClassifiers in Defaults.TaskGlobal <<= updateTask(withClassifiers = true, sbtClassifiers = true),
|
||||
coursierProject <<= Tasks.coursierProjectTask,
|
||||
coursierProjects <<= Tasks.coursierProjectsTask
|
||||
coursierProjects <<= Tasks.coursierProjectsTask,
|
||||
coursierSbtClassifiersModule <<= classifiersModule in updateSbtClassifiers
|
||||
)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package coursier
|
||||
|
||||
import java.io.File
|
||||
import sbt.{ Resolver, SettingKey, TaskKey }
|
||||
import sbt.{ GetClassifiersModule, Resolver, SettingKey, TaskKey }
|
||||
|
||||
object Keys {
|
||||
val coursierParallelDownloads = SettingKey[Int]("coursier-parallel-downloads", "") // 6
|
||||
|
|
@ -17,4 +17,6 @@ object Keys {
|
|||
|
||||
val coursierProject = TaskKey[(Project, Seq[(String, Seq[Artifact])])]("coursier-project", "")
|
||||
val coursierProjects = TaskKey[Seq[(Project, Seq[(String, Seq[Artifact])])]]("coursier-projects", "")
|
||||
|
||||
val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module", "")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@ import sbt._
|
|||
|
||||
object ToSbt {
|
||||
|
||||
def moduleId(dependency: Dependency): sbt.ModuleID =
|
||||
sbt.ModuleID(
|
||||
dependency.module.organization,
|
||||
dependency.module.name,
|
||||
dependency.version,
|
||||
configurations = Some(dependency.configuration),
|
||||
extraAttributes = dependency.module.attributes
|
||||
)
|
||||
|
||||
def artifact(module: Module, artifact: Artifact): sbt.Artifact =
|
||||
sbt.Artifact(
|
||||
module.name,
|
||||
|
|
@ -15,4 +24,88 @@ object ToSbt {
|
|||
Map.empty
|
||||
)
|
||||
|
||||
def moduleReport(dependency: Dependency, artifacts: Seq[(Artifact, Option[File])]): sbt.ModuleReport =
|
||||
new sbt.ModuleReport(
|
||||
ToSbt.moduleId(dependency),
|
||||
artifacts.collect {
|
||||
case (artifact, Some(file)) =>
|
||||
(ToSbt.artifact(dependency.module, artifact), file)
|
||||
},
|
||||
artifacts.collect {
|
||||
case (artifact, None) =>
|
||||
ToSbt.artifact(dependency.module, artifact)
|
||||
},
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Map.empty,
|
||||
None,
|
||||
None,
|
||||
Nil,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
|
||||
private def grouped[K, V](map: Seq[(K, V)]): Map[K, Seq[V]] =
|
||||
map.groupBy { case (k, _) => k }.map {
|
||||
case (k, l) =>
|
||||
k -> l.map { case (_, v) => v }
|
||||
}
|
||||
|
||||
def moduleReports(
|
||||
res: Resolution,
|
||||
classifiersOpt: Option[Seq[String]],
|
||||
artifactFileOpt: Artifact => Option[File]
|
||||
) = {
|
||||
val depArtifacts =
|
||||
classifiersOpt match {
|
||||
case None => res.dependencyArtifacts
|
||||
case Some(cl) => res.dependencyClassifiersArtifacts(cl)
|
||||
}
|
||||
|
||||
val groupedDepArtifacts = grouped(depArtifacts)
|
||||
|
||||
groupedDepArtifacts.map {
|
||||
case (dep, artifacts) =>
|
||||
ToSbt.moduleReport(dep, artifacts.map(a => a -> artifactFileOpt(a)))
|
||||
}
|
||||
}
|
||||
|
||||
def updateReport(
|
||||
configDependencies: Map[String, Seq[Dependency]],
|
||||
resolution: Resolution,
|
||||
configs: Map[String, Set[String]],
|
||||
classifiersOpt: Option[Seq[String]],
|
||||
artifactFileOpt: Artifact => Option[File]
|
||||
): sbt.UpdateReport = {
|
||||
|
||||
val configReports = configs.map {
|
||||
case (config, extends0) =>
|
||||
val configDeps = extends0.flatMap(configDependencies.getOrElse(_, Nil))
|
||||
val partialRes = resolution.part(configDeps)
|
||||
|
||||
val reports = ToSbt.moduleReports(partialRes, classifiersOpt, artifactFileOpt)
|
||||
|
||||
new ConfigurationReport(
|
||||
config,
|
||||
reports.toVector,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
}
|
||||
|
||||
new UpdateReport(
|
||||
null,
|
||||
configReports.toVector,
|
||||
new UpdateStats(-1L, -1L, -1L, cached = false),
|
||||
Map.empty
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue