From 9352e1cdad8b045d44d032fe21012d1a8b6b6d6a Mon Sep 17 00:00:00 2001 From: Dmitrii Naumenko Date: Wed, 29 Jan 2025 14:25:19 +0100 Subject: [PATCH] [2.x] fix: updateSbtClassifiers task fails with error (#8022) In `classifiersModuleTask` we now don't include the full plugin classpath, but include only the dependency classpath (effectively excluding sbt.PluginData.definitionClasspath). Only items from the dependency classpath are considered to be published. Only for them we can download classifier artifacts later in the `updateSbtClassifiers` pipeline. This also fixes integration test "dependency-management/update-sbt-classifiers". I also made the test stricter, it now tests the module ids that are included in the sbt classpath. --- main/src/main/scala/sbt/Defaults.scala | 10 ++- .../update-sbt-classifiers/build.sbt | 86 ++++++++++++++++++- .../update-sbt-classifiers/pending | 1 - .../update-sbt-classifiers/project/build.sbt | 4 + .../update-sbt-classifiers/test | 4 + 5 files changed, 98 insertions(+), 7 deletions(-) delete mode 100644 sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/pending create mode 100644 sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/project/build.sbt create mode 100644 sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index c09f3abad..915d4525d 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -3714,17 +3714,21 @@ object Classpaths { val ref = thisProjectRef.value val unit = loadedBuild.value.units(ref.build).unit val converter = unit.converter - val pluginClasspath = unit.plugins.fullClasspath.toVector + val pluginClasspath = unit.plugins.pluginData.dependencyClasspath.toVector + // 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 + // but it's left jsut in case val pluginJars = pluginClasspath.filter: x => !Files.isDirectory(converter.toPath(x.data)) - // exclude directories: an approximation to whether they've been published val pluginIDs: Vector[ModuleID] = pluginJars.flatMap(_.get(moduleIDStr).map: str => moduleIdJsonKeyFormat.read(str)) + + val dependencies = sbtDependency.value +: pluginIDs GetClassifiersModule( projectID.value, // TODO: Should it be sbt's scalaModuleInfo? scalaModuleInfo.value, - sbtDependency.value +: pluginIDs, + dependencies, // sbt is now on Maven Central, so this has changed from sbt 0.13. Vector(Configurations.Default) ++ Configurations.default, classifiers.toVector diff --git a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt index 4593d4710..83086b815 100644 --- a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt +++ b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt @@ -1,5 +1,3 @@ -ThisBuild / scalaVersion := "2.11.12" - ivyConfiguration := { throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / ivyConfiguration") } @@ -8,5 +6,87 @@ dependencyResolution := { throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / dependencyResolution") } -scalaOrganization := "doesnt.exist" +lazy val root = (project in file(".")) + .settings( + scalaVersion := "2.11.12", + scalaOrganization := "doesnt.exist", + name := "myProjectName", + TaskKey[Unit]("checkModuleIdsInUpdateSbtClassifiers") := { + val updateReport = updateSbtClassifiers.value + val moduleReports = updateReport.configurations.find(_.configuration.name == "default").get.modules + + // Calling "distinct" as there are different entries for sources and javadoc classifiers with same module + val moduleIds = moduleReports.map(_.module).distinct + val moduleIdsShort = moduleIds.map(m => s"${m.organization}:${m.name}") + + val expectedModuleIds = Seq( + "com.eed3si9n:gigahorse-apache-http_3", + "com.eed3si9n:gigahorse-core_3", + "com.eed3si9n:shaded-apache-httpasyncclient", + "com.eed3si9n:shaded-jawn-parser_3", + "com.eed3si9n:shaded-scalajson_3", + "com.eed3si9n:sjson-new-core_3", + "com.eed3si9n:sjson-new-murmurhash_3", + "com.eed3si9n:sjson-new-scalajson_3", + "com.github.ben-manes.caffeine:caffeine", + "com.github.mwiede:jsch", + "com.google.errorprone:error_prone_annotations", + "com.lmax:disruptor", + "com.swoval:file-tree-views", + "com.typesafe:config", + "com.typesafe:ssl-config-core_3", + "net.java.dev.jna:jna", + "net.java.dev.jna:jna-platform", + "net.openhft:zero-allocation-hashing", + "org.apache.logging.log4j:log4j-api", + "org.apache.logging.log4j:log4j-core", + "org.apache.logging.log4j:log4j-slf4j-impl", + "org.checkerframework:checker-qual", + "org.fusesource.jansi:jansi", + "org.jline:jline-builtins", + "org.jline:jline-native", + "org.jline:jline-reader", + "org.jline:jline-style", + "org.jline:jline-terminal", + "org.jline:jline-terminal-jni", + "org.reactivestreams:reactive-streams", + "org.scala-lang.modules:scala-asm", + "org.scala-lang.modules:scala-parallel-collections_3", + "org.scala-lang.modules:scala-parser-combinators_3", + "org.scala-lang.modules:scala-xml_3", + "org.scala-lang:scala-library", + "org.scala-lang:scala-reflect", + "org.scala-lang:scala3-compiler_3", + "org.scala-lang:scala3-interfaces", + "org.scala-lang:scala3-library_3", + "org.scala-lang:tasty-core_3", + "org.scala-sbt.ipcsocket:ipcsocket", + "org.scala-sbt.ivy:ivy", + "org.scala-sbt.jline:jline", + "org.scala-sbt:compiler-interface", + "org.scala-sbt:io_3", + "org.scala-sbt:launcher-interface", + "org.scala-sbt:sbinary_3", + "org.scala-sbt:template-resolver", + "org.scala-sbt:test-interface", + "org.scala-sbt:zinc-apiinfo_3", + "org.scala-sbt:zinc-classfile_3", + "org.scala-sbt:zinc-classpath_3", + "org.scala-sbt:zinc-compile-core_3", + "org.scala-sbt:zinc-core_3", + "org.scala-sbt:zinc-persist_3", + "org.scala-sbt:zinc_3", + "org.slf4j:slf4j-api", + ) + def assertCollectionsEqual(message: String, expected: Seq[String], actual: Seq[String]): Unit = + // using the new line for a more readable comparison failure output + org.junit.Assert.assertEquals(message: String, expected.mkString("\n"), actual.mkString("\n")) + + assertCollectionsEqual( + "Unexpected module ids in updateSbtClassifiers", + expectedModuleIds.sorted, + moduleIdsShort.sorted, + ) + } + ) \ No newline at end of file diff --git a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/pending b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/pending deleted file mode 100644 index 00ad751bf..000000000 --- a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/pending +++ /dev/null @@ -1 +0,0 @@ -> updateSbtClassifiers diff --git a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/project/build.sbt b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/project/build.sbt new file mode 100644 index 000000000..c5424bcc7 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/project/build.sbt @@ -0,0 +1,4 @@ +// The library surves two purposes: +// 1. add some non-standard library to the meta-build classpath to later check that it's included into updateSbtClassifiers +// 2. use assertions from junit in custom assertion in `build.sbt` of current scripted test +libraryDependencies += "junit" % "junit" % "4.13.2" \ No newline at end of file diff --git a/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/test b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/test new file mode 100644 index 000000000..7a2951b5e --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/update-sbt-classifiers/test @@ -0,0 +1,4 @@ +> updateSbtClassifiers + +# see assertion definition in build.sbt +> checkModuleIdsInUpdateSbtClassifiers \ No newline at end of file