Run resolution for each configuration

Rather than for each configuration sub-graph. This runs a resolution for
Compile, one for Runtime, one for Test, etc. rather than one for all 3
of them, for example.

We re-use the Resolution instance from the first extended configuration,
so that the performance penalty is really low.
This commit is contained in:
Alexandre Archambault 2020-05-18 12:57:28 +02:00
parent 627877fcc7
commit 3cd521c43c
22 changed files with 171 additions and 76 deletions

View File

@ -129,9 +129,11 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen
(ToCoursier.configuration(config), ToCoursier.dependency(dep0)) (ToCoursier.configuration(config), ToCoursier.dependency(dep0))
} }
val configGraphs = Inputs.ivyGraphs( val orderedConfigs = Inputs.orderedConfigurations(Inputs.configExtendsSeq(module0.configurations))
Inputs.configExtends(module0.configurations) .map {
).map(_.map(ToCoursier.configuration)) case (config, extends0) =>
(ToCoursier.configuration(config), extends0.map(ToCoursier.configuration))
}
val typelevel = so == Typelevel.typelevelOrg val typelevel = so == Typelevel.typelevelOrg
@ -146,7 +148,7 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen
val resolutionParams = ResolutionParams( val resolutionParams = ResolutionParams(
dependencies = dependencies, dependencies = dependencies,
fallbackDependencies = conf.fallbackDependencies, fallbackDependencies = conf.fallbackDependencies,
configGraphs = configGraphs, orderedConfigs = orderedConfigs,
autoScalaLibOpt = if (conf.autoScalaLibrary) Some((so, sv)) else None, autoScalaLibOpt = if (conf.autoScalaLibrary) Some((so, sv)) else None,
mainRepositories = mainRepositories, mainRepositories = mainRepositories,
parentProjectCache = Map.empty, parentProjectCache = Map.empty,
@ -167,10 +169,10 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen
missingOk = conf.missingOk, missingOk = conf.missingOk,
) )
def artifactsParams(resolutions: Map[Set[Configuration], Resolution]): ArtifactsParams = def artifactsParams(resolutions: Map[Configuration, Resolution]): ArtifactsParams =
ArtifactsParams( ArtifactsParams(
classifiers = classifiers, classifiers = classifiers,
resolutions = resolutions.values.toSeq, resolutions = resolutions.values.toSeq.distinct,
includeSignatures = false, includeSignatures = false,
loggerOpt = loggerOpt, loggerOpt = loggerOpt,
projectName = projectName, projectName = projectName,
@ -193,7 +195,7 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen
} }
def updateParams( def updateParams(
resolutions: Map[Set[Configuration], Resolution], resolutions: Map[Configuration, Resolution],
artifacts: Seq[(Dependency, Publication, Artifact, Option[File])] artifacts: Seq[(Dependency, Publication, Artifact, Option[File])]
) = ) =
UpdateParams( UpdateParams(

View File

@ -15,6 +15,11 @@ object Inputs {
Configuration(from.value) -> Configuration(to.value) Configuration(from.value) -> Configuration(to.value)
} }
def configExtendsSeq(configurations: Seq[sbt.librarymanagement.Configuration]): Seq[(Configuration, Seq[Configuration])] =
configurations
.map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name)))
@deprecated("Now unused internally, to be removed in the future", "2.0.0-RC6-5")
def configExtends(configurations: Seq[sbt.librarymanagement.Configuration]): Map[Configuration, Seq[Configuration]] = def configExtends(configurations: Seq[sbt.librarymanagement.Configuration]): Map[Configuration, Seq[Configuration]] =
configurations configurations
.map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name))) .map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name)))
@ -25,7 +30,7 @@ object Inputs {
shadedConfig: Option[(String, Configuration)] = None shadedConfig: Option[(String, Configuration)] = None
): Map[Configuration, Set[Configuration]] = { ): Map[Configuration, Set[Configuration]] = {
val configs0 = configExtends(configurations) val configs0 = configExtendsSeq(configurations).toMap
def allExtends(c: Configuration) = { def allExtends(c: Configuration) = {
// possibly bad complexity // possibly bad complexity
@ -55,6 +60,29 @@ object Inputs {
} }
} }
def orderedConfigurations(
configurations: Seq[(Configuration, Seq[Configuration])]
): Seq[(Configuration, Seq[Configuration])] = {
val map = configurations.toMap
def helper(done: Set[Configuration], toAdd: List[Configuration]): Stream[(Configuration, Seq[Configuration])] =
toAdd match {
case Nil => Stream.empty
case config :: rest =>
val extends0 = map.getOrElse(config, Nil)
val missingExtends = extends0.filterNot(done)
if (missingExtends.isEmpty)
(config, extends0) #:: helper(done + config, rest)
else
helper(done, missingExtends.toList ::: toAdd)
}
helper(Set.empty, configurations.map(_._1).toList)
.toVector
}
@deprecated("Now unused internally, to be removed in the future", "2.0.0-RC6-5")
def ivyGraphs(configurations: Map[Configuration, Seq[Configuration]]): Seq[Set[Configuration]] = { def ivyGraphs(configurations: Map[Configuration, Seq[Configuration]]): Seq[Set[Configuration]] = {
// probably bad complexity, but that shouldn't matter given the size of the graphs involved... // probably bad complexity, but that shouldn't matter given the size of the graphs involved...

View File

@ -10,11 +10,13 @@ import lmcoursier.FallbackDependency
import lmcoursier.definitions.ToCoursier import lmcoursier.definitions.ToCoursier
import coursier.util.Task import coursier.util.Task
import scala.collection.mutable
// private[coursier] // private[coursier]
final case class ResolutionParams( final case class ResolutionParams(
dependencies: Seq[(Configuration, Dependency)], dependencies: Seq[(Configuration, Dependency)],
fallbackDependencies: Seq[FallbackDependency], fallbackDependencies: Seq[FallbackDependency],
configGraphs: Seq[Set[Configuration]], orderedConfigs: Seq[(Configuration, Seq[Configuration])],
autoScalaLibOpt: Option[(Organization, String)], autoScalaLibOpt: Option[(Organization, String)],
mainRepositories: Seq[Repository], mainRepositories: Seq[Repository],
parentProjectCache: ProjectCache, parentProjectCache: ProjectCache,
@ -30,6 +32,18 @@ final case class ResolutionParams(
missingOk: Boolean, missingOk: Boolean,
) { ) {
lazy val allConfigExtends: Map[Configuration, Set[Configuration]] = {
val map = new mutable.HashMap[Configuration, Set[Configuration]]
for ((config, extends0) <- orderedConfigs) {
val allExtends = extends0
.iterator
// the else of the getOrElse shouldn't be hit (because of the ordering of the configurations)
.foldLeft(Set(config))((acc, ext) => acc ++ map.getOrElse(ext, Set(ext)))
map += config -> allExtends
}
map.toMap
}
val fallbackDependenciesRepositories = val fallbackDependenciesRepositories =
if (fallbackDependencies.isEmpty) if (fallbackDependencies.isEmpty)
Nil Nil

View File

@ -9,6 +9,8 @@ import coursier.maven.MavenRepository
import coursier.params.rule.RuleResolution import coursier.params.rule.RuleResolution
import sbt.util.Logger import sbt.util.Logger
import scala.collection.mutable
// private[coursier] // private[coursier]
object ResolutionRun { object ResolutionRun {
@ -16,7 +18,8 @@ object ResolutionRun {
params: ResolutionParams, params: ResolutionParams,
verbosityLevel: Int, verbosityLevel: Int,
log: Logger, log: Logger,
configs: Set[Configuration] configs: Set[Configuration],
startingResolutionOpt: Option[Resolution]
): Either[coursier.error.ResolutionError, Resolution] = { ): Either[coursier.error.ResolutionError, Resolution] = {
val isScalaToolConfig = configs(Configuration("scala-tool")) val isScalaToolConfig = configs(Configuration("scala-tool"))
@ -80,6 +83,8 @@ object ResolutionRun {
ThreadUtil.withFixedThreadPool(params.parallel) { pool => ThreadUtil.withFixedThreadPool(params.parallel) { pool =>
Resolve() Resolve()
// re-using various caches from a resolution of a configuration we extend
.withInitialResolution(startingResolutionOpt)
.withDependencies( .withDependencies(
params.dependencies.collect { params.dependencies.collect {
case (config, dep) if configs(config) => case (config, dep) if configs(config) =>
@ -126,7 +131,7 @@ object ResolutionRun {
params: ResolutionParams, params: ResolutionParams,
verbosityLevel: Int, verbosityLevel: Int,
log: Logger log: Logger
): Either[coursier.error.ResolutionError, Map[Set[Configuration], Resolution]] = { ): Either[coursier.error.ResolutionError, Map[Configuration, Resolution]] = {
// TODO Warn about possible duplicated modules from source repositories? // TODO Warn about possible duplicated modules from source repositories?
@ -141,13 +146,24 @@ object ResolutionRun {
// Downloads are already parallel, no need to parallelize further, anyway. // Downloads are already parallel, no need to parallelize further, anyway.
val resOrError = val resOrError =
Lock.lock.synchronized { Lock.lock.synchronized {
params.configGraphs.foldLeft[Either[coursier.error.ResolutionError, Map[Set[Configuration], Resolution]]](Right(Map())) { var map = new mutable.HashMap[Configuration, Resolution]
case (acc, config) => val either = params.orderedConfigs.foldLeft[Either[coursier.error.ResolutionError, Unit]](Right(())) {
case (acc, (config, extends0)) =>
for { for {
m <- acc _ <- acc
res <- resolution(params, verbosityLevel, log, config) initRes = {
} yield m + (config -> res) val it = extends0.iterator.flatMap(map.get(_).iterator)
if (it.hasNext) Some(it.next())
else None
}
allExtends = params.allConfigExtends.getOrElse(config, Set.empty)
res <- resolution(params, verbosityLevel, log, allExtends, initRes)
} yield {
map += config -> res
()
}
} }
either.map(_ => map.toMap)
} }
for (res <- resOrError) for (res <- resOrError)
SbtCoursierCache.default.putResolution(params.resolutionKey, res) SbtCoursierCache.default.putResolution(params.resolutionKey, res)

View File

@ -12,15 +12,15 @@ class SbtCoursierCache {
import SbtCoursierCache._ import SbtCoursierCache._
private val resolutionsCache = new ConcurrentHashMap[ResolutionKey, Map[Set[Configuration], Resolution]] private val resolutionsCache = new ConcurrentHashMap[ResolutionKey, Map[Configuration, Resolution]]
// these may actually not need to be cached any more, now that the resolutions // these may actually not need to be cached any more, now that the resolutions
// are cached // are cached
private val reportsCache = new ConcurrentHashMap[ReportKey, UpdateReport] private val reportsCache = new ConcurrentHashMap[ReportKey, UpdateReport]
def resolutionOpt(key: ResolutionKey): Option[Map[Set[Configuration], Resolution]] = def resolutionOpt(key: ResolutionKey): Option[Map[Configuration, Resolution]] =
Option(resolutionsCache.get(key)) Option(resolutionsCache.get(key))
def putResolution(key: ResolutionKey, res: Map[Set[Configuration], Resolution]): Unit = def putResolution(key: ResolutionKey, res: Map[Configuration, Resolution]): Unit =
resolutionsCache.put(key, res) resolutionsCache.put(key, res)
def reportOpt(key: ReportKey): Option[UpdateReport] = def reportOpt(key: ReportKey): Option[UpdateReport] =
@ -53,7 +53,7 @@ object SbtCoursierCache {
final case class ReportKey( final case class ReportKey(
dependencies: Seq[(Configuration, Dependency)], dependencies: Seq[(Configuration, Dependency)],
resolution: Map[Set[Configuration], Resolution], resolution: Map[Configuration, Resolution],
withClassifiers: Boolean, withClassifiers: Boolean,
sbtClassifiers: Boolean, sbtClassifiers: Boolean,
includeSignatures: Boolean includeSignatures: Boolean

View File

@ -132,7 +132,6 @@ private[internal] object SbtUpdateReport {
private def moduleReports( private def moduleReports(
thisModule: (Module, String), thisModule: (Module, String),
config: Configuration,
res: Resolution, res: Resolution,
interProjectDependencies: Seq[Project], interProjectDependencies: Seq[Project],
classifiersOpt: Option[Seq[Classifier]], classifiersOpt: Option[Seq[Classifier]],
@ -293,9 +292,8 @@ private[internal] object SbtUpdateReport {
def apply( def apply(
thisModule: (Module, String), thisModule: (Module, String),
configDependencies: Map[Configuration, Seq[Dependency]], configDependencies: Map[Configuration, Seq[Dependency]],
resolutions: Map[Configuration, Resolution], resolutions: Seq[(Configuration, Resolution)],
interProjectDependencies: Vector[Project], interProjectDependencies: Vector[Project],
configs: Map[Configuration, Set[Configuration]],
classifiersOpt: Option[Seq[Classifier]], classifiersOpt: Option[Seq[Classifier]],
artifactFileOpt: (Module, String, Attributes, Artifact) => Option[File], artifactFileOpt: (Module, String, Attributes, Artifact) => Option[File],
fullArtifactsOpt: Option[Map[(Dependency, Publication, Artifact), Option[File]]], fullArtifactsOpt: Option[Map[(Dependency, Publication, Artifact), Option[File]]],
@ -306,18 +304,11 @@ private[internal] object SbtUpdateReport {
missingOk: Boolean missingOk: Boolean
): UpdateReport = { ): UpdateReport = {
val configReports = configs.map { val configReports = resolutions.map {
case (config, extends0) => case (config, subRes) =>
val configDeps = extends0
.toSeq
.sortBy(_.value)
.flatMap(configDependencies.getOrElse(_, Nil))
.distinct
val subRes = resolutions(config).subset(configDeps)
val reports = moduleReports( val reports = moduleReports(
thisModule, thisModule,
config,
subRes, subRes,
interProjectDependencies, interProjectDependencies,
classifiersOpt, classifiersOpt,

View File

@ -15,7 +15,7 @@ final case class UpdateParams(
configs: Map[Configuration, Set[Configuration]], configs: Map[Configuration, Set[Configuration]],
dependencies: Seq[(Configuration, Dependency)], dependencies: Seq[(Configuration, Dependency)],
interProjectDependencies: Seq[Project], interProjectDependencies: Seq[Project],
res: Map[Set[Configuration], Resolution], res: Map[Configuration, Resolution],
includeSignatures: Boolean, includeSignatures: Boolean,
sbtBootJarOverrides: Map[(Module, String), File], sbtBootJarOverrides: Map[(Module, String), File],
classpathOrder: Boolean, classpathOrder: Boolean,

View File

@ -57,11 +57,6 @@ object UpdateRun {
log: Logger log: Logger
): UpdateReport = Lock.lock.synchronized { ): UpdateReport = Lock.lock.synchronized {
val configResolutions = params.res.flatMap {
case (configs, r) =>
configs.iterator.map((_, r))
}
val depsByConfig = grouped(params.dependencies)( val depsByConfig = grouped(params.dependencies)(
config => config =>
params.shadedConfigOpt match { params.shadedConfigOpt match {
@ -74,7 +69,7 @@ object UpdateRun {
if (verbosityLevel >= 2) { if (verbosityLevel >= 2) {
val finalDeps = dependenciesWithConfig( val finalDeps = dependenciesWithConfig(
configResolutions, params.res,
depsByConfig, depsByConfig,
params.configs params.configs
) )
@ -87,9 +82,8 @@ object UpdateRun {
SbtUpdateReport( SbtUpdateReport(
params.thisModule, params.thisModule,
depsByConfig, depsByConfig,
configResolutions, params.res.toVector.sortBy(_._1.value), // FIXME Order by config topologically?
params.interProjectDependencies.toVector, params.interProjectDependencies.toVector,
params.configs,
params.classifiers, params.classifiers,
params.artifactFileOpt, params.artifactFileOpt,
params.fullArtifacts, params.fullArtifacts,

View File

@ -37,7 +37,7 @@ object InputsTasks {
val exclusions0 = Inputs.exclusions(excludeDeps, sv, sbv, log) val exclusions0 = Inputs.exclusions(excludeDeps, sv, sbv, log)
val configMap = Inputs.configExtends(configurations) val configMap = Inputs.configExtendsSeq(configurations).toMap
val proj = FromSbt.project( val proj = FromSbt.project(
projId, projId,

View File

@ -176,13 +176,10 @@ object CoursierPlugin extends AutoPlugin {
coursierResolutions coursierResolutions
.value .value
.collectFirst { .getOrElse(
case (configs, res) if configs(config) => config,
res
}
.getOrElse {
sys.error(s"Resolution for configuration $config not found") sys.error(s"Resolution for configuration $config not found")
} )
}, },
coursierSbtClassifiersResolution := (Def.taskDyn { coursierSbtClassifiersResolution := (Def.taskDyn {
val missingOk = (updateConfiguration in updateSbtClassifiers).value.missingOk val missingOk = (updateConfiguration in updateSbtClassifiers).value.missingOk

View File

@ -13,7 +13,7 @@ import scala.collection.mutable
object DisplayTasks { object DisplayTasks {
private case class ResolutionResult(configs: Set[Configuration], resolution: Resolution, dependencies: Seq[Dependency]) private case class ResolutionResult(config: Configuration, resolution: Resolution, dependencies: Seq[Dependency])
private def coursierResolutionTask( private def coursierResolutionTask(
sbtClassifiers: Boolean = false, sbtClassifiers: Boolean = false,
@ -40,7 +40,11 @@ object DisplayTasks {
Def.task { Def.task {
val currentProject = currentProjectTask.value val currentProject = currentProjectTask.value
val classifiersRes = coursierSbtClassifiersResolution.value val classifiersRes = coursierSbtClassifiersResolution.value
Map(currentProject.configurations.keySet.map(ToCoursier.configuration) -> classifiersRes) currentProject
.configurations
.keysIterator
.map(config => ToCoursier.configuration(config) -> classifiersRes)
.toMap
} }
else else
Def.task(coursierResolutions.value) Def.task(coursierResolutions.value)
@ -57,19 +61,23 @@ object DisplayTasks {
val resolutions = resolutionsTask.value val resolutions = resolutionsTask.value
for { for {
(subGraphConfigs, res) <- resolutions.toSeq (subGraphConfig, res) <- resolutions.toSeq
if subGraphConfigs.exists(includedConfigs) if includedConfigs(subGraphConfig)
} yield { } yield {
val dependencies0 = currentProject.dependencies.collect { val dependencies0 = currentProject
case (cfg, dep) if includedConfigs(cfg) && subGraphConfigs(cfg) => dep .dependencies
}.sortBy { dep => .collect {
(dep.module.organization, dep.module.name, dep.version) case (`subGraphConfig`, dep) =>
} dep
}
.sortBy { dep =>
(dep.module.organization, dep.module.name, dep.version)
}
val subRes = res.subset(dependencies0) val subRes = res.subset(dependencies0)
ResolutionResult(subGraphConfigs, subRes, dependencies0) ResolutionResult(subGraphConfig, subRes, dependencies0)
} }
} }
} }
@ -82,9 +90,9 @@ object DisplayTasks {
val projectName = thisProjectRef.value.project val projectName = thisProjectRef.value.project
val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value
for (ResolutionResult(subGraphConfigs, resolution, dependencies) <- resolutions) { for (ResolutionResult(subGraphConfig, resolution, dependencies) <- resolutions) {
streams.value.log.info( streams.value.log.info(
s"$projectName (configurations ${subGraphConfigs.toVector.sorted.mkString(", ")})" + "\n" + s"$projectName (configuration ${subGraphConfig.value})" + "\n" +
Print.dependencyTree( Print.dependencyTree(
resolution, resolution,
dependencies, dependencies,
@ -110,13 +118,13 @@ object DisplayTasks {
val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value
val result = new mutable.StringBuilder val result = new mutable.StringBuilder
for (ResolutionResult(subGraphConfigs, resolution, _) <- resolutions) { for (ResolutionResult(subGraphConfig, resolution, _) <- resolutions) {
val roots = resolution val roots = resolution
.minDependencies .minDependencies
.filter(f => f.module == module) .filter(f => f.module == module)
.toVector .toVector
.sortBy(_.toString) // elements already have the same module, there's not much left for sorting .sortBy(_.toString) // elements already have the same module, there's not much left for sorting
val strToPrint = s"$projectName (configurations ${subGraphConfigs.toVector.sorted.map(_.value).mkString(", ")})" + "\n" + val strToPrint = s"$projectName (configurations ${subGraphConfig.value})" + "\n" +
Print.dependencyTree( Print.dependencyTree(
resolution, resolution,
roots, roots,

View File

@ -26,10 +26,13 @@ object InputsTasks {
} }
} }
def ivyGraphsTask: Def.Initialize[sbt.Task[Seq[Set[Configuration]]]] = def ivyGraphsTask: Def.Initialize[sbt.Task[Seq[(Configuration, Seq[Configuration])]]] =
Def.task { Def.task {
val p = coursierProject.value val p = coursierProject.value
Inputs.ivyGraphs(p.configurations).map(_.map(ToCoursier.configuration)) Inputs.orderedConfigurations(p.configurations.toSeq).map {
case (config, extends0) =>
(ToCoursier.configuration(config), extends0.map(ToCoursier.configuration))
}
} }
def parentProjectCacheTask: Def.Initialize[sbt.Task[Map[Seq[sbt.librarymanagement.Resolver], Seq[coursier.ProjectCache]]]] = def parentProjectCacheTask: Def.Initialize[sbt.Task[Map[Seq[sbt.librarymanagement.Resolver], Seq[coursier.ProjectCache]]]] =
@ -53,7 +56,7 @@ object InputsTasks {
n.foldLeft(Map.empty[Seq[Resolver], Seq[ProjectCache]]) { n.foldLeft(Map.empty[Seq[Resolver], Seq[ProjectCache]]) {
case (caches, (ref, resolutions)) => case (caches, (ref, resolutions)) =>
val mainResOpt = resolutions.collectFirst { val mainResOpt = resolutions.collectFirst {
case (k, v) if k(Configuration.compile) => v case (Configuration.compile, v) => v
} }
val r = for { val r = for {

View File

@ -21,7 +21,7 @@ object Keys {
val coursierVerbosity = SettingKey[Int]("coursier-verbosity") val coursierVerbosity = SettingKey[Int]("coursier-verbosity")
val coursierConfigGraphs = TaskKey[Seq[Set[Configuration]]]("coursier-config-graphs") val coursierConfigGraphs = TaskKey[Seq[(Configuration, Seq[Configuration])]]("coursier-config-graphs")
val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module") val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module")
@ -29,7 +29,7 @@ object Keys {
val coursierParentProjectCache = TaskKey[Map[Seq[Resolver], Seq[ProjectCache]]]("coursier-parent-project-cache") val coursierParentProjectCache = TaskKey[Map[Seq[Resolver], Seq[ProjectCache]]]("coursier-parent-project-cache")
val coursierResolutions = TaskKey[Map[Set[Configuration], Resolution]]("coursier-resolutions") val coursierResolutions = TaskKey[Map[Configuration, Resolution]]("coursier-resolutions")
private[coursier] val actualCoursierResolution = TaskKey[Resolution]("coursier-resolution") private[coursier] val actualCoursierResolution = TaskKey[Resolution]("coursier-resolution")

View File

@ -19,9 +19,9 @@ object ResolutionTasks {
def resolutionsTask( def resolutionsTask(
sbtClassifiers: Boolean = false, sbtClassifiers: Boolean = false,
missingOk: Boolean = false, missingOk: Boolean = false,
): Def.Initialize[sbt.Task[Map[Set[Configuration], coursier.Resolution]]] = { ): Def.Initialize[sbt.Task[Map[Configuration, coursier.Resolution]]] = {
val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[FallbackDependency], Seq[Set[Configuration]])]] = val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[FallbackDependency], Seq[(Configuration, Seq[Configuration])])]] =
if (sbtClassifiers) if (sbtClassifiers)
Def.task { Def.task {
val sv = scalaVersion.value val sv = scalaVersion.value
@ -35,7 +35,7 @@ object ResolutionTasks {
sbv sbv
) )
(proj, fallbackDeps, Vector(cm.configurations.map(c => Configuration(c.name)).toSet)) (proj, fallbackDeps, cm.configurations.map(c => Configuration(c.name) -> Nil))
} }
else else
Def.task { Def.task {
@ -97,7 +97,7 @@ object ResolutionTasks {
val authenticationByRepositoryId = coursierCredentials.value.mapValues(_.authentication) val authenticationByRepositoryId = coursierCredentials.value.mapValues(_.authentication)
val (currentProject, fallbackDependencies, configGraphs) = currentProjectTask.value val (currentProject, fallbackDependencies, orderedConfigs) = currentProjectTask.value
val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall(_.overrideScalaVersion) val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall(_.overrideScalaVersion)
@ -132,7 +132,7 @@ object ResolutionTasks {
ResolutionParams( ResolutionParams(
dependencies = currentProject.dependencies, dependencies = currentProject.dependencies,
fallbackDependencies = fallbackDependencies, fallbackDependencies = fallbackDependencies,
configGraphs = configGraphs, orderedConfigs = orderedConfigs,
autoScalaLibOpt = if (autoScalaLib) Some((so, sv)) else None, autoScalaLibOpt = if (autoScalaLib) Some((so, sv)) else None,
mainRepositories = mainRepositories, mainRepositories = mainRepositories,
parentProjectCache = parentProjectCache, parentProjectCache = parentProjectCache,

View File

@ -35,9 +35,13 @@ object UpdateTasks {
val resTask = val resTask =
if (withClassifiers && sbtClassifiers) if (withClassifiers && sbtClassifiers)
Def.task { Def.task {
val cm = coursierSbtClassifiersModule.value val mod = coursierSbtClassifiersModule.value
val classifiersRes = coursierSbtClassifiersResolution.value val classifiersRes = coursierSbtClassifiersResolution.value
Map(cm.configurations.map(c => Configuration(c.name)).toSet -> classifiersRes) mod
.configurations
.iterator
.map(c => Configuration(c.name) -> classifiersRes)
.toMap
} }
else else
Def.task(coursierResolutions.value) Def.task(coursierResolutions.value)

View File

@ -12,5 +12,6 @@ import CoursierPlugin.autoImport._
whatDependsOnCheck := { whatDependsOnCheck := {
val result = (coursierWhatDependsOn in Compile).toTask(" log4j:log4j").value val result = (coursierWhatDependsOn in Compile).toTask(" log4j:log4j").value
val file = new File("whatDependsOnResult.log") val file = new File("whatDependsOnResult.log")
assert(IO.read(file).toString == result) val expected = IO.read(file).toString
assert(expected == result, s"Expected '$expected', got '$result'")
} }

View File

@ -1,4 +1,4 @@
dependency-graph (configurations compile, compile-internal, optional, provided, runtime, runtime-internal, test, test-internal) dependency-graph (configurations compile)
└─ log4j:log4j:1.2.17 └─ log4j:log4j:1.2.17
├─ org.apache.zookeeper:zookeeper:3.5.0-alpha log4j:log4j:1.2.16 -> 1.2.17 ├─ org.apache.zookeeper:zookeeper:3.5.0-alpha log4j:log4j:1.2.16 -> 1.2.17
└─ org.slf4j:slf4j-log4j12:1.7.5 └─ org.slf4j:slf4j-log4j12:1.7.5

View File

@ -0,0 +1,8 @@
scalaVersion := "2.13.2"
libraryDependencies ++= Seq(
"io.get-coursier" %% "coursier-core" % "2.0.0-RC6",
// depends on coursier-core 2.0.0-RC6-16
"io.get-coursier" %% "coursier" % "2.0.0-RC6-16" % Test
)
mainClass.in(Compile) := Some("Main")
mainClass.in(Test) := Some("Test")

View File

@ -0,0 +1,13 @@
addSbtPlugin {
val name = sys.props.getOrElse(
"plugin.name",
sys.error("plugin.name Java property not set")
)
val version = sys.props.getOrElse(
"plugin.version",
sys.error("plugin.version Java property not set")
)
"io.get-coursier" % name % version
}

View File

@ -0,0 +1,7 @@
object Main {
def main(args: Array[String]): Unit = {
val version = coursier.util.Properties.version
val expected = "2.0.0-RC6"
assert(version == expected, s"version: $version, expected: $expected")
}
}

View File

@ -0,0 +1,7 @@
object Test {
def main(args: Array[String]): Unit = {
val version = coursier.util.Properties.version
val expected = "2.0.0-RC6-16"
assert(version == expected, s"version: $version, expected: $expected")
}
}

View File

@ -0,0 +1,2 @@
> run
> test:run