From c1b289c93441a92ccb3eed62aaefcacc2ac99b22 Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Mon, 13 Jul 2026 11:25:40 +0900 Subject: [PATCH] [2.0.x] fix sjson downgrade (#9426) Extend metabuild exclusion to all sbt-provided deps. --- main/src/main/scala/sbt/Defaults.scala | 8 ++- .../i8207-sjson-new-downgrade/build.sbt | 69 +++++++++++++++++++ .../project/Example.scala | 6 ++ .../project/plugins.sbt | 1 + .../project/i8207-sjson-new-downgrade/test | 10 +++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/build.sbt create mode 100644 sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/Example.scala create mode 100644 sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/plugins.sbt create mode 100644 sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index c57c9598b..1b3e823c4 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -3603,7 +3603,13 @@ object Classpaths { o %% "librarymanagement-ivy", o %% "util-logging", o %% "util-position", - o %% "io" + o %% "io", + "com.eed3si9n" %% "sjson-new-core", + "com.eed3si9n" %% "gigahorse-core", + "com.typesafe" %% "ssl-config-core", + "org.reactivestreams" % "reactive-streams", + "org.slf4j" % "slf4j-api", + "com.typesafe" % "config", ) if (isMeta && !force) excludes.toVector ++ sbtModulesExcludes else excludes diff --git a/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/build.sbt b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/build.sbt new file mode 100644 index 000000000..e2734d0de --- /dev/null +++ b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/build.sbt @@ -0,0 +1,69 @@ +ThisBuild / scalaVersion := "3.8.4" +ThisBuild / organization := "com.example" + +libraryDependencies += "com.typesafe" % "config" % "1.4.5" + +val checkMetabuildClasspath = taskKey[Unit]("Checks the effective metabuild classpath") +val checkProjectClasspath = taskKey[Unit]("Checks the project classpath") + +checkMetabuildClasspath := Def.uncached { + val buildUnit = loadedBuild.value.units(thisProjectRef.value.build).unit + val classpath = buildUnit.plugins.pluginData.dependencyClasspath + val managedModules = classpath + .flatMap(_.get(Keys.moduleIDStr)) + .map(Classpaths.moduleIdJsonKeyFormat.read) + .map(module => module.organization -> module.name) + .toSet + val launcherOwnedModules = Set( + "com.eed3si9n" -> "sjson-new-core_3", + "com.eed3si9n" -> "gigahorse-core_3", + "com.typesafe" -> "ssl-config-core_3", + "org.reactivestreams" -> "reactive-streams", + "org.slf4j" -> "slf4j-api", + "com.typesafe" -> "config", + ) + val pluginModules = Set( + "ch.epfl.scala" -> "sbt-github-dependency-submission_sbt2_3", + "com.eed3si9n" -> "gigahorse-asynchttpclient_3", + "com.eed3si9n" -> "shaded-asynchttpclient", + ) + val converter = buildUnit.converter + val launcherJars = classpath + .filter(_.get(Keys.moduleIDStr).isEmpty) + .map(entry => converter.toPath(entry.data).getFileName.toString) + val launcherJarNames = Set( + "sjson-new-core_3", + "gigahorse-core_3", + "ssl-config-core_3", + "reactive-streams", + "slf4j-api", + "config", + ) + + assert( + managedModules.intersect(launcherOwnedModules).isEmpty, + s"found plugin-managed sbt modules: ${managedModules.intersect(launcherOwnedModules)}", + ) + assert( + pluginModules.subsetOf(managedModules), + s"missing plugin modules: ${pluginModules.diff(managedModules)}", + ) + assert( + launcherJarNames.forall(name => launcherJars.count(_.startsWith(s"$name-")) == 1), + s"expected one launcher jar for each sbt module: $launcherJars", + ) +} + +checkProjectClasspath := Def.uncached { + val modules = (Compile / externalDependencyClasspath).value + .flatMap(_.get(Keys.moduleIDStr)) + .map(Classpaths.moduleIdJsonKeyFormat.read) + assert( + modules.exists(module => + module.organization == "com.typesafe" && + module.name == "config" && + module.revision == "1.4.5" + ), + s"missing project dependency: $modules", + ) +} diff --git a/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/Example.scala b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/Example.scala new file mode 100644 index 000000000..6adfcfc9f --- /dev/null +++ b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/Example.scala @@ -0,0 +1,6 @@ +import sbt.* +import sbt.Keys.* + +object Example { + lazy val settings = Seq(javaOptions += "-Dfoo=bar") +} diff --git a/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/plugins.sbt b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/plugins.sbt new file mode 100644 index 000000000..3ae2b253a --- /dev/null +++ b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.scala" % "sbt-github-dependency-submission" % "3.2.3") diff --git a/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/test b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/test new file mode 100644 index 000000000..0fcd00471 --- /dev/null +++ b/sbt-app/src/sbt-test/project/i8207-sjson-new-downgrade/test @@ -0,0 +1,10 @@ +# Issue 8207: a metabuild plugin must not downgrade sjson-new core. +# Loading this build exercises the metabuild compile, which summons +# the JsonFormat for String via the caching macro on javaOptions. +# When the plugin downgrades sjson-new core on the metabuild +# classpath, project load fails with a missing given. A successful +# load is the regression assertion. +> projects +> checkMetabuildClasspath +> checkProjectClasspath +> githubGenerateSnapshot {}