mirror of https://github.com/sbt/sbt.git
[2.x] fix: Fixes the local artifact handling in updateSbtClassifiers task (#8734)
- this should also work for global plugins once they are fixed in sbt 2.x - add `missingOk` support in classifier resolution to enable failure-tolerant artifact retrieval
This commit is contained in:
parent
0cae58403f
commit
9ca4f186f1
|
|
@ -3633,6 +3633,7 @@ object Classpaths {
|
||||||
.withArtifactFilter(
|
.withArtifactFilter(
|
||||||
updateConfig0.artifactFilter.map(af => af.withInverted(!af.inverted))
|
updateConfig0.artifactFilter.map(af => af.withInverted(!af.inverted))
|
||||||
)
|
)
|
||||||
|
.withMissingOk(true)
|
||||||
val app = appConfiguration.value
|
val app = appConfiguration.value
|
||||||
val srcTypes = sourceArtifactTypes.value
|
val srcTypes = sourceArtifactTypes.value
|
||||||
val docTypes = docArtifactTypes.value
|
val docTypes = docArtifactTypes.value
|
||||||
|
|
@ -3718,11 +3719,14 @@ object Classpaths {
|
||||||
val ref = thisProjectRef.value
|
val ref = thisProjectRef.value
|
||||||
val unit = loadedBuild.value.units(ref.build).unit
|
val unit = loadedBuild.value.units(ref.build).unit
|
||||||
val converter = unit.converter
|
val converter = unit.converter
|
||||||
val pluginClasspath = unit.plugins.pluginData.dependencyClasspath.toVector
|
val pluginData = unit.plugins.pluginData
|
||||||
|
val pluginInternalCp = pluginData.internalDependencyClasspath.toVector
|
||||||
|
val pluginClasspath = pluginData.dependencyClasspath.toVector
|
||||||
|
val cp = pluginClasspath.diff(pluginInternalCp)
|
||||||
// Exclude directories: an approximation to whether they've been published
|
// Exclude directories: an approximation to whether they've been published
|
||||||
// Note: it might be a redundant legacy from sbt 0.13/1.x times where the classpath contained directories
|
// Note: it might be a redundant legacy from sbt 0.13/1.x times where the classpath contained directories
|
||||||
// but it's left just in case
|
// but it's left just in case
|
||||||
val pluginJars = pluginClasspath.filter: x =>
|
val pluginJars = cp.filter: x =>
|
||||||
!Files.isDirectory(converter.toPath(x.data))
|
!Files.isDirectory(converter.toPath(x.data))
|
||||||
val pluginIDs: Vector[ModuleID] = pluginJars.flatMap(_.get(moduleIDStr).map: str =>
|
val pluginIDs: Vector[ModuleID] = pluginJars.flatMap(_.get(moduleIDStr).map: str =>
|
||||||
moduleIdJsonKeyFormat.read(str))
|
moduleIdJsonKeyFormat.read(str))
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,10 @@ object EvaluateTaskConfig {
|
||||||
) extends EvaluateTaskConfig
|
) extends EvaluateTaskConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param internalDependencyClasspath internal classpath entries from the metabuild that are used to exclude
|
||||||
|
* them when resolving/retrieving classifiers for sbt.
|
||||||
|
*/
|
||||||
final case class PluginData(
|
final case class PluginData(
|
||||||
dependencyClasspath: Def.Classpath,
|
dependencyClasspath: Def.Classpath,
|
||||||
definitionClasspath: Def.Classpath,
|
definitionClasspath: Def.Classpath,
|
||||||
|
|
@ -155,13 +159,28 @@ final case class PluginData(
|
||||||
managedSources: Seq[File],
|
managedSources: Seq[File],
|
||||||
buildTarget: Option[BuildTargetIdentifier],
|
buildTarget: Option[BuildTargetIdentifier],
|
||||||
converter: FileConverter,
|
converter: FileConverter,
|
||||||
|
internalDependencyClasspath: Def.Classpath,
|
||||||
) {
|
) {
|
||||||
val classpath: Def.Classpath = definitionClasspath ++ dependencyClasspath
|
val classpath: Def.Classpath = definitionClasspath ++ dependencyClasspath
|
||||||
}
|
}
|
||||||
|
|
||||||
object PluginData {
|
object PluginData {
|
||||||
private[sbt] def apply(dependencyClasspath: Def.Classpath, converter: FileConverter): PluginData =
|
private[sbt] def apply(dependencyClasspath: Def.Classpath, converter: FileConverter): PluginData =
|
||||||
PluginData(dependencyClasspath, Nil, None, None, Nil, Nil, Nil, Nil, Nil, Nil, None, converter)
|
PluginData(
|
||||||
|
dependencyClasspath,
|
||||||
|
Nil,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Nil,
|
||||||
|
Nil,
|
||||||
|
Nil,
|
||||||
|
Nil,
|
||||||
|
Nil,
|
||||||
|
Nil,
|
||||||
|
None,
|
||||||
|
converter,
|
||||||
|
Nil
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object EvaluateTask {
|
object EvaluateTask {
|
||||||
|
|
|
||||||
|
|
@ -1381,6 +1381,7 @@ private[sbt] object Load {
|
||||||
isMetaBuild :== true,
|
isMetaBuild :== true,
|
||||||
pluginData := Def.uncached {
|
pluginData := Def.uncached {
|
||||||
val prod = (Configurations.Runtime / exportedProducts).value
|
val prod = (Configurations.Runtime / exportedProducts).value
|
||||||
|
val internalCp = (Configurations.Runtime / internalDependencyClasspath).value
|
||||||
val cp = (Configurations.Runtime / fullClasspath).value
|
val cp = (Configurations.Runtime / fullClasspath).value
|
||||||
val opts = (Configurations.Compile / scalacOptions).value
|
val opts = (Configurations.Compile / scalacOptions).value
|
||||||
val javaOpts = (Configurations.Compile / javacOptions).value
|
val javaOpts = (Configurations.Compile / javacOptions).value
|
||||||
|
|
@ -1403,6 +1404,7 @@ private[sbt] object Load {
|
||||||
managedSrcs,
|
managedSrcs,
|
||||||
Some(buildTarget),
|
Some(buildTarget),
|
||||||
converter,
|
converter,
|
||||||
|
internalCp,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onLoadMessage := ("loading project definition from " + baseDirectory.value)
|
onLoadMessage := ("loading project definition from " + baseDirectory.value)
|
||||||
|
|
@ -1670,6 +1672,7 @@ final case class LoadBuildConfiguration(
|
||||||
Nil,
|
Nil,
|
||||||
None,
|
None,
|
||||||
converter,
|
converter,
|
||||||
|
Nil
|
||||||
)
|
)
|
||||||
case None => PluginData(globalPluginClasspath, converter)
|
case None => PluginData(globalPluginClasspath, converter)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
// Verify that local plugins work
|
||||||
|
TaskKey[Unit]("checkLocalPlugins") := Def.uncached {
|
||||||
|
val localResult = localPluginCheck.value
|
||||||
|
val customResult = customPluginCheck.value
|
||||||
|
assert(localResult == "local-plugin-active", s"Expected local plugin to be active, got: $localResult")
|
||||||
|
assert(customResult == "custom plugin", s"Expected custom plugin to be active, got: $customResult")
|
||||||
|
},
|
||||||
|
|
||||||
|
// Verify that the dependencies in updateSbtClassifiers / classifiersModule do not include the local plugins but do include
|
||||||
|
// other declared dependencies
|
||||||
|
TaskKey[Unit]("checkClassifiersModule") := Def.uncached {
|
||||||
|
val mod = (updateSbtClassifiers / classifiersModule).value
|
||||||
|
val deps = mod.dependencies
|
||||||
|
val actual = deps.map(m => s"${m.organization}:${m.name}").sorted.toSet
|
||||||
|
|
||||||
|
val expected = Set(
|
||||||
|
"org.scala-sbt:sbt",
|
||||||
|
"junit:junit",
|
||||||
|
"com.eed3si9n:sbt-buildinfo_sbt2_3",
|
||||||
|
"org.hamcrest:hamcrest-core",
|
||||||
|
"com.eed3si9n.manifesto:manifesto_3",
|
||||||
|
"org.scala-lang:scala3-library_3",
|
||||||
|
"org.scala-lang:scala-library",
|
||||||
|
"org.typelevel:cats-core_3",
|
||||||
|
"org.typelevel:cats-kernel_3"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert(
|
||||||
|
actual == expected,
|
||||||
|
s"""
|
||||||
|
|ClassifiersModule dependencies mismatch.
|
||||||
|
|Expected: ${expected.mkString(", ")}
|
||||||
|
|Actual: ${actual.mkString(", ")}
|
||||||
|
""".stripMargin
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import sbt.*
|
||||||
|
import sbt.Keys.*
|
||||||
|
|
||||||
|
object LocalPlugin extends AutoPlugin {
|
||||||
|
override def requires: Plugins = plugins.JvmPlugin
|
||||||
|
override def trigger: PluginTrigger = allRequirements
|
||||||
|
|
||||||
|
object autoImport {
|
||||||
|
val localPluginCheck = taskKey[String]("A task provided by the local plugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
import autoImport.*
|
||||||
|
|
||||||
|
override lazy val projectSettings: Seq[Setting[?]] = Seq(
|
||||||
|
localPluginCheck := "local-plugin-active"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
lazy val meta = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
// Just to make the test more comprehensive and check whether the additional libraries/plugins
|
||||||
|
// are present in updateSbtClassifiers/classifiersModule.
|
||||||
|
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1"),
|
||||||
|
libraryDependencies += "junit" % "junit" % "4.13.2"
|
||||||
|
)
|
||||||
|
.dependsOn(customPlugin)
|
||||||
|
|
||||||
|
lazy val customPlugin = (project in file("custom"))
|
||||||
|
.enablePlugins(SbtPlugin)
|
||||||
|
.settings(
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
"org.typelevel" %% "cats-core" % "2.13.0",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import sbt.*
|
||||||
|
import sbt.Keys.*
|
||||||
|
|
||||||
|
object CustomPlugin extends AutoPlugin {
|
||||||
|
override def requires: Plugins = plugins.JvmPlugin
|
||||||
|
override def trigger: PluginTrigger = allRequirements
|
||||||
|
|
||||||
|
object autoImport {
|
||||||
|
val customPluginCheck = taskKey[String]("A task provided by the custom plugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
import autoImport.*
|
||||||
|
|
||||||
|
override lazy val projectSettings: Seq[Setting[?]] = Seq(
|
||||||
|
customPluginCheck := {
|
||||||
|
import cats.implicits.*
|
||||||
|
List("custom", " ", "plugin").combineAll
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Verify the local plugins are loaded and active
|
||||||
|
> checkLocalPlugins
|
||||||
|
|
||||||
|
# Verify the local plugins are not included in the classifiersModule dependencies
|
||||||
|
> checkClassifiersModule
|
||||||
|
|
||||||
|
# Also verify updateSbtClassifiers itself succeeds
|
||||||
|
> updateSbtClassifiers
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
// Inject a non-existent module into the classifiers module dependencies
|
||||||
|
// to simulate a scenario where classifier artifacts can't be downloaded.
|
||||||
|
// With missingOk=true, updateSbtClassifiers should still succeed.
|
||||||
|
updateSbtClassifiers / classifiersModule := {
|
||||||
|
val mod = (updateSbtClassifiers / classifiersModule).value
|
||||||
|
val fakeModule = "com.example.nonexistent" % "fake-library" % "0.0.1"
|
||||||
|
mod.withDependencies(mod.dependencies :+ fakeModule)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1")
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
> updateSbtClassifiers
|
||||||
Loading…
Reference in New Issue