From 08469d8b8ce3ff17120e22f18b5bb40f00643d36 Mon Sep 17 00:00:00 2001 From: MkDev11 Date: Sun, 11 Jan 2026 04:17:24 -0800 Subject: [PATCH] [2.x] fix: Upgrade launcher-package to sbt 1.10.7 and replace dispatch-http (#8465) Fixes #7826 Changes: - Upgrade sbt version from 0.13.18 to 1.10.7 in launcher-package/project/build.properties - Remove dead dispatch-http 0.8.10 dependency from plugins.sbt - Update sbt-native-packager from 1.7.6 to 1.10.4 (com.github.sbt) - Update sbt-pgp from 2.1.2 to 2.3.1 - Replace all dispatch.classic._ HTTP calls with Java URL.openStream() The dispatch-http library is dead and doesn't support sbt 1.x. This change uses standard Java networking APIs for HTTP downloads, eliminating the dependency on outdated libraries. All HTTP download operations now use: - java.net.URL.openConnection() - InputStream with buffered reading - Proper resource cleanup with try-finally blocks - Removes the sbt-export-repo plugin dependency - Defines exportRepo and exportRepoDirectory settings locally - Removes ExportRepoPlugin from dist project - Fixes exportRepo task to not reference itself * fix: Update PackageSignerPlugin.scala for sbt 1.x compatibility - Use withExtension instead of copy(extension = ...) for Artifact - Update Classpaths.publishConfig to use sbt 1.x signature with all required parameters - Use new slash syntax for scoped keys (pgpSigner / skip instead of skip in pgpSigner) * fix: Use computed status instead of status key in PackageSignerPlugin * fix: Use withRevision instead of copy for ModuleID in build.sbt - Add scala.sys.process._ import for shell command execution (! method) - Fix resolvers setting to use new slash syntax and proper Option handling - Fix publish/publishLocal to use {} instead of () to avoid deprecation warning - Fix Classpaths.publishTask to use variant without delivery key (deprecated since 1.1.1) - Add scala.sys.process._ import for shell command execution - Fix publish/publishLocal to use {} instead of () - Remove problematic resolvers setting that caused task/setting dependency issues - Use IvyActions.publish directly instead of deprecated Classpaths.publishTask - Fix ModuleID.copy to use withRevision - Fix Artifact.copy to use withExtension - Use computed status value instead of status key Build now compiles successfully with sbt 1.10.7. --- launcher-package/build.sbt | 135 +++++++++++++----- .../project/PackageSignerPlugin.scala | 47 ++++-- launcher-package/project/build.properties | 2 +- launcher-package/project/plugins.sbt | 6 +- 4 files changed, 138 insertions(+), 52 deletions(-) diff --git a/launcher-package/build.sbt b/launcher-package/build.sbt index 53e00cb55..cfefbf7da 100755 --- a/launcher-package/build.sbt +++ b/launcher-package/build.sbt @@ -1,4 +1,5 @@ import scala.util.control.Exception.catching +import scala.sys.process._ import NativePackagerHelper._ import com.typesafe.sbt.packager.SettingsHelper._ import DebianConstants._ @@ -69,6 +70,8 @@ val debianBuildId = settingKey[Int]("build id for Debian") val exportRepoUsingCoursier = taskKey[File]("export Maven style repository") val exportRepoCsrDirectory = settingKey[File]("") +val exportRepo = taskKey[File]("export Ivy style repository") +val exportRepoDirectory = settingKey[File]("directory for exported repository") val universalMacPlatform = "universal-apple-darwin" val x86LinuxPlatform = "x86_64-pc-linux" @@ -109,13 +112,24 @@ val root = (project in file(".")). sbtLaunchJar := { val uri = sbtLaunchJarUrl.value val file = sbtLaunchJarLocation.value - import dispatch.classic._ if(!file.exists) { // oddly, some places require us to create the file before writing... IO.touch(file) + val url = new java.net.URL(uri) + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(file)) - try Http(url(uri) >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } } // TODO - GPG Trust validation. file @@ -135,12 +149,23 @@ val root = (project in file(".")). val linuxX86Tar = t / linuxX86ImageTar val linuxAarch64Tar = t / linuxAarch64ImageTar val windowsZip = t / windowsImageZip - import dispatch.classic._ if(!macosUniversalTar.exists && !isWindows && sbtIncludeSbtn) { IO.touch(macosUniversalTar) + val url = new java.net.URL(s"$baseUrl/v$v/$macosUniversalImageTar") + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(macosUniversalTar)) - try Http(url(s"$baseUrl/v$v/$macosUniversalImageTar") >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } val platformDir = t / universalMacPlatform IO.createDirectory(platformDir) s"tar zxvf $macosUniversalTar --directory $platformDir".! @@ -148,9 +173,21 @@ val root = (project in file(".")). } if(!linuxX86Tar.exists && !isWindows && sbtIncludeSbtn) { IO.touch(linuxX86Tar) + val url = new java.net.URL(s"$baseUrl/v$v/$linuxX86ImageTar") + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxX86Tar)) - try Http(url(s"$baseUrl/v$v/$linuxX86ImageTar") >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } val platformDir = t / x86LinuxPlatform IO.createDirectory(platformDir) s"""tar zxvf $linuxX86Tar --directory $platformDir""".! @@ -158,9 +195,21 @@ val root = (project in file(".")). } if(!linuxAarch64Tar.exists && !isWindows && sbtIncludeSbtn) { IO.touch(linuxAarch64Tar) + val url = new java.net.URL(s"$baseUrl/v$v/$linuxAarch64ImageTar") + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxAarch64Tar)) - try Http(url(s"$baseUrl/v$v/$linuxAarch64ImageTar") >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } val platformDir = t / aarch64LinuxPlatform IO.createDirectory(platformDir) s"""tar zxvf $linuxAarch64Tar --directory $platformDir""".! @@ -168,9 +217,21 @@ val root = (project in file(".")). } if(!windowsZip.exists && sbtIncludeSbtn) { IO.touch(windowsZip) + val url = new java.net.URL(s"$baseUrl/v$v/$windowsImageZip") + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(windowsZip)) - try Http(url(s"$baseUrl/v$v/$windowsImageZip") >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } val platformDir = t / x86WindowsPlatform IO.unzip(windowsZip, platformDir) IO.move(platformDir / "sbtn.exe", t / x86WindowsImageName) @@ -336,22 +397,22 @@ val root = (project in file(".")). else Seq[(File, String)](base.getParentFile / "LICENSE" -> "LICENSE", base / "NOTICE" -> "NOTICE") }, - // Misccelaneous publishing stuff... - projectID in Debian := { + // Miscellaneous publishing stuff... + (Debian / projectID) := { val m = moduleID.value - m.copy(revision = (version in Debian).value) + m.withRevision((Debian / version).value) }, - projectID in Windows := { + (Windows / projectID) := { val m = moduleID.value - m.copy(revision = (version in Windows).value) + m.withRevision((Windows / version).value) }, - projectID in Rpm := { + (Rpm / projectID) := { val m = moduleID.value - m.copy(revision = (version in Rpm).value) + m.withRevision((Rpm / version).value) }, - projectID in Universal := { + (Universal / projectID) := { val m = moduleID.value - m.copy(revision = (version in Universal).value) + m.withRevision((Universal / version).value) } ) @@ -406,9 +467,7 @@ def makePublishToForConfig(config: Configuration) = { val resolver = Resolver.url(id, new URL(url))(Patterns(pattern)) Some(resolver) } - )) ++ Seq( - resolvers ++= ((publishTo in config) apply (_.toSeq)).value - ) + )) } def publishToSettings = @@ -416,19 +475,29 @@ def publishToSettings = def downloadUrl(uri: URI, out: File): Unit = { - import dispatch.classic._ if(!out.exists) { IO.touch(out) + val url = new java.net.URL(uri.toString) + val connection = url.openConnection() + val input = connection.getInputStream val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(out)) - try Http(url(uri.toString) >>> writer) - finally writer.close() + try { + val buffer = new Array[Byte](8192) + var bytesRead = input.read(buffer) + while (bytesRead != -1) { + writer.write(buffer, 0, bytesRead) + bytesRead = input.read(buffer) + } + } finally { + input.close() + writer.close() + } } } def colonName(m: ModuleID): String = s"${m.organization}:${m.name}:${m.revision}" lazy val dist = (project in file("dist")) - .enablePlugins(ExportRepoPlugin) .settings( name := "dist", scalaVersion := { @@ -437,19 +506,19 @@ lazy val dist = (project in file("dist")) }, libraryDependencies ++= Seq(sbtActual, jansi, scala212Compiler, scala212Jline, scala212Xml) ++ sbt013ExtraDeps, exportRepo := { - val old = exportRepo.value + val outDir = exportRepoDirectory.value sbtVersionToRelease match { case v if v.startsWith("1.") => sys.error("sbt 1.x should use coursier") case v if v.startsWith("0.13.") => - val outbase = exportRepoDirectory.value / "org.scala-sbt" / "compiler-interface" / v + val outbase = outDir / "org.scala-sbt" / "compiler-interface" / v val uribase = s"https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/$v/" downloadUrl(uri(uribase + "ivys/ivy.xml"), outbase / "ivys" / "ivy.xml") downloadUrl(uri(uribase + "jars/compiler-interface.jar"), outbase / "jars" / "compiler-interface.jar") downloadUrl(uri(uribase + "srcs/compiler-interface-sources.jar"), outbase / "srcs" / "compiler-interface-sources.jar") case _ => } - old + outDir }, exportRepoDirectory := target.value / "lib" / "local-preloaded", exportRepoCsrDirectory := exportRepoDirectory.value, @@ -481,7 +550,7 @@ lazy val dist = (project in file("dist")) outDirectory }, conflictWarning := ConflictWarning.disable, - publish := (), - publishLocal := (), + publish := {}, + publishLocal := {}, resolvers += Resolver.typesafeIvyRepo("releases") ) diff --git a/launcher-package/project/PackageSignerPlugin.scala b/launcher-package/project/PackageSignerPlugin.scala index c81401872..c819dff6c 100644 --- a/launcher-package/project/PackageSignerPlugin.scala +++ b/launcher-package/project/PackageSignerPlugin.scala @@ -1,5 +1,6 @@ import sbt._ import Keys._ +import sbt.internal.librarymanagement.IvyActions import com.jsuereth.sbtpgp.SbtPgp import com.typesafe.sbt.packager.universal.{ UniversalPlugin, UniversalDeployPlugin } import com.typesafe.sbt.packager.debian.{ DebianPlugin, DebianDeployPlugin } @@ -21,13 +22,13 @@ object PackageSignerPlugin extends sbt.AutoPlugin { inConfig(Rpm)(packageSignerSettings) def subExtension(art: Artifact, ext: String): Artifact = - art.copy(extension = ext) + art.withExtension(ext) def packageSignerSettings: Seq[Setting[_]] = Seq( signedArtifacts := { val artifacts = packagedArtifacts.value val r = pgpSigner.value - val skipZ = (skip in pgpSigner).value + val skipZ = (pgpSigner / skip).value val s = streams.value if (!skipZ) { artifacts flatMap { case (art, f) => @@ -39,21 +40,39 @@ object PackageSignerPlugin extends sbt.AutoPlugin { else artifacts }, publishSignedConfiguration := Classpaths.publishConfig( - signedArtifacts.value, - None, + publishMavenStyle = publishMavenStyle.value, + deliverIvyPattern = (Compile / packageBin / artifactPath).value.getParent + "/[artifact]-[revision](-[classifier]).[ext]", + status = if (isSnapshot.value) "integration" else "release", + configurations = Vector.empty, + artifacts = signedArtifacts.value.toVector, + checksums = (publish / checksums).value.toVector, resolverName = Classpaths.getPublishTo(publishTo.value).name, - checksums = (checksums in publish).value, - logging = ivyLoggingLevel.value, - overwrite = isSnapshot.value), + logging = ivyLoggingLevel.value, + overwrite = isSnapshot.value), publishLocalSignedConfiguration := Classpaths.publishConfig( - signedArtifacts.value, - None, + publishMavenStyle = publishMavenStyle.value, + deliverIvyPattern = (Compile / packageBin / artifactPath).value.getParent + "/[artifact]-[revision](-[classifier]).[ext]", + status = if (isSnapshot.value) "integration" else "release", + configurations = Vector.empty, + artifacts = signedArtifacts.value.toVector, + checksums = (publish / checksums).value.toVector, resolverName = "local", - checksums = (checksums in publish).value, - logging = ivyLoggingLevel.value, - overwrite = isSnapshot.value), - publishSigned := Classpaths.publishTask(publishSignedConfiguration, deliver).value, - publishLocalSigned := Classpaths.publishTask(publishLocalSignedConfiguration, deliver).value + logging = ivyLoggingLevel.value, + overwrite = isSnapshot.value), + publishSigned := Def.taskDyn { + val config = publishSignedConfiguration.value + val s = streams.value + Def.task { + IvyActions.publish(ivyModule.value, config, s.log) + } + }.value, + publishLocalSigned := Def.taskDyn { + val config = publishLocalSignedConfiguration.value + val s = streams.value + Def.task { + IvyActions.publish(ivyModule.value, config, s.log) + } + }.value ) } diff --git a/launcher-package/project/build.properties b/launcher-package/project/build.properties index 8e682c526..73df629ac 100644 --- a/launcher-package/project/build.properties +++ b/launcher-package/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.18 +sbt.version=1.10.7 diff --git a/launcher-package/project/plugins.sbt b/launcher-package/project/plugins.sbt index e4069706c..10a9e1796 100644 --- a/launcher-package/project/plugins.sbt +++ b/launcher-package/project/plugins.sbt @@ -1,4 +1,2 @@ -addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.7.6") -libraryDependencies += "net.databinder" %% "dispatch-http" % "0.8.10" -addSbtPlugin("com.eed3si9n" % "sbt-export-repo" % "0.1.1") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")