mirror of https://github.com/sbt/sbt.git
Merge pull request #2297 from sbt/wip/fix-2264
Fixes #2264. Fixes updateClassifiers when default configuration is missing + uses listed artifacts if any
This commit is contained in:
commit
8749a969c3
|
|
@ -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): 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(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,6 +258,21 @@ object IvyActions {
|
|||
throw w.resolveException
|
||||
}
|
||||
}
|
||||
// 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
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -31,8 +31,14 @@ final class ConfigurationReport(
|
|||
* All resolved modules for this configuration.
|
||||
* For a given organization and module name, there is only one revision/`ModuleID` in this sequence.
|
||||
*/
|
||||
def allModules: Seq[ModuleID] = modules.map(mr => addConfiguration(mr.module))
|
||||
private[this] def addConfiguration(mod: ModuleID): ModuleID = if (mod.configurations.isEmpty) mod.copy(configurations = Some(configuration)) else mod
|
||||
def allModules: Seq[ModuleID] = modules map addConfiguration
|
||||
private[this] def addConfiguration(mr: ModuleReport): ModuleID = {
|
||||
val module = mr.module
|
||||
if (module.configurations.isEmpty) {
|
||||
val conf = mr.configurations map (c => s"$configuration->$c") mkString ";"
|
||||
module.copy(configurations = Some(conf))
|
||||
} else module
|
||||
}
|
||||
|
||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
|
||||
new ConfigurationReport(configuration, modules map { _.retrieve((mid, art, file) => f(configuration, mid, art, file)) }, details, evicted)
|
||||
|
|
@ -194,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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
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)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
val fooFile = taskKey[File]("sample artifact")
|
||||
val RuntimeX = config("runtime")
|
||||
val check = taskKey[Unit]("check")
|
||||
|
||||
lazy val commonSettings = Seq(
|
||||
organization := "com.example",
|
||||
version := "0.1-SNAPSHOT",
|
||||
scalaVersion := "2.11.7",
|
||||
ivyPaths := new IvyPaths( (baseDirectory in ThisBuild).value, Some((target in LocalRootProject).value / "ivy-cache")),
|
||||
fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project")
|
||||
)
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(commonSettings)
|
||||
|
||||
lazy val classifierproducer = (project in file("classifierproducer")).
|
||||
settings(
|
||||
commonSettings,
|
||||
fooFile := { baseDirectory.value / "foo.txt" },
|
||||
addArtifact( Artifact("classifierproducer", "text", "txt", "runtime"), fooFile),
|
||||
ivyConfigurations := Seq(RuntimeX, Configurations.ScalaTool),
|
||||
publishArtifact in Compile := false,
|
||||
publishArtifact in Test := false,
|
||||
publishMavenStyle := false,
|
||||
autoScalaLibrary := false,
|
||||
crossPaths := false
|
||||
)
|
||||
|
||||
lazy val classifierconsumer = (project in file("classifierconsumer")).
|
||||
settings(
|
||||
commonSettings,
|
||||
libraryDependencies += "com.example" % "classifierproducer" % "0.1-SNAPSHOT" % "compile->runtime",
|
||||
check := {
|
||||
val ur = updateClassifiers.value
|
||||
val mrs = for {
|
||||
cr <- ur.configurations if cr.configuration == "compile"
|
||||
oar <- cr.details if (oar.organization == "com.example") && (oar.name == "classifierproducer")
|
||||
mr <- oar.modules if (mr.module.revision == "0.1-SNAPSHOT")
|
||||
} yield mr
|
||||
val mr = mrs.head
|
||||
if (mr.artifacts exists { case (a: Artifact, f) =>
|
||||
a.extension == "txt"
|
||||
}) ()
|
||||
else sys.error("txt artifact was not found: " + mr.toString)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
> classifierproducer/publishLocal
|
||||
|
||||
> classifierconsumer/check
|
||||
Loading…
Reference in New Issue