Fixes #2264. Use explicit artifacts if any, fallback to hardcoded

Even though it's not really used, updateClassifiers constructs
dependency graph based on the result from update.
The direct cause of #2264 came from the fact that the `allModules`
returned from ConfigurationReport did not include dependency
configurations. For example it returned "compile" instead of
"compile->runtime". I've identified that in #2264 and was fixed by
@Duhemm in f49fb33e6d.

Martin identified that the fix still does not address the fact that
updateClassifier hardcodes the classifiers to be tried. This commit
adds the fallback behavior so for Ivy-published modules it will use the
explicit list of artifacts, and for others it will fallback to the
hardcoded list of classifiers.
This commit is contained in:
Eugene Yokota 2015-12-02 16:41:02 -05:00
parent 13410ca68e
commit 3a3965b5f5
4 changed files with 51 additions and 12 deletions

View File

@ -231,20 +231,24 @@ object IvyActions {
throw w.resolveException
}
val newConfig = config.copy(module = mod.copy(modules = report.allModules))
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, log, ???)
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, Vector(), log)
}
@deprecated("This is no longer public.", "0.13.6")
def updateClassifiers(ivySbt: IvySbt, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
updateClassifiers(ivySbt, config, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log, ???)
updateClassifiers(ivySbt, config, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, Vector(), log)
// artifacts can be obtained from calling toSeq on UpdateReport
private[sbt] def updateClassifiers(ivySbt: IvySbt, config: GetClassifiersConfiguration,
uwconfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File], log: Logger, upd: UpdateReport): UpdateReport =
uwconfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File],
artifacts: Vector[(String, ModuleID, Artifact, File)],
log: Logger): UpdateReport =
{
import config.{ configuration => c, module => mod, _ }
import mod.{ configurations => confs, _ }
assert(classifiers.nonEmpty, "classifiers cannot be empty")
val baseModules = modules map { m => restrictedCopy(m, true) }
val deps = baseModules.distinct flatMap classifiedArtifacts(upd, exclude) //classifiedArtifacts(classifiers, exclude)
// Adding list of explicit artifacts here.
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts)
val base = restrictedCopy(id, true).copy(name = id.name + classifiers.mkString("$", "_", ""))
val module = new ivySbt.Module(InlineConfigurationWithExcludes(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala, configurations = confs))
val upConf = new UpdateConfiguration(c.retrieve, true, c.logging)
@ -254,14 +258,21 @@ object IvyActions {
throw w.resolveException
}
}
def classifiedArtifacts(updateReport: UpdateReport, exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] = {
// This version adds explicit artifact
private[sbt] def classifiedArtifacts(classifiers: Seq[String],
exclude: Map[ModuleID, Set[String]],
artifacts: Vector[(String, ModuleID, Artifact, File)])(m: ModuleID): Option[ModuleID] = {
def sameModule(m1: ModuleID, m2: ModuleID): Boolean = m1.organization == m2.organization && m1.name == m2.name && m1.revision == m2.revision
updateReport.toSeq.groupBy(_._2) collectFirst {
case (k, v) if sameModule(k, m) =>
val arts = v.collect { case (_, _, art, _) if art.classifier.isDefined => art }.distinct
m.copy(isTransitive = false, explicitArtifacts = arts)
}
def explicitArtifacts =
{
val arts = (artifacts collect { case (_, x, art, _) if sameModule(m, x) && art.classifier.isDefined => art }).distinct
if (arts.isEmpty) None
else Some(m.copy(isTransitive = false, explicitArtifacts = arts))
}
def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m)
explicitArtifacts orElse hardcodedArtifacts
}
@deprecated("This is no longer public.", "0.13.10")
def classifiedArtifacts(classifiers: Seq[String], exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] =
{
val excluded = exclude getOrElse (restrictedCopy(m, false), Set.empty)

View File

@ -200,7 +200,21 @@ final class UpdateReport(val cachedDescriptor: File, val configurations: Seq[Con
override def toString = "Update report:\n\t" + stats + "\n" + configurations.mkString
/** All resolved modules in all configurations. */
def allModules: Seq[ModuleID] = configurations.flatMap(_.allModules).distinct
def allModules: Seq[ModuleID] =
{
val key = (m: ModuleID) => (m.organization, m.name, m.revision)
configurations.flatMap(_.allModules).groupBy(key).toSeq map {
case (k, v) =>
v reduceLeft { (agg, x) =>
agg.copy(
configurations = (agg.configurations, x.configurations) match {
case (None, _) => x.configurations
case (Some(ac), None) => Some(ac)
case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
})
}
}
}
def retrieve(f: (String, ModuleID, Artifact, File) => File): UpdateReport =
new UpdateReport(cachedDescriptor, configurations map { _ retrieve f }, stats, stamps)

View File

@ -1234,7 +1234,8 @@ object Classpaths {
val uwConfig = (unresolvedWarningConfiguration in update).value
val logicalClock = LogicalClock(state.value.hashCode)
val depDir = dependencyCacheDirectory.value
IvyActions.updateClassifiers(is, GetClassifiersConfiguration(mod, excludes, c, ivyScala.value), uwConfig, LogicalClock(state.value.hashCode), Some(depDir), s.log, update.value)
val artifacts = update.value.toSeq.toVector
IvyActions.updateClassifiers(is, GetClassifiersConfiguration(mod, excludes, c, ivyScala.value), uwConfig, LogicalClock(state.value.hashCode), Some(depDir), artifacts, s.log)
}
} tag (Tags.Update, Tags.Network)
)

View File

@ -0,0 +1,13 @@
[@eed3si9n]: https://github.com/eed3si9n
[@Duhemm]: https://github.com/Duhemm
[2264]: https://github.com/sbt/sbt/issues/2264
### Fixes with compatibility implications
### Improvements
### Bug fixes
- Fixes `updateClassifiers` on Ivy modules without `default` configuration.
[#2264][2264] by [@eed3si9n][@eed3si9n]/[@Duhemm][@Duhemm]