From 280d3054fe1f6ffb0bf3fc253f3cd1ed1f6a4d0a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 9 Nov 2024 14:57:27 -0500 Subject: [PATCH] Cross build to sbt 2.x --- build.sbt | 10 +- .../com/typesafe/sbt/packager/Compat.scala | 0 .../typesafe/sbt/packager/PluginCompat.scala | 26 ++++ .../com/typesafe/sbt/packager/Compat.scala | 3 + .../typesafe/sbt/packager/PluginCompat.scala | 56 ++++++++ .../com/typesafe/sbt/packager/Compat.scala | 50 ------- .../sbt/packager/MappingsHelper.scala | 130 ------------------ .../sbt/packager/SettingsHelper.scala | 90 ------------ .../com/typesafe/sbt/PackagerPlugin.scala | 24 ++-- .../sbt/packager/MappingsHelper.scala | 36 +++-- .../sbt/packager/SettingsHelper.scala | 28 ++-- .../com/typesafe/sbt/packager/Stager.scala | 21 ++- .../sbt/packager/archetypes/JavaAppKeys.scala | 15 +- .../archetypes/JavaAppPackaging.scala | 87 +++++++----- .../archetypes/JavaServerApplication.scala | 12 +- .../packager/archetypes/TemplateWriter.scala | 2 +- .../archetypes/jlink/JlinkPlugin.scala | 18 ++- .../scripts/ApplicationIniGenerator.scala | 11 +- .../scripts/BashStartScriptKeys.scala | 5 +- .../scripts/BashStartScriptPlugin.scala | 23 ++-- .../scripts/BatStartScriptKeys.scala | 6 +- .../scripts/BatStartScriptPlugin.scala | 64 ++------- .../scripts/CommonStartScriptGenerator.scala | 36 +++-- .../systemloader/SystemdPlugin.scala | 3 +- .../systemloader/SystemloaderPlugin.scala | 4 +- .../archetypes/systemloader/package.scala | 4 +- .../debian/DebianNativePackaging.scala | 55 +++++--- .../sbt/packager/debian/DebianPlugin.scala | 26 +++- .../sbt/packager/debian/JDebPackaging.scala | 23 ++-- .../typesafe/sbt/packager/debian/Keys.scala | 8 +- .../sbt/packager/docker/DockerPlugin.scala | 60 ++++---- .../typesafe/sbt/packager/docker/Keys.scala | 4 +- .../sbt/packager/docker/LayeredMapping.scala | 5 +- .../sbt/packager/docker/dockerfile.scala | 2 +- .../GraalVMNativeImagePlugin.scala | 41 +++--- .../sbt/packager/jar/ClasspathJarPlugin.scala | 21 +-- .../sbt/packager/jar/LauncherJarPlugin.scala | 25 ++-- .../jdkpackager/JDKPackagerAntHelper.scala | 56 +++++--- .../jdkpackager/JDKPackagerPlugin.scala | 13 +- .../typesafe/sbt/packager/linux/Keys.scala | 7 +- .../sbt/packager/linux/LinuxMappingDSL.scala | 6 +- .../packager/linux/LinuxPackageMapping.scala | 4 +- .../sbt/packager/linux/LinuxPlugin.scala | 37 +++-- .../typesafe/sbt/packager/rpm/RpmHelper.scala | 26 ++-- .../sbt/packager/rpm/RpmMetadata.scala | 8 +- .../typesafe/sbt/packager/rpm/RpmPlugin.scala | 56 +++++--- .../sbt/packager/universal/Keys.scala | 9 +- .../packager/universal/UniversalPlugin.scala | 74 ++++++---- .../sbt/packager/validation/package.scala | 4 +- .../sbt/packager/windows/WindowsPlugin.scala | 30 ++-- .../sbt/packager/windows/WixHelper.scala | 4 +- .../jdkpackager/test-package-image/build.sbt | 12 +- .../src/main/scala/ExampleApp.scala | 2 +- .../test-package-mappings/build.sbt | 18 +-- .../src/main/scala/ExampleApp.scala | 2 +- .../test-package-minimal/build.sbt | 6 +- .../src/main/scala/ExampleApp.scala | 2 +- .../jlink/test-jlink-minimal/build.sbt | 6 +- src/sphinx/formats/jdkpackager.rst | 6 +- .../packager/universal/ZipHelperSpec.scala | 2 +- test-project-jdkpackager/build.sbt | 6 +- .../src/main/scala/ExampleApp.scala | 2 +- 62 files changed, 735 insertions(+), 697 deletions(-) rename src/main/{scala-sbt-1.0 => scala-2.12}/com/typesafe/sbt/packager/Compat.scala (100%) create mode 100644 src/main/scala-2.12/com/typesafe/sbt/packager/PluginCompat.scala create mode 100644 src/main/scala-3/com/typesafe/sbt/packager/Compat.scala create mode 100644 src/main/scala-3/com/typesafe/sbt/packager/PluginCompat.scala delete mode 100644 src/main/scala-sbt-0.13/com/typesafe/sbt/packager/Compat.scala delete mode 100644 src/main/scala-sbt-0.13/com/typesafe/sbt/packager/MappingsHelper.scala delete mode 100644 src/main/scala-sbt-0.13/com/typesafe/sbt/packager/SettingsHelper.scala rename src/main/{scala-sbt-1.0 => scala}/com/typesafe/sbt/packager/MappingsHelper.scala (69%) rename src/main/{scala-sbt-1.0 => scala}/com/typesafe/sbt/packager/SettingsHelper.scala (79%) diff --git a/build.sbt b/build.sbt index 705bc72df..7fe17071d 100644 --- a/build.sbt +++ b/build.sbt @@ -3,9 +3,12 @@ organization := "com.github.sbt" homepage := Some(url("https://github.com/sbt/sbt-native-packager")) Global / onChangedBuildSource := ReloadOnSourceChanges -Global / scalaVersion := "2.12.20" // crossBuildingSettings +lazy val scala212 = "2.12.20" +lazy val scala3 = "3.3.4" +Global / scalaVersion := scala3 +crossScalaVersions := Seq(scala3, scala212) (pluginCrossBuild / sbtVersion) := { scalaBinaryVersion.value match { case "2.12" => "1.1.6" @@ -48,8 +51,7 @@ libraryDependencies ++= { // scala version depended libraries libraryDependencies ++= { scalaBinaryVersion.value match { - case "2.10" => Nil - case _ => + case "2.12" => Seq( // Do NOT upgrade these dependencies to 2.x or newer! sbt-native-packager is a sbt-plugin // and gets published with Scala 2.12, therefore we need to stay at the same major version @@ -58,6 +60,8 @@ libraryDependencies ++= { "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2", // Do not upgrade beyond 1.x "org.scala-lang.modules" %% "scala-xml" % "2.2.0" ) + case _ => + Nil } } diff --git a/src/main/scala-sbt-1.0/com/typesafe/sbt/packager/Compat.scala b/src/main/scala-2.12/com/typesafe/sbt/packager/Compat.scala similarity index 100% rename from src/main/scala-sbt-1.0/com/typesafe/sbt/packager/Compat.scala rename to src/main/scala-2.12/com/typesafe/sbt/packager/Compat.scala diff --git a/src/main/scala-2.12/com/typesafe/sbt/packager/PluginCompat.scala b/src/main/scala-2.12/com/typesafe/sbt/packager/PluginCompat.scala new file mode 100644 index 000000000..87bee98e9 --- /dev/null +++ b/src/main/scala-2.12/com/typesafe/sbt/packager/PluginCompat.scala @@ -0,0 +1,26 @@ +package com.typesafe.sbt.packager + +import java.nio.file.{Path => NioPath} +import java.util.jar.Attributes +import sbt.* +import xsbti.{FileConverter, HashedVirtualFileRef, VirtualFile} + +private[packager] object PluginCompat { + type FileRef = java.io.File + type ArtifactPath = java.io.File + type Out = java.io.File + + def toNioPath(a: Attributed[File])(implicit conv: FileConverter): NioPath = + a.data.toPath() + def toFile(a: Attributed[File])(implicit conv: FileConverter): File = + a.data + def artifactPathToFile(ref: File)(implicit conv: FileConverter): File = + ref + def toNioPaths(cp: Seq[Attributed[File]])(implicit conv: FileConverter): Vector[NioPath] = + cp.map(_.data.toPath()).toVector + def toFiles(cp: Seq[Attributed[File]])(implicit conv: FileConverter): Vector[File] = + cp.map(_.data).toVector + + def classpathAttr = Attributes.Name.CLASS_PATH + def mainclassAttr = Attributes.Name.MAIN_CLASS +} diff --git a/src/main/scala-3/com/typesafe/sbt/packager/Compat.scala b/src/main/scala-3/com/typesafe/sbt/packager/Compat.scala new file mode 100644 index 000000000..9c148f0b4 --- /dev/null +++ b/src/main/scala-3/com/typesafe/sbt/packager/Compat.scala @@ -0,0 +1,3 @@ +package com.typesafe.sbt.packager + +object Compat {} diff --git a/src/main/scala-3/com/typesafe/sbt/packager/PluginCompat.scala b/src/main/scala-3/com/typesafe/sbt/packager/PluginCompat.scala new file mode 100644 index 000000000..cb3d1ac6e --- /dev/null +++ b/src/main/scala-3/com/typesafe/sbt/packager/PluginCompat.scala @@ -0,0 +1,56 @@ +package com.typesafe.sbt.packager + +import java.io.File +import java.nio.file.{ Path => NioPath } +import java.util.jar.Attributes +import sbt.* +import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFile, VirtualFileRef } +import sbt.internal.RemoteCache + +private[packager] object PluginCompat: + type FileRef = HashedVirtualFileRef + type ArtifactPath = VirtualFileRef + type Out = VirtualFile + type IncludeArtifact = Any => Boolean + + val artifactStr = Keys.artifactStr + val moduleIDStr = Keys.moduleIDStr + def parseModuleIDStrAttribute(str: String): ModuleID = + Classpaths.moduleIdJsonKeyFormat.read(str) + def moduleIDToStr(m: ModuleID): String = + Classpaths.moduleIdJsonKeyFormat.write(m) + + def parseArtifactStrAttribute(str: String): Artifact = + import sbt.librarymanagement.LibraryManagementCodec.ArtifactFormat + import sjsonnew.support.scalajson.unsafe.* + Converter.fromJsonUnsafe[Artifact](Parser.parseUnsafe(str)) + def artifactToStr(art: Artifact): String = + import sbt.librarymanagement.LibraryManagementCodec.ArtifactFormat + import sjsonnew.support.scalajson.unsafe.* + CompactPrinter(Converter.toJsonUnsafe(art)) + + def toNioPath(a: Attributed[HashedVirtualFileRef])(using conv: FileConverter): NioPath = + conv.toPath(a.data) + def toNioPath(ref: HashedVirtualFileRef)(using conv: FileConverter): NioPath = + conv.toPath(ref) + inline def toFile(a: Attributed[HashedVirtualFileRef])(using conv: FileConverter): File = + toNioPath(a).toFile() + inline def toFile(ref: HashedVirtualFileRef)(using conv: FileConverter): File = + toNioPath(ref).toFile() + def artifactPathToFile(ref: VirtualFileRef)(using conv: FileConverter): File = + conv.toPath(ref).toFile() + def toArtifactPath(f: File)(using conv: FileConverter): ArtifactPath = + conv.toVirtualFile(f.toPath()) + def toNioPaths(cp: Seq[Attributed[HashedVirtualFileRef]])(using conv: FileConverter): Vector[NioPath] = + cp.map(toNioPath).toVector + inline def toFiles(cp: Seq[Attributed[HashedVirtualFileRef]])(using conv: FileConverter): Vector[File] = + toNioPaths(cp).map(_.toFile()) + def toFileRef(x: File)(using conv: FileConverter): FileRef = + conv.toVirtualFile(x.toPath()) + def getName(ref: FileRef): String = + ref.name() + def getArtifactPathName(ref: ArtifactPath): String = + ref.name() + def classpathAttr: String = Attributes.Name.CLASS_PATH.toString() + def mainclassAttr: String = Attributes.Name.MAIN_CLASS.toString() +end PluginCompat diff --git a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/Compat.scala b/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/Compat.scala deleted file mode 100644 index 2f1cab8de..000000000 --- a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/Compat.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.typesafe.sbt.packager - -import sbt.{Artifact, BufferedLogger, FullLogger, Logger} - -import scala.sys.process.ProcessLogger - -object Compat { - - /** - * Used in: - * - * - [[com.typesafe.sbt.packager.windows.WindowsPlugin]] - * - [[com.typesafe.sbt.packager.rpm.RpmHelper]] - * - [[com.typesafe.sbt.packager.docker.DockerPlugin]] - * - [[com.typesafe.sbt.packager.debian.DebianNativePackaging]] - * - [[com.typesafe.sbt.packager.rpm.RpmPlugin]] - * - * @param log - * @return - * turns a Logger into a ProcessLogger - */ - implicit def log2ProcessLogger(log: Logger): sys.process.ProcessLogger = - new BufferedLogger(new FullLogger(log)) with sys.process.ProcessLogger { - def err(s: => String): Unit = error(s) - def out(s: => String): Unit = info(s) - } - - /** - * Used in - * - * - [[com.typesafe.sbt.packager.docker.DockerPlugin]] - * - * @param logger - * The sbt.ProcessLogger that should be wrapped - * @return - * A scala ProcessLogger - */ - implicit def sbtProcessLogger2ScalaProcessLogger(logger: sbt.ProcessLogger): sys.process.ProcessLogger = - ProcessLogger(msg => logger.info(msg), err => logger.error(err)) - - /** - * Use in the scripted `universal/multiproject-classifiers` test. - * @param artifact - * polyfill new methods - */ - implicit class CompatArtifact(artifact: Artifact) { - def withClassifier(classifier: Option[String]): Artifact = - artifact.copy(classifier = classifier) - } -} diff --git a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/MappingsHelper.scala b/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/MappingsHelper.scala deleted file mode 100644 index 636dc3126..000000000 --- a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/MappingsHelper.scala +++ /dev/null @@ -1,130 +0,0 @@ -package com.typesafe.sbt.packager - -import sbt._ - -/** A set of helper methods to simplify the writing of mappings */ -object MappingsHelper { - - /** - * return a Seq of mappings which effect is to add a whole directory in the generated package - * - * @example - * {{{ - * mappings in Universal ++= directory(baseDirectory.value / "extra") - * }}} - * - * @param sourceDir - * @return - * mappings - */ - def directory(sourceDir: File): Seq[(File, String)] = - Option(sourceDir.getParentFile) - .map(parent => sourceDir.*** pair relativeTo(parent)) - .getOrElse(sourceDir.*** pair basic) - - /** - * It lightens the build file if one wants to give a string instead of file. - * - * @example - * {{{ - * mappings in Universal ++= directory("extra") - * }}} - * - * @param sourceDir - * @return - * mappings - */ - def directory(sourceDir: String): Seq[(File, String)] = - directory(file(sourceDir)) - - /** - * return a Seq of mappings which effect is to add the content of directory in the generated package, excluding the - * directory itself. - * - * @example - * {{{ - * mappings in Universal ++= sourceDir(baseDirectory.value / "extra") - * }}} - * - * @param sourceDir - * @return - * mappings - */ - def contentOf(sourceDir: File): Seq[(File, String)] = - (sourceDir.*** --- sourceDir) pair relativeTo(sourceDir) - - /** - * It lightens the build file if one wants to give a string instead of file. - * - * @example - * {{{ - * mappings in Universal ++= sourceDir("extra") - * }}} - * - * @param sourceDir - * as string representation - * @return - * mappings - */ - def contentOf(sourceDir: String): Seq[(File, String)] = - contentOf(file(sourceDir)) - - /** - * Create mappings from your classpath. For example if you want to add additional dependencies, like test or model. - * - * @example - * Add all test artifacts to a separated test folder - * {{{ - * mappings in Universal ++= fromClasspath((managedClasspath in Test).value, target = "test") - * }}} - * - * @param entries - * @param target - * @return - * a list of mappings - */ - def fromClasspath(entries: Seq[Attributed[File]], target: String): Seq[(File, String)] = - fromClasspath(entries, target, _ => true) - - /** - * Create mappings from your classpath. For example if you want to add additional dependencies, like test or model. - * You can also filter the artifacts that should be mapped to mappings. - * - * @example - * Filter all osgi bundles - * {{{ - * mappings in Universal ++= fromClasspath( - * (managedClasspath in Runtime).value, - * "osgi", - * artifact => artifact.`type` == "bundle" - * ) - * }}} - * - * @param entries - * from where mappings should be created from - * @param target - * folder, e.g. `model`. Must not end with a slash - * @param includeArtifact - * function to determine if an artifact should result in a mapping - * @param includeOnNoArtifact - * default is false. When there's no Artifact meta data remove it - */ - def fromClasspath( - entries: Seq[Attributed[File]], - target: String, - includeArtifact: Artifact => Boolean, - includeOnNoArtifact: Boolean = false - ): Seq[(File, String)] = - entries.filter(attr => attr.get(sbt.Keys.artifact.key) map includeArtifact getOrElse includeOnNoArtifact).map { - attribute => - val file = attribute.data - file -> s"$target/${file.getName}" - } - - /** - * Get the mappings for the given files relative to the given directories. - */ - def relative(files: Seq[File], dirs: Seq[File]): Seq[(File, String)] = - (files --- dirs) pair (relativeTo(dirs) | Path.flat) - -} diff --git a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/SettingsHelper.scala b/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/SettingsHelper.scala deleted file mode 100644 index 5c3580234..000000000 --- a/src/main/scala-sbt-0.13/com/typesafe/sbt/packager/SettingsHelper.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.typesafe.sbt.packager - -import sbt.Keys._ -import sbt._ - -object SettingsHelper { - - def addPackage( - config: Configuration, - packageTask: TaskKey[File], - extension: String, - classifier: Option[String] = None - ): Seq[Setting[_]] = - inConfig(config)( - addArtifact( - name apply (Artifact( - _, - extension, - extension, - classifier = classifier, - configurations = Iterable.empty, - url = None, - extraAttributes = Map.empty - )), - packageTask - ) - ) - - def makeDeploymentSettings( - config: Configuration, - packageTask: TaskKey[File], - extension: String, - classifier: Option[String] = None - ): Seq[Setting[_]] = - inConfig(config)(Classpaths.ivyPublishSettings ++ Classpaths.jvmPublishSettings) ++ inConfig(config)( - Seq( - artifacts := Seq.empty, - packagedArtifacts := Map.empty, - projectID := ModuleID(organization.value, name.value, version.value), - moduleSettings := InlineConfiguration(projectID.value, projectInfo.value, Seq.empty), - ivyModule := { - val ivy = ivySbt.value - new ivy.Module(moduleSettings.value) - }, - deliverLocalConfiguration := Classpaths.deliverConfig(crossTarget.value, logging = ivyLoggingLevel.value), - deliverConfiguration := deliverLocalConfiguration.value, - publishConfiguration := new PublishConfiguration( - ivyFile = None, - resolverName = Classpaths.getPublishTo(publishTo.value).name, - artifacts = packagedArtifacts.value, - checksums = checksums.value, - logging = UpdateLogging.DownloadOnly, - overwrite = isSnapshot.value - ), - publishLocalConfiguration := new PublishConfiguration( - ivyFile = None, - resolverName = "local", - artifacts = packagedArtifacts.value, - checksums = checksums.value, - logging = UpdateLogging.DownloadOnly, - overwrite = isSnapshot.value - ), - publishM2Configuration := new PublishConfiguration( - ivyFile = None, - resolverName = Resolver.mavenLocal.name, - artifacts = packagedArtifacts.value, - checksums = checksums.value, - logging = UpdateLogging.DownloadOnly, - overwrite = isSnapshot.value - ) - ) - ) ++ addPackage(config, packageTask, extension, classifier) ++ addResolver(config) - - /** - * SBT looks in the `otherResolvers` setting for resolvers defined in `publishTo`. If a user scopes a `publishTo`, - * e.g. - * - * {{{ - * // publish the rpm to the target folder - * publishTo in Rpm := Some(Resolver.file("target-resolver", target.value / "rpm-repo" )) - * }}} - * - * then the resolver must also be present in the `otherResolvers` - * - * @param config - * the ivy configuration to look for resolvers - */ - private def addResolver(config: Configuration): Seq[Setting[_]] = - Seq(otherResolvers ++= (publishTo in config).value.toSeq) -} diff --git a/src/main/scala/com/typesafe/sbt/PackagerPlugin.scala b/src/main/scala/com/typesafe/sbt/PackagerPlugin.scala index 4a4eec099..6c3ad77b9 100644 --- a/src/main/scala/com/typesafe/sbt/PackagerPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/PackagerPlugin.scala @@ -1,10 +1,10 @@ package com.typesafe.sbt -import packager._ +import packager.* import debian.DebianPlugin.autoImport.genChanges import com.typesafe.sbt.packager.Keys.{packageXzTarball, packageZipTarball, validatePackage, validatePackageValidators} import com.typesafe.sbt.packager.validation.Validation -import sbt._ +import sbt.{*, given} import sbt.Keys.{name, normalizedName, packageBin, streams} /** @@ -73,16 +73,16 @@ object SbtNativePackager extends AutoPlugin { import SettingsHelper._ - @deprecated("Use enablePlugins(xxxDeployPlugin)", "1.x") - def deploymentSettings = - makeDeploymentSettings(Debian, Debian / packageBin, "deb") ++ - makeDeploymentSettings(Rpm, Rpm / packageBin, "rpm") ++ - makeDeploymentSettings(Windows, Windows / packageBin, "msi") ++ - makeDeploymentSettings(Universal, Universal / packageBin, "zip") ++ - addPackage(Universal, Universal / packageZipTarball, "tgz") ++ - makeDeploymentSettings(UniversalDocs, UniversalDocs / packageBin, "zip") ++ - addPackage(UniversalDocs, UniversalDocs / packageXzTarball, "txz") ++ - makeDeploymentSettings(Debian, Debian / genChanges, "changes") + // @deprecated("Use enablePlugins(xxxDeployPlugin)", "1.x") + // def deploymentSettings = + // makeDeploymentSettings(Debian, Debian / packageBin, "deb") ++ + // makeDeploymentSettings(Rpm, Rpm / packageBin, "rpm") ++ + // makeDeploymentSettings(Windows, Windows / packageBin, "msi") ++ + // makeDeploymentSettings(Universal, Universal / packageBin, "zip") ++ + // addPackage(Universal, Universal / packageZipTarball, "tgz") ++ + // makeDeploymentSettings(UniversalDocs, UniversalDocs / packageBin, "zip") ++ + // addPackage(UniversalDocs, UniversalDocs / packageXzTarball, "txz") ++ + // makeDeploymentSettings(Debian, Debian / genChanges, "changes") } import autoImport._ diff --git a/src/main/scala-sbt-1.0/com/typesafe/sbt/packager/MappingsHelper.scala b/src/main/scala/com/typesafe/sbt/packager/MappingsHelper.scala similarity index 69% rename from src/main/scala-sbt-1.0/com/typesafe/sbt/packager/MappingsHelper.scala rename to src/main/scala/com/typesafe/sbt/packager/MappingsHelper.scala index 4e47424be..468ec724b 100644 --- a/src/main/scala-sbt-1.0/com/typesafe/sbt/packager/MappingsHelper.scala +++ b/src/main/scala/com/typesafe/sbt/packager/MappingsHelper.scala @@ -1,7 +1,8 @@ package com.typesafe.sbt.packager -import sbt._ -import sbt.io._ +import sbt.{*, given} +import sbt.io.* +import xsbti.FileConverter /** A set of helper methods to simplify the writing of mappings */ object MappingsHelper extends Mapper { @@ -37,6 +38,13 @@ object MappingsHelper extends Mapper { def contentOf(sourceDir: String): Seq[(File, String)] = contentOf(file(sourceDir)) + def contentOf(sourceDir: File, conv0: FileConverter): Seq[(PluginCompat.FileRef, String)] = { + implicit val conv: FileConverter = conv0 + contentOf(sourceDir).map { case (f, p) => + PluginCompat.toFileRef(f) -> p + } + } + /** * Create mappings from your classpath. For example if you want to add additional dependencies, like test or model. * @@ -51,7 +59,10 @@ object MappingsHelper extends Mapper { * @return * a list of mappings */ - def fromClasspath(entries: Seq[Attributed[File]], target: String): Seq[(File, String)] = + def fromClasspath( + entries: Seq[Attributed[PluginCompat.FileRef]], + target: String + ): Seq[(PluginCompat.FileRef, String)] = fromClasspath(entries, target, _ => true) /** @@ -78,20 +89,25 @@ object MappingsHelper extends Mapper { * default is false. When there's no Artifact meta data remove it */ def fromClasspath( - entries: Seq[Attributed[File]], + entries: Seq[Attributed[PluginCompat.FileRef]], target: String, - includeArtifact: Artifact => Boolean, + includeArtifact: PluginCompat.IncludeArtifact, includeOnNoArtifact: Boolean = false - ): Seq[(File, String)] = - entries.filter(attr => attr.get(sbt.Keys.artifact.key) map includeArtifact getOrElse includeOnNoArtifact).map { + ): Seq[(PluginCompat.FileRef, String)] = + entries.filter(attr => attr.get(PluginCompat.artifactStr).map(includeArtifact) getOrElse includeOnNoArtifact).map { attribute => val file = attribute.data - file -> s"$target/${file.getName}" + val name = PluginCompat.getName(file) + file -> s"$target/${name}" } /** * Get the mappings for the given files relative to the given directories. */ - def relative(files: Seq[File], dirs: Seq[File]): Seq[(File, String)] = - (files --- dirs) pair (relativeTo(dirs) | flat) + def relative(files: Seq[File], dirs: Seq[File], conv0: FileConverter): Seq[(PluginCompat.FileRef, String)] = { + implicit val conv: FileConverter = conv0 + (files --- dirs) pair (relativeTo(dirs) | flat) map { case (f, p) => + PluginCompat.toFileRef(f) -> p + } + } } diff --git a/src/main/scala-sbt-1.0/com/typesafe/sbt/packager/SettingsHelper.scala b/src/main/scala/com/typesafe/sbt/packager/SettingsHelper.scala similarity index 79% rename from src/main/scala-sbt-1.0/com/typesafe/sbt/packager/SettingsHelper.scala rename to src/main/scala/com/typesafe/sbt/packager/SettingsHelper.scala index bdd2fd60f..35a2b0a0e 100644 --- a/src/main/scala-sbt-1.0/com/typesafe/sbt/packager/SettingsHelper.scala +++ b/src/main/scala/com/typesafe/sbt/packager/SettingsHelper.scala @@ -1,9 +1,9 @@ package com.typesafe.sbt.packager -import sbt._ -import sbt.Keys._ +import sbt.{*, given} +import sbt.Keys.* import sbt.librarymanagement.{IvyFileConfiguration, PublishConfiguration} -import com.typesafe.sbt.packager.Compat._ +import com.typesafe.sbt.packager.Compat.* /** * - TODO write tests for the SettingsHelper @@ -14,7 +14,7 @@ object SettingsHelper { def addPackage( config: Configuration, - packageTask: TaskKey[File], + packageTask: TaskKey[PluginCompat.FileRef], extension: String, classifier: Option[String] = None ): Seq[Setting[_]] = @@ -34,7 +34,7 @@ object SettingsHelper { def makeDeploymentSettings( config: Configuration, - packageTask: TaskKey[File], + packageTask: TaskKey[PluginCompat.FileRef], extension: String, classifier: Option[String] = None ): Seq[Setting[_]] = @@ -58,19 +58,31 @@ object SettingsHelper { // ------------------------------- publishConfiguration := PublishConfiguration() .withResolverName(Classpaths.getPublishTo(publishTo.value).name) - .withArtifacts(packagedArtifacts.value.toVector) + .withArtifacts(packagedArtifacts.value.toVector.map { case (a, f) => + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + (a, PluginCompat.toFile(f)) + }) .withChecksums(checksums.value.toVector) .withOverwrite(isSnapshot.value) .withLogging(UpdateLogging.DownloadOnly), publishLocalConfiguration := PublishConfiguration() .withResolverName("local") - .withArtifacts(packagedArtifacts.value.toVector) + .withArtifacts(packagedArtifacts.value.toVector.map { case (a, f) => + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + (a, PluginCompat.toFile(f)) + }) .withChecksums(checksums.value.toVector) .withOverwrite(isSnapshot.value) .withLogging(UpdateLogging.DownloadOnly), publishM2Configuration := PublishConfiguration() .withResolverName(Resolver.mavenLocal.name) - .withArtifacts(packagedArtifacts.value.toVector) + .withArtifacts(packagedArtifacts.value.toVector.map { case (a, f) => + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + (a, PluginCompat.toFile(f)) + }) .withChecksums(checksums.value.toVector) .withOverwrite(isSnapshot.value) .withLogging(UpdateLogging.DownloadOnly) diff --git a/src/main/scala/com/typesafe/sbt/packager/Stager.scala b/src/main/scala/com/typesafe/sbt/packager/Stager.scala index 525bda5a2..d9ca538b5 100644 --- a/src/main/scala/com/typesafe/sbt/packager/Stager.scala +++ b/src/main/scala/com/typesafe/sbt/packager/Stager.scala @@ -1,10 +1,12 @@ package com.typesafe.sbt.packager -import sbt._ +import sbt.{*, given} import sbt.Keys.TaskStreams +import sbt.util.CacheStore import java.io.File import com.typesafe.sbt.packager.Compat._ +import xsbti.FileConverter object Stager { @@ -20,12 +22,17 @@ object Stager { * @param mappings * staging content */ - def stageFiles(config: String)(cacheDirectory: File, stageDirectory: File, mappings: Seq[(File, String)]): File = { + def stageFiles( + config: String + )(cacheDirectory: File, stageDirectory: File, mappings: Seq[(PluginCompat.FileRef, String)])(implicit + conv: FileConverter + ): File = { val cache = cacheDirectory / ("packager-mappings-" + config) - val copies = mappings map { case (file, path) => - file -> (stageDirectory / path) + val copies = mappings map { case (ref, path) => + PluginCompat.toFile(ref) -> (stageDirectory / path) } - Sync(cache, FileInfo.hash, FileInfo.exists)(copies) + val store = CacheStore(cache) + Sync.sync(store, FileInfo.hash)(copies) // Now set scripts to executable using Java's lack of understanding of permissions. // TODO - Config file user-readable permissions.... for { @@ -41,7 +48,9 @@ object Stager { * @see * stageFiles */ - def stage(config: String)(streams: TaskStreams, stageDirectory: File, mappings: Seq[(File, String)]): File = + def stage(config: String)(streams: TaskStreams, stageDirectory: File, mappings: Seq[(PluginCompat.FileRef, String)])( + implicit conv: FileConverter + ): File = stageFiles(config)(streams.cacheDirectory, stageDirectory, mappings) } diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppKeys.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppKeys.scala index 22cd57a18..4f6f46147 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppKeys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppKeys.scala @@ -1,6 +1,7 @@ package com.typesafe.sbt.packager.archetypes -import sbt._ +import sbt.{*, given} +import com.typesafe.sbt.packager.PluginCompat /** * Available settings/tasks for the [[com.typesafe.sbt.packager.archetypes.JavaAppPackaging]] and all depending @@ -14,14 +15,10 @@ trait JavaAppKeys { "bashScriptEnvConfigLocation", "The location of a bash script that will be sourced before running the app." ) - val scriptClasspathOrdering = TaskKey[Seq[(File, String)]]( - "scriptClasspathOrdering", - "The order of the classpath used at runtime for the bat/bash scripts." - ) - val projectDependencyArtifacts = TaskKey[Seq[Attributed[File]]]( - "projectDependencyArtifacts", - "The set of exported artifacts from our dependent projects." - ) + val scriptClasspathOrdering = + taskKey[Seq[(PluginCompat.FileRef, String)]]("The order of the classpath used at runtime for the bat/bash scripts.") + val projectDependencyArtifacts = + taskKey[Seq[Attributed[PluginCompat.FileRef]]]("The set of exported artifacts from our dependent projects.") val scriptClasspath = TaskKey[Seq[String]]( "scriptClasspath", "A list of relative filenames (to the lib/ folder in the distribution) of what to include on the classpath." diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppPackaging.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppPackaging.scala index 163976e53..dc921efa9 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppPackaging.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaAppPackaging.scala @@ -1,13 +1,15 @@ -package com.typesafe.sbt.packager.archetypes +package com.typesafe.sbt.packager +package archetypes -import sbt._ -import sbt.Keys._ +import sbt.{*, given} +import sbt.Keys.* +import sbt.internal.BuildDependencies import com.typesafe.sbt.SbtNativePackager.{Debian, Universal} -import com.typesafe.sbt.packager._ import com.typesafe.sbt.packager.Keys.packageName import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping} import com.typesafe.sbt.packager.linux.LinuxPlugin.autoImport.{defaultLinuxInstallLocation, linuxPackageMappings} -import com.typesafe.sbt.packager.Compat._ +import com.typesafe.sbt.packager.Compat.* +import xsbti.FileConverter /** * ==Java Application== @@ -60,7 +62,8 @@ object JavaAppPackaging extends AutoPlugin { projectDependencyArtifacts := findProjectDependencyArtifacts.value, scriptClasspathOrdering ++= universalDepMappings( (Runtime / dependencyClasspath).value, - projectDependencyArtifacts.value + projectDependencyArtifacts.value, + fileConverter.value ), scriptClasspathOrdering := scriptClasspathOrdering.value.distinct, Universal / mappings ++= scriptClasspathOrdering.value, @@ -77,7 +80,7 @@ object JavaAppPackaging extends AutoPlugin { bundledJvmLocation := (bundledJvmLocation ?? None).value ) - private def makeRelativeClasspathNames(mappings: Seq[(File, String)]): Seq[String] = + private def makeRelativeClasspathNames(mappings: Seq[(PluginCompat.FileRef, String)]): Seq[String] = for { (_, name) <- mappings } yield @@ -105,17 +108,14 @@ object JavaAppPackaging extends AutoPlugin { // Determines a nicer filename for an attributed jar file, using the // ivy metadata if available. - private def getJarFullFilename(dep: Attributed[File]): String = { + private def getJarFullFilename(dep: Attributed[PluginCompat.FileRef]): String = { val filename: Option[String] = for { - module <- - dep.metadata - // sbt 0.13.x key - .get(AttributeKey[ModuleID]("module-id")) - // sbt 1.x key - .orElse(dep.metadata.get(AttributeKey[ModuleID]("moduleID"))) - artifact <- dep.metadata.get(AttributeKey[Artifact]("artifact")) + moduleStr <- dep.metadata.get(PluginCompat.moduleIDStr) + artifactStr <- dep.metadata.get(PluginCompat.artifactStr) + module = PluginCompat.parseModuleIDStrAttribute(moduleStr) + artifact = PluginCompat.parseArtifactStrAttribute(artifactStr) } yield makeJarName(module.organization, module.name, module.revision, artifact.name, artifact.classifier) - filename.getOrElse(dep.data.getName) + filename.getOrElse(PluginCompat.getName(dep.data)) } // Here we grab the dependencies... @@ -123,23 +123,27 @@ object JavaAppPackaging extends AutoPlugin { build.classpathTransitive.getOrElse(thisProject, Nil) // TODO - Should we pull in more than just JARs? How do native packages come in? - private def isRuntimeArtifact(dep: Attributed[File]): Boolean = - dep.get(sbt.Keys.artifact.key).map(_.`type` == "jar").getOrElse { - val name = dep.data.getName - !(name.endsWith(".jar") || name.endsWith("-sources.jar") || name.endsWith("-javadoc.jar")) - } + private def isRuntimeArtifact(dep: Attributed[PluginCompat.FileRef]): Boolean = + dep + .get(PluginCompat.artifactStr) + .map(PluginCompat.parseArtifactStrAttribute) + .map(_.`type` == "jar") + .getOrElse { + val name = PluginCompat.getName(dep.data) + !(name.endsWith(".jar") || name.endsWith("-sources.jar") || name.endsWith("-javadoc.jar")) + } - private def findProjectDependencyArtifacts: Def.Initialize[Task[Seq[Attributed[File]]]] = + private def findProjectDependencyArtifacts: Def.Initialize[Task[Seq[Attributed[PluginCompat.FileRef]]]] = Def - .task { + .setting { val stateTask = state.taskValue val refs = thisProjectRef.value +: dependencyProjectRefs(buildDependencies.value, thisProjectRef.value) // Dynamic lookup of dependencies... val artTasks = refs map { ref => extractArtifacts(stateTask, ref) } - val allArtifactsTask: Task[Seq[Attributed[File]]] = - artTasks.fold[Task[Seq[Attributed[File]]]](task(Nil)) { (previous, next) => + val allArtifactsTask: Task[Seq[Attributed[PluginCompat.FileRef]]] = + artTasks.fold[Task[Seq[Attributed[PluginCompat.FileRef]]]](task(Nil)) { (previous, next) => for { p <- previous n <- next @@ -147,9 +151,8 @@ object JavaAppPackaging extends AutoPlugin { } allArtifactsTask } - .flatMap(identity) - private def extractArtifacts(stateTask: Task[State], ref: ProjectRef): Task[Seq[Attributed[File]]] = + private def extractArtifacts(stateTask: Task[State], ref: ProjectRef): Task[Seq[Attributed[PluginCompat.FileRef]]] = stateTask.flatMap { state => val extracted = Project.extract(state) // TODO - Is this correct? @@ -159,31 +162,43 @@ object JavaAppPackaging extends AutoPlugin { arts <- artifactTask } yield for { (art, file) <- arts.toSeq // TODO -Filter! - } yield Attributed.blank(file).put(moduleID.key, module).put(artifact.key, art) + } yield Attributed + .blank(file) + .put(PluginCompat.moduleIDStr, PluginCompat.moduleIDToStr(module)) + .put(PluginCompat.artifactStr, PluginCompat.artifactToStr(art)) } - private def findRealDep(dep: Attributed[File], projectArts: Seq[Attributed[File]]): Option[Attributed[File]] = - if (dep.data.isFile) Some(dep) + private def findRealDep( + dep: Attributed[PluginCompat.FileRef], + projectArts: Seq[Attributed[PluginCompat.FileRef]], + conv0: FileConverter + ): Option[Attributed[PluginCompat.FileRef]] = { + implicit val conv: FileConverter = conv0 + if (PluginCompat.toFile(dep.data).isFile) Some(dep) else projectArts.find { art => // TODO - Why is the module not showing up for project deps? // (art.get(sbt.Keys.moduleID.key) == dep.get(sbt.Keys.moduleID.key)) && - (art.get(sbt.Keys.artifact.key), dep.get(sbt.Keys.artifact.key)) match { - case (Some(l), Some(r)) => + (art.get(PluginCompat.artifactStr), dep.get(PluginCompat.artifactStr)) match { + case (Some(l0), Some(r0)) => + val l = PluginCompat.parseArtifactStrAttribute(l0) + val r = PluginCompat.parseArtifactStrAttribute(r0) // TODO - extra attributes and stuff for comparison? // seems to break stuff if we do... l.name == r.name && l.classifier == r.classifier case _ => false } } + } // Converts a managed classpath into a set of lib mappings. private def universalDepMappings( - deps: Seq[Attributed[File]], - projectArts: Seq[Attributed[File]] - ): Seq[(File, String)] = + deps: Seq[Attributed[PluginCompat.FileRef]], + projectArts: Seq[Attributed[PluginCompat.FileRef]], + conv0: FileConverter + ): Seq[(PluginCompat.FileRef, String)] = for { dep <- deps - realDep <- findRealDep(dep, projectArts) + realDep <- findRealDep(dep, projectArts, conv0) } yield realDep.data -> ("lib/" + getJarFullFilename(realDep)) } diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaServerApplication.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaServerApplication.scala index f47c805d8..4327cf277 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaServerApplication.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/JavaServerApplication.scala @@ -1,15 +1,17 @@ -package com.typesafe.sbt.packager.archetypes +package com.typesafe.sbt.packager +package archetypes -import sbt._ -import sbt.Keys.{javaOptions, mainClass, run, sourceDirectory, streams, target} +import sbt.{*, given} +import sbt.Keys.{fileConverter, javaOptions, mainClass, run, sourceDirectory, streams, target} import com.typesafe.sbt.SbtNativePackager.{Debian, Linux, Rpm, Universal} -import com.typesafe.sbt.packager.Keys._ +import com.typesafe.sbt.packager.Keys.* import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping, LinuxPlugin, LinuxSymlink} import com.typesafe.sbt.packager.linux.LinuxPlugin.autoImport.packageTemplateMapping import com.typesafe.sbt.packager.debian.DebianPlugin import com.typesafe.sbt.packager.rpm.RpmPlugin import com.typesafe.sbt.packager.rpm.RpmPlugin.autoImport.RpmConstants import com.typesafe.sbt.packager.archetypes.systemloader.ServerLoader +import xsbti.FileConverter /** * ==Java Server App Packaging== @@ -256,7 +258,7 @@ object JavaServerAppPackaging extends AutoPlugin { } // used to override template - val rpmScripts = Option(scriptDirectory.listFiles) getOrElse Array.empty + val rpmScripts = Option(scriptDirectory.listFiles).getOrElse(Array.empty[File]) // remove all non files and already processed templates rpmScripts.filter(s => s.isFile && !predefined.contains(s.getName)).foldLeft(predefinedScripts) { diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/TemplateWriter.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/TemplateWriter.scala index 6a05541af..c447cdc62 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/TemplateWriter.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/TemplateWriter.scala @@ -49,7 +49,7 @@ object TemplateWriter { sb append replace(line, replacements, keySurround) sb append eol } - sb toString + sb.toString() } private[this] def replaceValues( diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala index 5efedd9ae..7e58588be 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala @@ -3,15 +3,17 @@ package jlink import scala.collection.immutable import scala.sys.process.{BasicIO, Process, ProcessBuilder} -import sbt._ -import sbt.Keys._ +import sbt.{*, given} +import sbt.Keys.* import com.typesafe.sbt.SbtNativePackager.{Debian, Universal} import com.typesafe.sbt.packager.Keys.{bundledJvmLocation, packageName} import com.typesafe.sbt.packager.Compat._ +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.archetypes.jlink._ import com.typesafe.sbt.packager.archetypes.scripts.BashStartScriptKeys import com.typesafe.sbt.packager.universal.UniversalPlugin import java.io.File +import xsbti.FileConverter /** * ==Jlink Application== @@ -51,10 +53,13 @@ object JlinkPlugin extends AutoPlugin { jlinkBuildImage / fullClasspath := (Compile / fullClasspath).value, jlinkModules := (jlinkModules ?? Nil).value, jlinkModules ++= { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val log = streams.value.log val javaHome0 = (jlinkBuildImage / javaHome).value.getOrElse(defaultJavaHome) val run = runJavaTool(javaHome0, log) _ - val paths = (jlinkBuildImage / fullClasspath).value.map(_.data.getPath) + val paths = + (jlinkBuildImage / fullClasspath).value.map(PluginCompat.toNioPath).map(_.toString()) val modulePath = (jlinkModules / jlinkModulePath).value val shouldIgnore = jlinkIgnoreMissingDependency.value @@ -164,12 +169,15 @@ object JlinkPlugin extends AutoPlugin { outDir }, jlinkBuildImage / mappings := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val prefix = jlinkBundledJvmLocation.value // make sure the prefix has a terminating slash val prefix0 = if (prefix.isEmpty) prefix else prefix + "/" findFiles(jlinkBuildImage.value).map { case (file, string) => - (file, prefix0 + string) + val ref = PluginCompat.toFileRef(file) + (ref, prefix0 + string) } }, Universal / mappings ++= (jlinkBuildImage / mappings).value @@ -256,7 +264,7 @@ object JlinkPlugin extends AutoPlugin { source: PackageDependency.Source ) - private[jlink] final object PackageDependency { + private[jlink] object PackageDependency { implicit object PackageDependencyOrdering extends Ordering[PackageDependency] { override def compare(x: PackageDependency, y: PackageDependency): Int = { diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/ApplicationIniGenerator.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/ApplicationIniGenerator.scala index 4c00aacab..8cf34a5f2 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/ApplicationIniGenerator.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/ApplicationIniGenerator.scala @@ -1,8 +1,10 @@ package com.typesafe.sbt.packager.archetypes.scripts +import com.typesafe.sbt.packager.PluginCompat import java.io.File -import sbt._ +import sbt.{*, given} +import xsbti.FileConverter trait ApplicationIniGenerator { @@ -11,12 +13,12 @@ trait ApplicationIniGenerator { * the existing mappings plus a generated application.ini if custom javaOptions are specified */ def generateApplicationIni( - universalMappings: Seq[(File, String)], + universalMappings: Seq[(PluginCompat.FileRef, String)], javaOptions: Seq[String], bashScriptConfigLocation: Option[String], tmpDir: File, log: Logger - ): Seq[(File, String)] = + )(implicit conv: FileConverter): Seq[(PluginCompat.FileRef, String)] = bashScriptConfigLocation .collect { case location if javaOptions.nonEmpty => @@ -42,7 +44,8 @@ trait ApplicationIniGenerator { case _ => true } - (configFile -> pathMapping) +: filteredMappings + val configFileRef = PluginCompat.toFileRef(configFile) + (configFileRef -> pathMapping) +: filteredMappings } .getOrElse(universalMappings) diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptKeys.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptKeys.scala index 71eca3ca7..6883c96a7 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptKeys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptKeys.scala @@ -1,6 +1,7 @@ package com.typesafe.sbt.packager.archetypes.scripts -import sbt._ +import sbt.{*, given} +import com.typesafe.sbt.packager.PluginCompat /** * Keys related to the [[BashStartScriptPlugin]] @@ -9,7 +10,7 @@ import sbt._ * [[BashStartScriptPlugin]] */ trait BashStartScriptKeys { - val makeBashScripts = TaskKey[Seq[(File, String)]]("makeBashScripts", "Creates start scripts for this project.") + val makeBashScripts = taskKey[Seq[(PluginCompat.FileRef, String)]]("Creates start scripts for this project.") val bashScriptTemplateLocation = TaskKey[File]("bashScriptTemplateLocation", "The location of the bash script template.") diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptPlugin.scala index 1e74a29b3..97ca2e773 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BashStartScriptPlugin.scala @@ -5,8 +5,8 @@ import java.io.File import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.Keys._ import com.typesafe.sbt.packager.archetypes.{JavaAppPackaging, TemplateWriter} -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} /** * ==Bash StartScript Plugin== @@ -69,13 +69,17 @@ object BashStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator wit bashScriptConfigLocation := (bashScriptConfigLocation ?? Some(appIniLocation)).value, bashScriptEnvConfigLocation := (bashScriptEnvConfigLocation ?? None).value, // Generating the application configuration - Universal / mappings := generateApplicationIni( - (Universal / mappings).value, - (Universal / javaOptions).value, - bashScriptConfigLocation.value, - (Universal / target).value, - streams.value.log - ), + Universal / mappings := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + generateApplicationIni( + (Universal / mappings).value, + (Universal / javaOptions).value, + bashScriptConfigLocation.value, + (Universal / target).value, + streams.value.log + ) + }, makeBashScripts := generateStartScripts( BashScriptConfig( executableScriptName = executableScriptName.value, @@ -87,6 +91,7 @@ object BashStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator wit (Compile / bashScriptDefines / mainClass).value, (Compile / discoveredMainClasses).value, (Universal / target).value / "scripts", + fileConverter.value, streams.value.log ), Universal / mappings ++= makeBashScripts.value diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptKeys.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptKeys.scala index ab9042eba..550c2123d 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptKeys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptKeys.scala @@ -1,4 +1,5 @@ -package com.typesafe.sbt.packager.archetypes.scripts +package com.typesafe.sbt.packager +package archetypes.scripts import sbt._ @@ -9,7 +10,8 @@ import sbt._ * [[BatStartScriptPlugin]] */ trait BatStartScriptKeys { - val makeBatScripts = TaskKey[Seq[(File, String)]]("makeBatScripts", "Creates start scripts for this project.") + val makeBatScripts = + taskKey[Seq[(PluginCompat.FileRef, String)]]("Creates start scripts for this project.") val batScriptTemplateLocation = TaskKey[File]("batScriptTemplateLocation", "The location of the bat script template.") diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptPlugin.scala index 09f8fa629..aa9888ef7 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/BatStartScriptPlugin.scala @@ -6,8 +6,8 @@ import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.Keys._ import com.typesafe.sbt.packager.archetypes.{JavaAppPackaging, TemplateWriter} import com.typesafe.sbt.packager.windows.NameHelper -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} /** * ==Bat StartScript Plugin== @@ -53,47 +53,6 @@ object BatStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator with bundledJvmLocation: Option[String], override val forwarderTemplateLocation: Option[File] ) extends ScriptConfig { - - @deprecated("1.3.21", "") - def this( - executableScriptName: String, - scriptClasspath: Seq[String], - configLocation: Option[String], - extraDefines: Seq[String], - replacements: Seq[(String, String)], - templateLocation: File - ) = - this( - executableScriptName, - scriptClasspath, - configLocation, - extraDefines, - replacements, - templateLocation, - None, - None - ) - - @deprecated("1.3.21", "") - def copy( - executableScriptName: String = executableScriptName, - scriptClasspath: Seq[String] = scriptClasspath, - configLocation: Option[String] = configLocation, - extraDefines: Seq[String] = extraDefines, - replacements: Seq[(String, String)] = replacements, - templateLocation: File = templateLocation - ): BatScriptConfig = - BatScriptConfig( - executableScriptName, - scriptClasspath, - configLocation, - extraDefines, - replacements, - templateLocation, - bundledJvmLocation, - forwarderTemplateLocation - ) - override def withScriptName(scriptName: String): BatScriptConfig = copy(executableScriptName = scriptName) } @@ -134,13 +93,17 @@ object BatStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator with batScriptExtraDefines := Nil, batScriptReplacements := Replacements(executableScriptName.value), // Generating the application configuration - Universal / mappings := generateApplicationIni( - (Universal / mappings).value, - (Universal / javaOptions).value, - batScriptConfigLocation.value, - (Universal / target).value, - streams.value.log - ), + Universal / mappings := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + generateApplicationIni( + (Universal / mappings).value, + (Universal / javaOptions).value, + batScriptConfigLocation.value, + (Universal / target).value, + streams.value.log + ) + }, makeBatScripts := generateStartScripts( BatScriptConfig( executableScriptName = executableScriptName.value, @@ -155,6 +118,7 @@ object BatStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator with (Compile / batScriptReplacements / mainClass).value, (Compile / discoveredMainClasses).value, (Universal / target).value / "scripts", + fileConverter.value, streams.value.log ), Universal / mappings ++= makeBatScripts.value diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/CommonStartScriptGenerator.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/CommonStartScriptGenerator.scala index f9de4b3c7..69e41cb4b 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/CommonStartScriptGenerator.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/scripts/CommonStartScriptGenerator.scala @@ -3,8 +3,10 @@ package com.typesafe.sbt.packager.archetypes.scripts import java.io.File import java.net.URL +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.archetypes.TemplateWriter -import sbt._ +import sbt.{*, given} +import xsbti.FileConverter trait CommonStartScriptGenerator { @@ -67,27 +69,29 @@ trait CommonStartScriptGenerator { mainClass: Option[String], discoveredMainClasses: Seq[String], targetDir: File, + conv: FileConverter, log: sbt.Logger - ): Seq[(File, String)] = + ): Seq[(PluginCompat.FileRef, String)] = StartScriptMainClassConfig.from(mainClass, discoveredMainClasses) match { case NoMain => log.warn("You have no main class in your project. No start script will be generated.") Seq.empty case SingleMain(main) => - Seq(createMainScript(main, config, targetDir, Seq(main))) + Seq(createMainScript(main, config, targetDir, Seq(main), conv)) case MultipleMains(mains) => - generateMainScripts(mains, config, targetDir, log) + generateMainScripts(mains, config, targetDir, conv, log) case ExplicitMainWithAdditional(main, additional) => - createMainScript(main, config, targetDir, discoveredMainClasses) +: - createForwarderScripts(config.executableScriptName, additional, targetDir, config, log) + createMainScript(main, config, targetDir, discoveredMainClasses, conv) +: + createForwarderScripts(config.executableScriptName, additional, targetDir, config, conv, log) } private[this] def generateMainScripts( discoveredMainClasses: Seq[String], config: SpecializedScriptConfig, targetDir: File, + conv: FileConverter, log: sbt.Logger - ): Seq[(File, String)] = { + ): Seq[(PluginCompat.FileRef, String)] = { val classAndScriptNames = ScriptUtils.createScriptNames(discoveredMainClasses) ScriptUtils.warnOnScriptNameCollision(classAndScriptNames, log) @@ -101,7 +105,7 @@ trait CommonStartScriptGenerator { ) // empty string to enforce the custom class in scripts .map { case (qualifiedClassName, scriptName) => val newConfig = config.withScriptName(scriptName) - createMainScript(qualifiedClassName, newConfig, targetDir, discoveredMainClasses) + createMainScript(qualifiedClassName, newConfig, targetDir, discoveredMainClasses, conv) } } @@ -122,8 +126,10 @@ trait CommonStartScriptGenerator { mainClass: String, config: SpecializedScriptConfig, targetDir: File, - mainClasses: Seq[String] - ): (File, String) = { + mainClasses: Seq[String], + conv0: FileConverter + ): (PluginCompat.FileRef, String) = { + implicit val conv: FileConverter = conv0 val template = resolveTemplate(config.templateLocation) val replacements = createReplacementsForMainScript(mainClass, mainClasses, config) val scriptContent = TemplateWriter.generateScript(template, replacements, eol, keySurround) @@ -133,7 +139,8 @@ trait CommonStartScriptGenerator { IO.write(script, scriptContent) // TODO - Better control over this! script.setExecutable(executableBitValue) - script -> s"$scriptTargetFolder/$scriptNameWithSuffix" + val scriptRef = PluginCompat.toFileRef(script) + scriptRef -> s"$scriptTargetFolder/$scriptNameWithSuffix" } private[this] def resolveTemplate(templateLocation: File): URL = @@ -145,8 +152,10 @@ trait CommonStartScriptGenerator { discoveredMainClasses: Seq[String], targetDir: File, config: ScriptConfig, + conv0: FileConverter, log: sbt.Logger - ): Seq[(File, String)] = { + ): Seq[(PluginCompat.FileRef, String)] = { + implicit val conv: FileConverter = conv0 val tmp = targetDir / scriptTargetFolder val forwarderTemplate = config.forwarderTemplateLocation.map(resolveTemplate).getOrElse(getClass.getResource(forwarderTemplateName)) @@ -161,7 +170,8 @@ trait CommonStartScriptGenerator { IO.write(file, scriptContent) file.setExecutable(executableBitValue) - file -> s"$scriptTargetFolder/$scriptName" + val fileRef = PluginCompat.toFileRef(file) + fileRef -> s"$scriptTargetFolder/$scriptName" } } } diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemdPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemdPlugin.scala index 7a6a28307..6b23b0100 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemdPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemdPlugin.scala @@ -1,6 +1,6 @@ package com.typesafe.sbt.packager.archetypes.systemloader -import sbt._ +import sbt.{*, given} import sbt.Keys.{sourceDirectory, target} import com.typesafe.sbt.packager.Keys.{ defaultLinuxStartScriptLocation, @@ -19,6 +19,7 @@ import com.typesafe.sbt.packager.Keys.{ stopRunlevels } import com.typesafe.sbt.SbtNativePackager.{Debian, Linux, Rpm, Universal} +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.archetypes.MaintainerScriptHelper.maintainerScriptsAppend import com.typesafe.sbt.packager.debian.DebianPlugin import com.typesafe.sbt.packager.debian.DebianPlugin.autoImport.DebianConstants diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemloaderPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemloaderPlugin.scala index 61a84ac8c..1f1d6f5fc 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemloaderPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/SystemloaderPlugin.scala @@ -1,7 +1,7 @@ package com.typesafe.sbt.packager.archetypes.systemloader -import sbt._ -import sbt.Keys.{sourceDirectory, target} +import sbt.{*, given} +import sbt.Keys.{fileConverter, sourceDirectory, target} import com.typesafe.sbt.SbtNativePackager.{Debian, Rpm} import com.typesafe.sbt.packager.Keys.{ defaultLinuxStartScriptLocation, diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/package.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/package.scala index 5c94ae8b6..cd6a01aef 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/package.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/systemloader/package.scala @@ -1,13 +1,15 @@ package com.typesafe.sbt.packager.archetypes -import sbt._ +import sbt.{*, given} import java.io.File import java.net.URL +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.linux._ import com.typesafe.sbt.packager.linux.LinuxPlugin.Users import com.typesafe.sbt.packager.archetypes.systemloader.ServerLoader._ +import xsbti.FileConverter package object systemloader { diff --git a/src/main/scala/com/typesafe/sbt/packager/debian/DebianNativePackaging.scala b/src/main/scala/com/typesafe/sbt/packager/debian/DebianNativePackaging.scala index 445f4e7d9..91e8454c3 100644 --- a/src/main/scala/com/typesafe/sbt/packager/debian/DebianNativePackaging.scala +++ b/src/main/scala/com/typesafe/sbt/packager/debian/DebianNativePackaging.scala @@ -1,11 +1,13 @@ -package com.typesafe.sbt.packager.debian +package com.typesafe.sbt.packager +package debian import com.typesafe.sbt.SbtNativePackager.Debian import com.typesafe.sbt.packager.Keys._ import com.typesafe.sbt.packager.linux.LinuxFileMetaData import com.typesafe.sbt.packager.Compat._ -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} +import xsbti.FileConverter /** * ==Native Packaging== @@ -36,17 +38,20 @@ trait DebianNativePackaging extends DebianPluginLike { inConfig(Debian)( Seq( debianNativeBuildOptions += "-Znone", // packages are largely JARs, which are already compressed - genChanges := dpkgGenChanges( - packageBin.value, - debianChangelog.value, - debianPackageMetadata.value, - target.value - ), + genChanges := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + dpkgGenChanges(packageBin.value, debianChangelog.value, debianPackageMetadata.value, target.value) + }, debianSign := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val deb = packageBin.value + val debFile = PluginCompat.toFile(deb) val role = debianSignRole.value val log = streams.value.log - sys.process.Process(Seq("dpkg-sig", "-s", role, deb.getAbsolutePath), Some(deb.getParentFile)) ! log match { + sys.process + .Process(Seq("dpkg-sig", "-s", role, debFile.getAbsolutePath), Some(debFile.getParentFile)) ! log match { case 0 => () case x => sys.error("Failed to sign debian package! exit code: " + x) @@ -54,8 +59,11 @@ trait DebianNativePackaging extends DebianPluginLike { deb }, lintian := { - val file = packageBin.value - sys.process.Process(Seq("lintian", "-c", "-v", file.getName), Some(file.getParentFile)).! + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val deb = packageBin.value + val debFile = PluginCompat.toFile(deb) + sys.process.Process(Seq("lintian", "-c", "-v", debFile.getName), Some(debFile.getParentFile)).! }, /** Implementation of the actual packaging */ packageBin := buildPackage( @@ -64,12 +72,18 @@ trait DebianNativePackaging extends DebianPluginLike { packageArchitecture.value, stage.value, debianNativeBuildOptions.value, + fileConverter.value, streams.value.log ) ) ) - private[this] def dpkgGenChanges(debFile: File, changelog: Option[File], data: PackageMetaData, targetDir: File) = { + private[this] def dpkgGenChanges( + debFile: PluginCompat.FileRef, + changelog: Option[File], + data: PackageMetaData, + targetDir: File + )(implicit conv: FileConverter): PluginCompat.FileRef = { println(s"Changelog: $changelog") changelog match { case None => @@ -79,10 +93,11 @@ trait DebianNativePackaging extends DebianPluginLike { val debSrc = targetDir / "../tmp" / Names.DebianSource debSrc.mkdirs() copyAndFixPerms(chlog, debSrc / Names.Changelog, LinuxFileMetaData("0644")) - IO.writeLines(debSrc / Names.Files, List(debFile.getName + " " + data.section + " " + data.priority)) + val debFileFile = PluginCompat.toFile(debFile) + IO.writeLines(debSrc / Names.Files, List(debFileFile.getName + " " + data.section + " " + data.priority)) // dpkg-genchanges needs a "source" control file, located in a "debian" directory IO.writeLines(debSrc / Names.Control, List(data.makeSourceControl())) - val changesFileName = debFile.getName.replaceAll("deb$", "changes") + val changesFileName = debFileFile.getName.replaceAll("deb$", "changes") val changesFile: File = targetDir / ".." / changesFileName try { val changes = sys.process.Process(Seq("dpkg-genchanges", "-b"), Some(targetDir / "../tmp")).!! @@ -92,7 +107,8 @@ trait DebianNativePackaging extends DebianPluginLike { case e: Exception => throw new RuntimeException("Failure generating changes file.", e) } - changesFile + val changesFileRef = PluginCompat.toFileRef(changesFile) + changesFileRef } } @@ -102,8 +118,10 @@ trait DebianNativePackaging extends DebianPluginLike { arch: String, stageDir: File, buildOptions: Seq[String], + conv0: FileConverter, log: Logger - ) = { + ): PluginCompat.FileRef = { + implicit val conv: FileConverter = conv0 log.info("Building debian package with native implementation") // Make the package. We put this in fakeroot, so we can build the package with root owning files. val archive = archiveFilename(name, version, arch) @@ -115,7 +133,8 @@ trait DebianNativePackaging extends DebianPluginLike { case x => sys.error("Failure packaging debian file. Exit code: " + x) } - stageDir / ".." / archive + val out = stageDir / ".." / archive + PluginCompat.toFileRef(out) } } diff --git a/src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala index de4760bb1..3d76a7da3 100644 --- a/src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala @@ -1,4 +1,5 @@ -package com.typesafe.sbt.packager.debian +package com.typesafe.sbt.packager +package debian import com.typesafe.sbt.SbtNativePackager.{Linux, Universal} import com.typesafe.sbt.packager.Keys._ @@ -8,8 +9,9 @@ import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping, import com.typesafe.sbt.packager.universal.Archives import com.typesafe.sbt.packager.validation._ import com.typesafe.sbt.packager.{chmod, Hashing, SettingsHelper} -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} +import xsbti.FileConverter import scala.util.matching.Regex @@ -154,7 +156,7 @@ object DebianPlugin extends AutoPlugin with DebianNativePackaging { // apply all replacements content.mapValues { lines => TemplateWriter.generateScriptFromLines(lines, replacements) - } + }.toMap }, debianMaintainerScripts := generateDebianMaintainerScripts( (Debian / maintainerScripts).value, @@ -189,12 +191,22 @@ object DebianPlugin extends AutoPlugin with DebianNativePackaging { debianPackageProvides.value, debianPackageRecommends.value ), - debianPackageInstallSize := getPackageInstallSize(linuxPackageMappings.value), + debianPackageInstallSize := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + getPackageInstallSize(linuxPackageMappings.value) + }, debianControlFile := createConfFile(debianPackageMetadata.value, debianPackageInstallSize.value, target.value), - debianConffilesFile := createConffilesFile(linuxPackageMappings.value, target.value), + debianConffilesFile := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + createConffilesFile(linuxPackageMappings.value, target.value) + }, debianMD5sumsFile := createMD5SumFile(stage.value), debianMakeChownReplacements := makeChownReplacements(linuxPackageMappings.value, streams.value), stage := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val debianTarget = target.value stageMappings(linuxPackageMappings.value, debianTarget) @@ -272,7 +284,7 @@ object DebianPlugin extends AutoPlugin with DebianNativePackaging { dirs map { case (_, dirName) => targetDir / dirName } foreach { targetDir => - targetDir mkdirs () + targetDir.mkdirs() chmod(targetDir, perms.permissions) } diff --git a/src/main/scala/com/typesafe/sbt/packager/debian/JDebPackaging.scala b/src/main/scala/com/typesafe/sbt/packager/debian/JDebPackaging.scala index 14664691d..d0ff9ea30 100644 --- a/src/main/scala/com/typesafe/sbt/packager/debian/JDebPackaging.scala +++ b/src/main/scala/com/typesafe/sbt/packager/debian/JDebPackaging.scala @@ -1,9 +1,11 @@ -package com.typesafe.sbt.packager.debian +package com.typesafe.sbt.packager +package debian +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.archetypes.TemplateWriter import com.typesafe.sbt.packager.universal.Archives -import sbt._ -import sbt.Keys.{classpathTypes, normalizedName, packageBin, streams, target, version} +import sbt.{*, given} +import sbt.Keys.{classpathTypes, fileConverter, normalizedName, packageBin, streams, target, version} import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink} import com.typesafe.sbt.packager.linux.LinuxPlugin.autoImport.{ linuxPackageMappings, @@ -14,6 +16,7 @@ import com.typesafe.sbt.packager.linux.LinuxPlugin.autoImport.{ import scala.collection.JavaConverters._ import DebianPlugin.Names import DebianPlugin.autoImport._ +import xsbti.FileConverter /** * ==JDeb Plugin== @@ -58,6 +61,8 @@ object JDebPackaging extends AutoPlugin with DebianPluginLike { * Depends on the 'debianExplodedPackage' task as this creates all the files which are defined in the mappings. */ packageBin := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val targetDir = target.value val log = streams.value.log val mappings = linuxPackageMappings.value @@ -80,8 +85,8 @@ object JDebPackaging extends AutoPlugin with DebianPluginLike { val archive = archiveFilename(normalizedName.value, version.value, packageArchitecture.value) val debianFile = targetDir.getParentFile / archive val debMaker = new JDebPackagingTask() - debMaker.packageDebian(mappings, symlinks, debianFile, targetDir, log) - debianFile + debMaker.packageDebian(mappings, symlinks, debianFile, targetDir, fileConverter.value, log) + PluginCompat.toFileRef(debianFile) }, packageBin := (packageBin dependsOn debianControlFile).value, packageBin := (packageBin dependsOn debianConffilesFile).value, @@ -147,8 +152,10 @@ private class JDebPackagingTask { symlinks: Seq[LinuxSymlink], debianFile: File, targetDir: File, + conv0: FileConverter, log: Logger ): Unit = { + implicit val conv: FileConverter = conv0 val debMaker = new DebMaker( new JDebConsole(log), (fileAndDirectoryProducers(mappings, targetDir) ++ linkProducers(symlinks)).asJava, @@ -161,8 +168,8 @@ private class JDebPackagingTask { debMaker setControl (targetDir / Names.DebianMaintainerScripts) // TODO add signing with setKeyring, setKey, setPassphrase, setSignPackage, setSignMethod, setSignRole - debMaker validate () - debMaker makeDeb () + debMaker.validate() + debMaker.makeDeb() } /** @@ -176,7 +183,7 @@ private class JDebPackagingTask { // Directories need to be created so jdeb can pick them up case (path, name) if path.isDirectory => val permMapper = new PermMapper(-1, -1, perms.user, perms.group, null, perms.permissions, -1, null) - (target / cleanPath(name)) mkdirs () + (target / cleanPath(name)).mkdirs() new DataProducerDirectory(target, Array(cleanPath(name)), null, Array(permMapper)) // Files are just referenced diff --git a/src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala index fb55453e0..484dc392d 100644 --- a/src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala @@ -2,7 +2,7 @@ package com.typesafe.sbt package packager package debian -import sbt._ +import sbt.{*, given} import linux.LinuxPackageMapping /** DEB packaging specifc build targets. */ @@ -43,10 +43,12 @@ trait DebianKeys { @deprecated("Use debian:stage instead", "1.2.0") val debianExplodedPackage = TaskKey[File]("debian-exploded-package", "makes an exploded debian package") val lintian = TaskKey[Unit]("lintian", "runs the debian lintian tool on the current package.") - val debianSign = TaskKey[File]("debian-sign", "runs the dpkg-sig command to sign the generated deb file.") + val debianSign = + taskKey[PluginCompat.FileRef]("runs the dpkg-sig command to sign the generated deb file.") val debianSignRole = SettingKey[String]("debian-sign-role", "The role to use when signing a debian file (defaults to 'builder').") - val genChanges = TaskKey[File]("gen-changes", "runs the dpkg-genchanges command to generate the .changes file.") + val genChanges = + taskKey[PluginCompat.FileRef]("runs the dpkg-genchanges command to generate the .changes file.") // Debian control scripts val debianControlScriptsDirectory = SettingKey[File]( diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala index 7175085bd..bb8e62c9f 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala @@ -1,4 +1,5 @@ -package com.typesafe.sbt.packager.docker +package com.typesafe.sbt.packager +package docker import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.Keys._ @@ -7,9 +8,8 @@ import com.typesafe.sbt.packager.linux.LinuxPlugin.autoImport.{daemonUser, defau import com.typesafe.sbt.packager.universal.UniversalPlugin import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport.stage import com.typesafe.sbt.packager.validation._ -import com.typesafe.sbt.packager.{MappingsHelper, Stager} -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} import java.io.File import java.util.UUID @@ -101,10 +101,12 @@ object DockerPlugin extends AutoPlugin { (Docker / packageName).value, Option((Docker / version).value) ), - dockerLayerGrouping := { _: String => + dockerLayerGrouping := { (_: String) => None }, dockerGroupLayers := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val dockerBaseDirectory = (Docker / defaultLinuxInstallLocation).value // Ensure this doesn't break even if the JvmPlugin isn't enabled. var artifacts = projectDependencyArtifacts.?.value.getOrElse(Nil).map(_.data).toSet @@ -119,7 +121,7 @@ object DockerPlugin extends AutoPlugin { val oldFunction = dockerLayerGrouping.value // By default we set this to a function that always returns None. - val oldPartialFunction = Function.unlift((tuple: (File, String)) => oldFunction(tuple._2)) + val oldPartialFunction = Function.unlift((tuple: (PluginCompat.FileRef, String)) => oldFunction(tuple._2)) val libDir = dockerBaseDirectory + "/lib/" val binDir = dockerBaseDirectory + "/bin/" @@ -183,6 +185,8 @@ object DockerPlugin extends AutoPlugin { } }, dockerCommands := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val strategy = dockerPermissionStrategy.value val dockerBaseDirectory = (Docker / defaultLinuxInstallLocation).value val user = (Docker / daemonUser).value @@ -220,7 +224,7 @@ object DockerPlugin extends AutoPlugin { .getOrElse { // We couldn't find a source file for the mapping, so try with a dummy source file, // in case there is an explicitly configured path based layer mapping, eg for a directory. - layerToPath.lift((new File("/dev/null"), v)) + layerToPath.lift((PluginCompat.toFileRef(new File("/dev/null")), v)) } makeChmod(tpe, Seq(pathInLayer(v, layerId))) } @@ -325,13 +329,17 @@ object DockerPlugin extends AutoPlugin { publish := publishTask.value, clean := cleanTask.value, sourceDirectory := sourceDirectory.value / "docker", - stage := Stager.stage(Docker.name)( - streams.value, - stagingDirectory.value, - dockerLayerMappings.value.map { case LayeredMapping(layerIdx, file, path) => - (file, pathInLayer(path, layerIdx)) - } - ), + stage := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + Stager.stage(Docker.name)( + streams.value, + stagingDirectory.value, + dockerLayerMappings.value.map { case LayeredMapping(layerIdx, file, path) => + (file, pathInLayer(path, layerIdx)) + } + ) + }, stage := (stage dependsOn dockerGenerateConfig).value, stagingDirectory := (Docker / target).value / "stage", dockerLayerMappings := { @@ -352,14 +360,20 @@ object DockerPlugin extends AutoPlugin { defaultLinuxInstallLocation := "/opt/docker", validatePackage := Validation .runAndThrow(validatePackageValidators.value, streams.value.log), - validatePackageValidators := Seq( - nonEmptyMappings((Docker / mappings).value), - filesExist((Docker / mappings).value), - validateExposedPorts(dockerExposedPorts.value, dockerExposedUdpPorts.value), - validateDockerVersion(dockerApiVersion.value), - validateDockerPermissionStrategy(dockerPermissionStrategy.value, dockerVersion.value, dockerApiVersion.value) - ), - dockerPackageMappings := MappingsHelper.contentOf(sourceDirectory.value), + validatePackageValidators := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val xs = (Docker / mappings).value + val fileMappings = xs.map { case (ref, p) => PluginCompat.toFile(ref) -> p } + Seq( + nonEmptyMappings(fileMappings), + filesExist(fileMappings), + validateExposedPorts(dockerExposedPorts.value, dockerExposedUdpPorts.value), + validateDockerVersion(dockerApiVersion.value), + validateDockerPermissionStrategy(dockerPermissionStrategy.value, dockerVersion.value, dockerApiVersion.value) + ) + }, + dockerPackageMappings := MappingsHelper.contentOf(sourceDirectory.value, fileConverter.value), dockerGenerateConfig := { val _ = validatePackage.value generateDockerConfig(dockerCommands.value, stagingDirectory.value) @@ -628,7 +642,7 @@ object DockerPlugin extends AutoPlugin { * uses the `Universal / mappings` to generate the `Docker / mappings`. */ def mapGenericFilesToDocker: Seq[Setting[_]] = { - def renameDests(from: Seq[(File, String)], dest: String) = + def renameDests(from: Seq[(PluginCompat.FileRef, String)], dest: String) = for { (f, path) <- from pathWithValidSeparator = if (Path.sep == '/') path else path.replace(Path.sep, '/') diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala index 6300dd323..d34126136 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala @@ -11,7 +11,7 @@ import sbt._ trait DockerKeys { val dockerGenerateConfig = TaskKey[File]("docker-generate-config", "Generates configuration file for Docker.") val dockerPackageMappings = - TaskKey[Seq[(File, String)]]("docker-package-mappings", "Generates location mappings for Docker build.") + taskKey[Seq[(PluginCompat.FileRef, String)]]("Generates location mappings for Docker build.") val dockerBaseImage = SettingKey[String]("dockerBaseImage", "Base image for Dockerfile.") @@ -64,7 +64,7 @@ private[packager] trait DockerKeysEx extends DockerKeys { "Group files by path into in layers to increase docker cache hits. " + "Lower index means the file would be a part of an earlier layer." ) - val dockerGroupLayers = taskKey[PartialFunction[(File, String), Int]]( + val dockerGroupLayers = taskKey[PartialFunction[(PluginCompat.FileRef, String), Int]]( "Group files by mapping into layers to increase docker cache hits. " + "Lower index means the file would be a part of an earlier layer." ) diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/LayeredMapping.scala b/src/main/scala/com/typesafe/sbt/packager/docker/LayeredMapping.scala index bf40bf9f6..8db7b1677 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/LayeredMapping.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/LayeredMapping.scala @@ -1,4 +1,5 @@ -package com.typesafe.sbt.packager.docker +package com.typesafe.sbt.packager +package docker import java.io.File @@ -14,4 +15,4 @@ import java.io.File * @param path * The path in the final image */ -case class LayeredMapping(layerId: Option[Int], file: File, path: String) +case class LayeredMapping(layerId: Option[Int], file: PluginCompat.FileRef, path: String) diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala b/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala index 87021d3a3..654cc5046 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala @@ -94,6 +94,6 @@ case class Dockerfile(commands: CmdLike*) { def makeContent: String = { val sb = new StringBuilder commands foreach { sb append _.makeContent } - sb toString + sb.toString() } } diff --git a/src/main/scala/com/typesafe/sbt/packager/graalvmnativeimage/GraalVMNativeImagePlugin.scala b/src/main/scala/com/typesafe/sbt/packager/graalvmnativeimage/GraalVMNativeImagePlugin.scala index e1ddbf3db..184caf3c0 100644 --- a/src/main/scala/com/typesafe/sbt/packager/graalvmnativeimage/GraalVMNativeImagePlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/graalvmnativeimage/GraalVMNativeImagePlugin.scala @@ -1,15 +1,18 @@ -package com.typesafe.sbt.packager.graalvmnativeimage +package com.typesafe.sbt.packager +package graalvmnativeimage import java.io.ByteArrayInputStream -import sbt._ -import sbt.Keys.{mainClass, name, _} import com.typesafe.sbt.packager.{MappingsHelper, Stager} -import com.typesafe.sbt.packager.Keys._ -import com.typesafe.sbt.packager.Compat._ +import com.typesafe.sbt.packager.Keys.* +import com.typesafe.sbt.packager.Compat.* import com.typesafe.sbt.packager.archetypes.JavaAppPackaging import com.typesafe.sbt.packager.docker.{Cmd, DockerPlugin, Dockerfile, ExecCmd} import com.typesafe.sbt.packager.universal.UniversalPlugin +import sbt.{*, given} +import sbt.Keys.{mainClass, name, _} +import scala.sys.process.ProcessLogger +import xsbti.FileConverter /** * Plugin to compile ahead-of-time native executables. @@ -46,7 +49,7 @@ object GraalVMNativeImagePlugin extends AutoPlugin { private lazy val scopedSettings = Seq[Setting[_]]( resourceDirectories := Seq(resourceDirectory.value), includeFilter := "*", - resources := resourceDirectories.value.descendantsExcept(includeFilter.value, excludeFilter.value).get, + resources := resourceDirectories.value.descendantsExcept(includeFilter.value, excludeFilter.value).get(), UniversalPlugin.autoImport.containerBuildImage := Def.taskDyn { graalVMNativeImageGraalVersion.value match { case Some(tag) => generateContainerBuildImage(s"$GraalVMBaseImage:$tag") @@ -54,6 +57,8 @@ object GraalVMNativeImagePlugin extends AutoPlugin { } }.value, packageBin := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val targetDirectory = target.value val binaryName = name.value val nativeImageCommand = graalVMNativeImageCommand.value @@ -67,20 +72,21 @@ object GraalVMNativeImagePlugin extends AutoPlugin { UniversalPlugin.autoImport.containerBuildImage.value match { case None => - buildLocal( + val file = buildLocal( targetDirectory, binaryName, nativeImageCommand, className, - classpathJars.map(_._1), + classpathJars.map(x => PluginCompat.toFile(x._1)), extraOptions, UnbufferedProcessLogger(streams.log) ) + PluginCompat.toFileRef(file) case Some(image) => - val resourceMappings = MappingsHelper.relative(graalResources, graalResourceDirectories) + val resourceMappings = MappingsHelper.relative(graalResources, graalResourceDirectories, conv) - buildInDockerContainer( + val file = buildInDockerContainer( targetDirectory, binaryName, className, @@ -89,8 +95,10 @@ object GraalVMNativeImagePlugin extends AutoPlugin { dockerCommand, resourceMappings, image, + conv, streams ) + PluginCompat.toFileRef(file) } } ) @@ -130,14 +138,15 @@ object GraalVMNativeImagePlugin extends AutoPlugin { targetDirectory: File, binaryName: String, className: String, - classpathJars: Seq[(File, String)], + classpathJars: Seq[(PluginCompat.FileRef, String)], extraOptions: Seq[String], dockerCommand: Seq[String], - resources: Seq[(File, String)], + resources: Seq[(PluginCompat.FileRef, String)], image: String, + conv0: FileConverter, streams: TaskStreams ): File = { - + implicit val conv: FileConverter = conv0 stage(targetDirectory, classpathJars, resources, streams) val graalDestDir = "/opt/graalvm" @@ -212,10 +221,10 @@ object GraalVMNativeImagePlugin extends AutoPlugin { private def stage( targetDirectory: File, - classpathJars: Seq[(File, String)], - resources: Seq[(File, String)], + classpathJars: Seq[(PluginCompat.FileRef, String)], + resources: Seq[(PluginCompat.FileRef, String)], streams: TaskStreams - ): File = { + )(implicit conv: FileConverter): File = { val stageDir = targetDirectory / "stage" val mappings = classpathJars ++ resources.map { case (resource, path) => resource -> s"resources/$path" diff --git a/src/main/scala/com/typesafe/sbt/packager/jar/ClasspathJarPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/jar/ClasspathJarPlugin.scala index 7185aae56..5036957c8 100644 --- a/src/main/scala/com/typesafe/sbt/packager/jar/ClasspathJarPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/jar/ClasspathJarPlugin.scala @@ -4,8 +4,9 @@ import java.io.File import java.util.jar.Attributes import sbt.Package.ManifestAttributes -import sbt._ +import sbt.{*, given} import sbt.Keys._ +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.Keys._ import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.archetypes.JavaAppPackaging @@ -13,10 +14,8 @@ import com.typesafe.sbt.packager.archetypes.JavaAppPackaging object ClasspathJarPlugin extends AutoPlugin { object autoImport { - val packageJavaClasspathJar: TaskKey[File] = TaskKey[File]( - "packageJavaClasspathJar", - "Creates a Java classpath jar that specifies the classpath in its manifest" - ) + val packageJavaClasspathJar: TaskKey[PluginCompat.FileRef] = + taskKey[PluginCompat.FileRef]("Creates a Java classpath jar that specifies the classpath in its manifest") } import autoImport._ @@ -28,18 +27,22 @@ object ClasspathJarPlugin extends AutoPlugin { packageJavaClasspathJar / artifactClassifier := Option("classpath"), packageJavaClasspathJar / packageOptions := { val classpath = (packageJavaClasspathJar / scriptClasspath).value - val manifestClasspath = Attributes.Name.CLASS_PATH -> classpath.mkString(" ") + val manifestClasspath = PluginCompat.classpathAttr -> classpath.mkString(" ") Seq(ManifestAttributes(manifestClasspath)) }, packageJavaClasspathJar / artifactName := { (scalaVersion, moduleId, artifact) => moduleId.organization + "." + artifact.name + "-" + moduleId.revision + artifact.classifier.fold("")("-" + _) + "." + artifact.extension }, - bashScriptDefines / scriptClasspath := Seq((packageJavaClasspathJar / artifactPath).value.getName), - batScriptReplacements / scriptClasspath := Seq((packageJavaClasspathJar / artifactPath).value.getName), + bashScriptDefines / scriptClasspath := { + Seq(PluginCompat.getArtifactPathName((packageJavaClasspathJar / artifactPath).value)) + }, + batScriptReplacements / scriptClasspath := { + Seq(PluginCompat.getArtifactPathName((packageJavaClasspathJar / artifactPath).value)) + }, Universal / mappings += { val classpathJar = packageJavaClasspathJar.value - classpathJar -> ("lib/" + classpathJar.getName) + classpathJar -> ("lib/" + PluginCompat.getName(classpathJar)) } ) } diff --git a/src/main/scala/com/typesafe/sbt/packager/jar/LauncherJarPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/jar/LauncherJarPlugin.scala index ae32b4471..ceeacd0b2 100644 --- a/src/main/scala/com/typesafe/sbt/packager/jar/LauncherJarPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/jar/LauncherJarPlugin.scala @@ -4,17 +4,18 @@ import java.io.File import java.util.jar.Attributes import sbt.Package.ManifestAttributes -import sbt._ +import sbt.{*, given} import sbt.Keys._ +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.Keys._ import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.archetypes.JavaAppPackaging +import xsbti.FileConverter object LauncherJarPlugin extends AutoPlugin { object autoImport { - val packageJavaLauncherJar: TaskKey[File] = TaskKey[File]( - "packageJavaLauncherJar", + val packageJavaLauncherJar: TaskKey[PluginCompat.FileRef] = taskKey[PluginCompat.FileRef]( "Creates a Java launcher jar that specifies the main class and classpath in its manifest" ) } @@ -29,9 +30,9 @@ object LauncherJarPlugin extends AutoPlugin { packageJavaLauncherJar / artifactClassifier := Option("launcher"), packageJavaLauncherJar / packageOptions := { val classpath = (packageJavaLauncherJar / scriptClasspath).value - val manifestClasspath = Attributes.Name.CLASS_PATH -> classpath.mkString(" ") + val manifestClasspath = PluginCompat.classpathAttr -> classpath.mkString(" ") val manifestMainClass = - (Compile / packageJavaLauncherJar / mainClass).value.map(Attributes.Name.MAIN_CLASS -> _) + (Compile / packageJavaLauncherJar / mainClass).value.map(PluginCompat.mainclassAttr -> _) Seq(ManifestAttributes(manifestMainClass.toSeq :+ manifestClasspath: _*)) }, packageJavaLauncherJar / artifactName := { (scalaVersion, moduleId, artifact) => @@ -39,16 +40,24 @@ object LauncherJarPlugin extends AutoPlugin { artifact.classifier.fold("")("-" + _) + "." + artifact.extension }, Compile / bashScriptDefines / mainClass := { - Some(s"""-jar "$$lib_dir/${(packageJavaLauncherJar / artifactPath).value.getName}"""") + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val a = (packageJavaLauncherJar / artifactPath).value + Some(s"""-jar "$$lib_dir/${PluginCompat.artifactPathToFile(a).getName}"""") }, bashScriptDefines / scriptClasspath := Nil, Compile / batScriptReplacements / mainClass := { - Some(s"""-jar "%APP_LIB_DIR%\\${(packageJavaLauncherJar / artifactPath).value.getName}"""") + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val a = (packageJavaLauncherJar / artifactPath).value + Some(s"""-jar "%APP_LIB_DIR%\\${PluginCompat.artifactPathToFile(a).getName}"""") }, batScriptReplacements / scriptClasspath := Nil, Universal / mappings += { val javaLauncher = packageJavaLauncherJar.value - javaLauncher -> ("lib/" + javaLauncher.getName) + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + javaLauncher -> ("lib/" + PluginCompat.toFile(javaLauncher).getName) } ) } diff --git a/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerAntHelper.scala b/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerAntHelper.scala index e4e19941e..aba8b58d6 100644 --- a/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerAntHelper.scala +++ b/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerAntHelper.scala @@ -1,12 +1,14 @@ package com.typesafe.sbt.packager.jdkpackager +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.jdkpackager.JDKPackagerPlugin.autoImport._ import org.apache.tools.ant.{BuildEvent, BuildListener, ProjectHelper} -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} import scala.util.Try import scala.xml.Elem +import xsbti.FileConverter /** * Helpers for working with Ant build definitions @@ -39,11 +41,11 @@ object JDKPackagerAntHelper { // Unlift searchPoint `Option`-s, and for each base directory, add the parent variant to cover nested JREs on Unix. val entryPoints = - searchPoints.flatten.flatMap(f ⇒ Seq(f, f.getAbsoluteFile)) + searchPoints.flatten.flatMap(f => Seq(f, f.getAbsoluteFile)) // On Windows we're often running in the JRE and not the JDK. If JDK is installed, // it's likely to be in a parallel directory, with the "jre" prefix changed to "jdk" - val entryPointsSpecialCaseWindows = entryPoints.flatMap { f ⇒ + val entryPointsSpecialCaseWindows = entryPoints.flatMap { f => if (f.getName.startsWith("jre")) Seq(f, f.getParentFile / ("jdk" + f.getName.drop(3))) else Seq(f) @@ -52,11 +54,11 @@ object JDKPackagerAntHelper { // Now search for the tool entryPointsSpecialCaseWindows .map(_ / "lib" / jarname) - .find { f ⇒ + .find { f => logger.debug(s"Looking for '$jarname' in '${f.getParent}'"); f.exists() } - .map { f ⇒ + .map { f => logger.debug(s"Found '$f'!"); f } } @@ -135,10 +137,12 @@ object JDKPackagerAntHelper { private[jdkpackager] def deployDOM( basename: String, packageType: String, - mainJar: File, + mainJar: PluginCompat.ArtifactPath, outputDir: File, - infoDOM: InfoDOM - ): DeployDOM = + infoDOM: InfoDOM, + conv0: FileConverter + ): DeployDOM = { + implicit val conv: FileConverter = conv0 // format: OFF - + + } // format: ON type BuildDOM = xml.Elem @@ -176,7 +181,7 @@ object JDKPackagerAntHelper { antExtraClasspath: Seq[File], name: String, sourceDir: File, - mappings: Seq[(File, String)], + mappings: Seq[(PluginCompat.FileRef, String)], platformDOM: PlatformDOM, applicationDOM: ApplicationDOM, deployDOM: DeployDOM @@ -233,8 +238,8 @@ object JDKPackagerAntHelper { val globs = Seq("*.dmg", "*.pkg", "*.app", "*.msi", "*.exe", "*.deb", "*.rpm") val finder = globs.foldLeft(PathFinder.empty)(_ +++ output ** _) - val result = finder.getPaths.headOption - result.foreach(f ⇒ s.log.info("Wrote " + f)) + val result = finder.getPaths().headOption + result.foreach(f => s.log.info("Wrote " + f)) result.map(file) } @@ -248,8 +253,14 @@ object JDKPackagerAntHelper { } /** Build package via Ant build.xml definition. */ - private[jdkpackager] def buildPackageWithAnt(buildXML: File, target: File, s: TaskStreams): File = { - import org.apache.tools.ant.{Project ⇒ AntProject} + private[jdkpackager] def buildPackageWithAnt( + buildXML: File, + target: File, + conv0: FileConverter, + s: TaskStreams + ): PluginCompat.FileRef = { + import org.apache.tools.ant.{Project => AntProject} + implicit val conv: FileConverter = conv0 val ap = new AntProject ap.setUserProperty("ant.file", buildXML.getAbsolutePath) @@ -264,12 +275,13 @@ object JDKPackagerAntHelper { ap.removeBuildListener(adapter) // Not sure what to do when we can't find the result - findResult(target, s).getOrElse(target) + val result = findResult(target, s).getOrElse(target) + PluginCompat.toFileRef(result) } /** For piping Ant messages to sbt logger. */ private class AntLogAdapter(s: TaskStreams) extends BuildListener { - import org.apache.tools.ant.{Project ⇒ AntProject} + import org.apache.tools.ant.{Project => AntProject} def buildFinished(event: BuildEvent): Unit = () def buildStarted(event: BuildEvent): Unit = () def targetStarted(event: BuildEvent): Unit = () @@ -278,11 +290,11 @@ object JDKPackagerAntHelper { def taskStarted(event: BuildEvent): Unit = () def messageLogged(event: BuildEvent): Unit = event.getPriority match { - case AntProject.MSG_ERR ⇒ s.log.error(event.getMessage) - case AntProject.MSG_WARN ⇒ s.log.warn(event.getMessage) - case AntProject.MSG_INFO ⇒ s.log.info(event.getMessage) - case AntProject.MSG_VERBOSE ⇒ s.log.verbose(event.getMessage) - case _ ⇒ s.log.debug(event.getMessage) + case AntProject.MSG_ERR => s.log.error(event.getMessage) + case AntProject.MSG_WARN => s.log.warn(event.getMessage) + case AntProject.MSG_INFO => s.log.info(event.getMessage) + case AntProject.MSG_VERBOSE => s.log.verbose(event.getMessage) + case _ => s.log.debug(event.getMessage) } } } diff --git a/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerPlugin.scala index 635020576..1b2d67c80 100644 --- a/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerPlugin.scala @@ -1,14 +1,14 @@ package com.typesafe.sbt.packager.jdkpackager import com.typesafe.sbt.SbtNativePackager -import com.typesafe.sbt.packager.Keys._ +import com.typesafe.sbt.packager.Keys.* import com.typesafe.sbt.packager.SettingsHelper import com.typesafe.sbt.packager.archetypes.JavaAppPackaging import com.typesafe.sbt.packager.archetypes.jar.LauncherJarPlugin -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{*, given} import SbtNativePackager.Universal -import JDKPackagerAntHelper._ +import JDKPackagerAntHelper.* /** * Package format via Oracle's packaging tool bundled with JDK 8. @@ -74,11 +74,12 @@ object JDKPackagerPlugin extends AutoPlugin { maintainer.value, jdkAppIcon.value, jdkPackagerAssociations.value - ) + ), + fileConverter.value ) ), writeAntBuild := writeAntFile(target.value, antBuildDefn.value, streams.value), - packageBin := buildPackageWithAnt(writeAntBuild.value, target.value, streams.value) + packageBin := buildPackageWithAnt(writeAntBuild.value, target.value, fileConverter.value, streams.value) ) ) diff --git a/src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala index d58ad8fa6..cd5cc8720 100644 --- a/src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala @@ -2,7 +2,7 @@ package com.typesafe.sbt package packager package linux -import sbt._ +import sbt.{*, given} import com.typesafe.sbt.packager.archetypes.systemloader.ServerLoader /** Linux packaging generic build targets. */ @@ -34,7 +34,7 @@ trait LinuxKeys { val generateManPages = TaskKey[Unit]("generate-man-pages", "Shows all the man files in the current project") val linuxMakeStartScript = - TaskKey[Option[File]]("linuxMakeStartScript", "Creates or discovers the start script used by this project") + taskKey[Option[File]]("Creates or discovers the start script used by this project") val linuxStartScriptTemplate = TaskKey[URL]( "linuxStartScriptTemplate", "The location of the template start script file we use for debian (upstart or init.d" @@ -67,7 +67,8 @@ trait LinuxKeys { """.stripMargin ) - val makeEtcDefault = TaskKey[Option[File]]("makeEtcDefault", "Creates or discovers the /etc/default/ script") + val makeEtcDefault = + taskKey[Option[File]]("Creates or discovers the /etc/default/ script") val defaultLinuxInstallLocation = SettingKey[String]("defaultLinuxInstallLocation", "The location where we will install generic linux packages.") diff --git a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxMappingDSL.scala b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxMappingDSL.scala index 5754dabe2..e2d0b9adc 100644 --- a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxMappingDSL.scala +++ b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxMappingDSL.scala @@ -1,6 +1,6 @@ package com.typesafe.sbt.packager.linux -import sbt._ +import sbt.{*, given} trait LinuxMappingDSL { @@ -13,7 +13,7 @@ trait LinuxMappingDSL { * @param files */ def packageTemplateMapping(files: String*)(dir: File = new File(sys.props("java.io.tmpdir"))) = - LinuxPackageMapping(files map ((dir, _))) + LinuxPackageMapping(files.map((dir, _))) // TODO can the packager.MappingsHelper be used here? /** @@ -34,7 +34,7 @@ trait LinuxMappingDSL { def mapDirectoryAndContents(dirs: (File, String)*): Seq[(File, String)] = for { (src, dest) <- dirs - path <- (src ** AllPassFilter).get + path <- (src ** AllPassFilter).get() } yield path -> path.toString.replaceFirst(src.toString, dest) /** diff --git a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPackageMapping.scala b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPackageMapping.scala index 4f66e0545..5e1fe1d55 100644 --- a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPackageMapping.scala +++ b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPackageMapping.scala @@ -2,7 +2,7 @@ package com.typesafe.sbt package packager package linux -import sbt._ +import sbt.{*, given} import LinuxPlugin.Users case class LinuxFileMetaData( @@ -32,7 +32,7 @@ case class LinuxPackageMapping( def withConfig(c: String = "true") = copy(fileData = fileData withConfig c) def withContents() = copy(mappings = Mapper.mapDirectoryAndContents(mappings.toSeq: _*)) - def asDocs() = copy(fileData = fileData asDocs ()) + def asDocs() = copy(fileData = fileData.asDocs()) /** Modifies the current package mapping to have gzipped data. */ def gzipped = copy(zipped = true) diff --git a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala index 44a5d4d3e..d96cc8f96 100644 --- a/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala @@ -1,10 +1,10 @@ -package com.typesafe.sbt.packager.linux +package com.typesafe.sbt.packager +package linux -import sbt._ -import sbt.Keys.{mappings, name, sourceDirectory, streams} +import sbt.{*, given} +import sbt.Keys.{fileConverter, mappings, name, sourceDirectory, streams} import com.typesafe.sbt.SbtNativePackager.Universal -import com.typesafe.sbt.packager.MappingsHelper -import com.typesafe.sbt.packager.Keys._ +import com.typesafe.sbt.packager.Keys.* import com.typesafe.sbt.packager.universal.UniversalPlugin import com.typesafe.sbt.packager.archetypes.TemplateWriter @@ -50,7 +50,7 @@ object LinuxPlugin extends AutoPlugin { Linux / sourceDirectory := sourceDirectory.value / "linux", generateManPages := { val log = streams.value.log - for (file <- ((Linux / sourceDirectory).value / "usr/share/man/man1" ** "*.1").get) { + for (file <- ((Linux / sourceDirectory).value / "usr/share/man/man1" ** "*.1").get()) { val man = makeMan(file) log.info("Generated man page for[" + file + "] =") log.info(man) @@ -116,27 +116,32 @@ object LinuxPlugin extends AutoPlugin { linuxPackageMappings ++= getUniversalFolderMappings( (Linux / packageName).value, defaultLinuxInstallLocation.value, - (Universal / mappings).value + (Universal / mappings).value, + fileConverter.value ), // Now we generate symlinks. linuxPackageSymlinks ++= { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val installLocation = defaultLinuxInstallLocation.value val linuxPackageName = (Linux / packageName).value for { (file, name) <- (Universal / mappings).value - if !file.isDirectory + if !PluginCompat.toFile(file).isDirectory if name startsWith "bin/" if !(name endsWith ".bat") // IGNORE windows-y things. } yield LinuxSymlink("/usr/" + name, installLocation + "/" + linuxPackageName + "/" + name) }, // Map configuration files linuxPackageSymlinks ++= { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val linuxPackageName = (Linux / packageName).value val installLocation = defaultLinuxInstallLocation.value val configLocation = defaultLinuxConfigLocation.value val needsConfLink = (Universal / mappings).value exists { case (file, destination) => - (destination startsWith "conf/") && !file.isDirectory + (destination startsWith "conf/") && !PluginCompat.toFile(file).isDirectory } if (needsConfLink) Seq( @@ -189,7 +194,7 @@ object LinuxPlugin extends AutoPlugin { * placeholder->content */ def controlScriptFunctionsReplacement(template: Option[URL] = None): (String, String) = { - val url = template getOrElse LinuxPlugin.controlFunctions + val url = template getOrElse LinuxPlugin.controlFunctions() LinuxPlugin.CONTROL_FUNCTIONS -> TemplateWriter.generateScript(source = url, replacements = Nil) } @@ -240,7 +245,7 @@ object LinuxPlugin extends AutoPlugin { Seq( packageMappingWithRename(binaries ++ directories: _*) withUser user withGroup group withPerms "0755", packageMappingWithRename(compressedManPages: _*).gzipped withUser user withGroup group withPerms "0644", - packageMappingWithRename(configFiles: _*) withConfig () withUser user withGroup group withPerms "0644", + packageMappingWithRename(configFiles: _*).withConfig() withUser user withGroup group withPerms "0644", packageMappingWithRename(remaining: _*) withUser user withGroup group withPerms "0644" ) } @@ -251,13 +256,17 @@ object LinuxPlugin extends AutoPlugin { private[this] def getUniversalFolderMappings( pkg: String, installLocation: String, - mappings: Seq[(File, String)] + mappings: Seq[(PluginCompat.FileRef, String)], + conv0: FileConverter ): Seq[LinuxPackageMapping] = { + implicit val conv: FileConverter = conv0 // TODO - More windows filters... - def isWindowsFile(f: (File, String)): Boolean = + def isWindowsFile(f: (PluginCompat.FileRef, String)): Boolean = f._2 endsWith ".bat" - val filtered = mappings.filterNot(isWindowsFile) + val filtered = mappings.filterNot(isWindowsFile).map { case (x, p) => + (PluginCompat.toFile(x), p) + } if (filtered.isEmpty) Seq.empty else diff --git a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala index 00e58e599..2de76b24b 100644 --- a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala +++ b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala @@ -1,14 +1,16 @@ package com.typesafe.sbt.packager.rpm -import sbt._ +import sbt.{*, given} +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.linux.LinuxSymlink import com.typesafe.sbt.packager.sourceDateEpoch +import xsbti.FileConverter object RpmHelper { /** Returns the host vendor for an rpm. */ def hostVendor = - sys.process.Process(Seq("rpm", "-E", "%{_host_vendor}")) !! + sys.process.Process(Seq("rpm", "-E", "%{_host_vendor}")).!! /** * Prepares the staging directory for the rpm build command. @@ -22,7 +24,7 @@ object RpmHelper { * @return * the `workArea` */ - def stage(spec: RpmSpec, workArea: File, log: sbt.Logger): File = { + def stage(spec: RpmSpec, workArea: File, log: sbt.Logger)(implicit conv: FileConverter): File = { buildWorkArea(workArea) copyFiles(spec, workArea, log) writeSpecFile(spec, workArea, log) @@ -31,8 +33,12 @@ object RpmHelper { workArea } - private[rpm] def defaultRpmArtifactPath(stagingArea: File, meta: RpmMetadata): File = - stagingArea / "RPMS" / meta.arch / s"${meta.name}-${meta.version}-${meta.release}.${meta.arch}.rpm" + private[rpm] def defaultRpmArtifactPath(stagingArea: File, meta: RpmMetadata)(implicit + conv: FileConverter + ): PluginCompat.ArtifactPath = + PluginCompat.toArtifactPath( + stagingArea / "RPMS" / meta.arch / s"${meta.name}-${meta.version}-${meta.release}.${meta.arch}.rpm" + ) /** * Build the rpm package @@ -46,12 +52,14 @@ object RpmHelper { * @return * The rpm package */ - def buildRpm(spec: RpmSpec, stagingArea: File, log: sbt.Logger): File = { + def buildRpm(spec: RpmSpec, stagingArea: File, log: sbt.Logger)(implicit + conv: FileConverter + ): PluginCompat.ArtifactPath = { buildPackage(stagingArea, spec, log) defaultRpmArtifactPath(stagingArea, spec.meta) } - private[this] def copyFiles(spec: RpmSpec, workArea: File, log: sbt.Logger): Unit = { + private[this] def copyFiles(spec: RpmSpec, workArea: File, log: sbt.Logger)(implicit conv: FileConverter): Unit = { // TODO - special treatment of icon... val buildroot = workArea / "tmp-buildroot" @@ -80,7 +88,9 @@ object RpmHelper { LinuxSymlink.makeSymLinks(spec.symlinks, buildroot, relativeLinks = false) } - private[this] def writeSpecFile(spec: RpmSpec, workArea: File, log: sbt.Logger): File = { + private[this] def writeSpecFile(spec: RpmSpec, workArea: File, log: sbt.Logger)(implicit + conv: FileConverter + ): File = { val specdir = workArea / "SPECS" val rpmBuildroot = workArea / "buildroot" val tmpBuildRoot = workArea / "tmp-buildroot" diff --git a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala index 169f11214..daa0909e8 100644 --- a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala +++ b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala @@ -7,6 +7,8 @@ import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping, import com.typesafe.sbt.packager.rpm.RpmPlugin.Names._ import com.typesafe.sbt.packager.archetypes.TemplateWriter import java.io.File +import java.nio.file.Files +import xsbti.FileConverter case class RpmMetadata( name: String, @@ -198,14 +200,14 @@ case class RpmSpec( sb.toString } - private[this] def fileSection: String = { + private[this] def fileSection(implicit conv: FileConverter): String = { val sb = new StringBuilder sb append "\n%files\n" // TODO - default attribute string. for { mapping <- mappings (file, dest) <- mapping.mappings - } sb append makeFilesLine(dest, mapping.fileData, file.isDirectory) + } sb.append(makeFilesLine(dest, mapping.fileData, file.isDirectory)) symlinks foreach (l => sb append s"${l.link}\n") sb.toString @@ -229,7 +231,7 @@ case class RpmSpec( } // TODO - This is *very* tied to RPM helper, may belong *in* RpmHelper - def writeSpec(rpmRoot: File, tmpRoot: File): String = { + def writeSpec(rpmRoot: File, tmpRoot: File)(implicit conv: FileConverter): String = { val sb = new StringBuilder sb append ("Name: %s\n" format meta.name) sb append ("Version: %s\n" format meta.version) diff --git a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmPlugin.scala index ea23a39c9..aa18ac416 100644 --- a/src/main/scala/com/typesafe/sbt/packager/rpm/RpmPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/rpm/RpmPlugin.scala @@ -1,15 +1,16 @@ package com.typesafe.sbt.packager.rpm -import sbt._ -import sbt.Keys._ +import sbt.{*, given} +import sbt.Keys.* import java.nio.charset.Charset import com.typesafe.sbt.SbtNativePackager.Linux +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.SettingsHelper -import com.typesafe.sbt.packager.Keys._ -import com.typesafe.sbt.packager.linux._ -import com.typesafe.sbt.packager.Compat._ -import com.typesafe.sbt.packager.validation._ +import com.typesafe.sbt.packager.Keys.* +import com.typesafe.sbt.packager.linux.* +import com.typesafe.sbt.packager.Compat.* +import com.typesafe.sbt.packager.validation.* /** * Plugin containing all generic values used for packaging rpms. @@ -104,12 +105,16 @@ object RpmPlugin extends AutoPlugin { Rpm / executableScriptName := (Linux / executableScriptName).value, rpmDaemonLogFile := s"${(Linux / packageName).value}.log", Rpm / daemonStdoutLogFile := Some(rpmDaemonLogFile.value), - Rpm / validatePackageValidators := Seq( - nonEmptyMappings((Rpm / linuxPackageMappings).value.flatMap(_.mappings)), - filesExist((Rpm / linuxPackageMappings).value.flatMap(_.mappings)), - checkMaintainer((Rpm / maintainer).value, asWarning = false), - epochIsNaturalNumber((Rpm / rpmEpoch).value.getOrElse(0)) - ), + Rpm / validatePackageValidators := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + Seq( + nonEmptyMappings((Rpm / linuxPackageMappings).value.flatMap(_.mappings)), + filesExist((Rpm / linuxPackageMappings).value.flatMap(_.mappings)), + checkMaintainer((Rpm / maintainer).value, asWarning = false), + epochIsNaturalNumber((Rpm / rpmEpoch).value.getOrElse(0)) + ) + }, // override the linux sourceDirectory setting Rpm / sourceDirectory := sourceDirectory.value, Rpm / packageArchitecture := "noarch", @@ -164,18 +169,35 @@ object RpmPlugin extends AutoPlugin { (Rpm / linuxPackageSymlinks).value, (Rpm / defaultLinuxInstallLocation).value ), - Rpm / stage := RpmHelper.stage(rpmSpecConfig.value, (Rpm / target).value, streams.value.log), - Rpm / packageBin / artifactPath := RpmHelper.defaultRpmArtifactPath((Rpm / target).value, rpmMetadata.value), + Rpm / stage := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + RpmHelper.stage(rpmSpecConfig.value, (Rpm / target).value, streams.value.log) + }, + Rpm / packageBin / artifactPath := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + RpmHelper.defaultRpmArtifactPath((Rpm / target).value, rpmMetadata.value) + }, Rpm / packageBin := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val defaultPath = RpmHelper.buildRpm(rpmSpecConfig.value, (Rpm / stage).value, streams.value.log) // `file` points to where buildRpm created the rpm. However we want it to be at `artifactPath`. // If `artifactPath` is not the default value then we need to copy the file. val path = (Rpm / packageBin / artifactPath).value - if (path.getCanonicalFile != defaultPath.getCanonicalFile) IO.copyFile(defaultPath, path) - path + val defaultPathFile = PluginCompat.artifactPathToFile(defaultPath) + val pathFile = PluginCompat.artifactPathToFile(path) + if (pathFile.getCanonicalFile != defaultPathFile.getCanonicalFile) + IO.copyFile(defaultPathFile, pathFile) + PluginCompat.toFileRef(pathFile) }, rpmLint := { - sys.process.Process(Seq("rpmlint", "-v", (Rpm / packageBin).value.getAbsolutePath)) ! streams.value.log match { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val pkg = (Rpm / packageBin).value + val path = PluginCompat.toNioPath(pkg) + sys.process.Process(Seq("rpmlint", "-v", path.toAbsolutePath().toString())).!(streams.value.log) match { case 0 => () case x => sys.error("Failed to run rpmlint, exit status: " + x) } diff --git a/src/main/scala/com/typesafe/sbt/packager/universal/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/universal/Keys.scala index 8c2e91f79..521563600 100644 --- a/src/main/scala/com/typesafe/sbt/packager/universal/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/universal/Keys.scala @@ -6,15 +6,16 @@ import sbt._ trait UniversalKeys { val packageZipTarball = - TaskKey[File]("package-zip-tarball", "Creates a tgz package.") + taskKey[PluginCompat.FileRef]("Creates a tgz package.") val packageXzTarball = - TaskKey[File]("package-xz-tarball", "Creates a txz package.") - val packageOsxDmg = TaskKey[File]("package-osx-dmg", "Creates a dmg package for macOS (only on macOS).") + taskKey[PluginCompat.FileRef]("Creates a txz package.") + val packageOsxDmg = + taskKey[PluginCompat.FileRef]("Creates a dmg package for macOS (only on macOS).") val stage = TaskKey[File]( "stage", "Create a local directory with all the files laid out as they would be in the final distribution." ) - val dist = TaskKey[File]("dist", "Creates the distribution packages.") + val dist = taskKey[PluginCompat.FileRef]("Creates the distribution packages.") val stagingDirectory = SettingKey[File]("stagingDirectory", "Directory where we stage distributions/releases.") val topLevelDirectory = SettingKey[Option[String]]("topLevelDirectory", "Top level dir in compressed output file.") val universalArchiveOptions = diff --git a/src/main/scala/com/typesafe/sbt/packager/universal/UniversalPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/universal/UniversalPlugin.scala index 502e40091..7542c45db 100644 --- a/src/main/scala/com/typesafe/sbt/packager/universal/UniversalPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/universal/UniversalPlugin.scala @@ -1,14 +1,16 @@ -package com.typesafe.sbt.packager.universal +package com.typesafe.sbt.packager +package universal -import sbt._ -import sbt.Keys._ -import Archives._ +import sbt.{*, given} +import sbt.Keys.* +import Archives.* import com.typesafe.sbt.SbtNativePackager -import com.typesafe.sbt.packager.Keys._ +import com.typesafe.sbt.packager.Keys.* import com.typesafe.sbt.packager.docker.DockerPlugin import com.typesafe.sbt.packager.validation._ import com.typesafe.sbt.packager.{SettingsHelper, Stager} import sbt.Keys.TaskStreams +import xsbti.FileConverter /** * ==Universal Plugin== @@ -84,10 +86,14 @@ object UniversalPlugin extends AutoPlugin { inConfig(config)( Seq( packageName := (packageName.value + "-" + version.value), - mappings := findSources(sourceDirectory.value), + mappings := findSources(sourceDirectory.value, fileConverter.value), dist := printDist(packageBin.value, streams.value), stagingDirectory := target.value / "stage", - stage := Stager.stage(config.name)(streams.value, stagingDirectory.value, mappings.value) + stage := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + Stager.stage(config.name)(streams.value, stagingDirectory.value, mappings.value) + } ) ) ++ Seq( config / sourceDirectory := sourceDirectory.value / config.name, @@ -105,35 +111,49 @@ object UniversalPlugin extends AutoPlugin { UniversalSrc / packageXzTarball / universalArchiveOptions := Seq("-pcvf") ) - private[this] def printDist(dist: File, streams: TaskStreams): File = { + private[this] def printDist(dist: PluginCompat.FileRef, streams: TaskStreams): PluginCompat.FileRef = { streams.log.info("") - streams.log.info("Your package is ready in " + dist.getCanonicalPath) + streams.log.info("Your package is ready in " + dist.toString()) streams.log.info("") dist } - private type Packager = (File, String, Seq[(File, String)], Option[String], Seq[String]) => File + private type Packager = + (File, String, Seq[(File, String)], Option[String], Seq[String]) => File /** Creates packaging settings for a given package key, configuration + archive type. */ - private[this] def makePackageSettings(packageKey: TaskKey[File], config: Configuration)( + private[this] def makePackageSettings(packageKey: TaskKey[PluginCompat.FileRef], config: Configuration)( packager: Packager ): Seq[Setting[_]] = inConfig(config)( Seq( packageKey / universalArchiveOptions := Nil, packageKey / mappings := mappings.value, - packageKey := packager( - target.value, - packageName.value, - (packageKey / mappings).value, - topLevelDirectory.value, - (packageKey / universalArchiveOptions).value - ), - packageKey / validatePackageValidators := (config / validatePackageValidators).value ++ Seq( - nonEmptyMappings((packageKey / mappings).value), - filesExist((packageKey / mappings).value), - checkMaintainer((packageKey / maintainer).value, asWarning = true) - ), + packageKey := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val xs = (packageKey / mappings).value + val fileMappings = xs.map { case (ref, p) => PluginCompat.toFile(ref) -> p } + val file = packager( + target.value, + packageName.value, + fileMappings, + topLevelDirectory.value, + (packageKey / universalArchiveOptions).value + ) + PluginCompat.toFileRef(file) + }, + packageKey / validatePackageValidators := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + val xs = (packageKey / mappings).value + val fileMappings = xs.map { case (ref, p) => PluginCompat.toFile(ref) -> p } + (config / validatePackageValidators).value ++ Seq( + nonEmptyMappings(fileMappings), + filesExist(fileMappings), + checkMaintainer((packageKey / maintainer).value, asWarning = true) + ) + }, packageKey / validatePackage := Validation .runAndThrow((config / packageKey / validatePackageValidators).value, streams.value.log), packageKey := packageKey.dependsOn(packageKey / validatePackage).value @@ -141,8 +161,12 @@ object UniversalPlugin extends AutoPlugin { ) /** Finds all sources in a source directory. */ - private[this] def findSources(sourceDir: File): Seq[(File, String)] = - ((PathFinder(sourceDir) ** AllPassFilter) --- sourceDir).pair(file => IO.relativize(sourceDir, file)) + private[this] def findSources(sourceDir: File, conv0: FileConverter): Seq[(PluginCompat.FileRef, String)] = { + implicit val conv: FileConverter = conv0 + ((PathFinder(sourceDir) ** AllPassFilter) --- sourceDir).pair(file => IO.relativize(sourceDir, file)).map { + case (f, p) => PluginCompat.toFileRef(f) -> p + } + } } diff --git a/src/main/scala/com/typesafe/sbt/packager/validation/package.scala b/src/main/scala/com/typesafe/sbt/packager/validation/package.scala index c770d402f..dcddff676 100644 --- a/src/main/scala/com/typesafe/sbt/packager/validation/package.scala +++ b/src/main/scala/com/typesafe/sbt/packager/validation/package.scala @@ -1,6 +1,6 @@ package com.typesafe.sbt.packager -import sbt._ +import sbt.{*, given} /** * ==validation== @@ -42,7 +42,7 @@ package object validation { } .map { case (file, dest) => ValidationError( - description = s"Not found: ${file.getAbsolutePath} (mapped to $dest)", + description = s"Not found: ${file} (mapped to $dest)", howToFix = "Generate the file in the task/setting that adds it to the mappings task" ) } diff --git a/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala index e310e0744..3d021ee14 100644 --- a/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala @@ -1,14 +1,16 @@ package com.typesafe.sbt.packager.windows -import sbt._ -import sbt.Keys.{mappings, name, packageBin, sourceDirectory, streams, target, version} +import sbt.{*, given} +import sbt.Keys.{fileConverter, mappings, name, packageBin, sourceDirectory, streams, target, version} import com.typesafe.sbt.SbtNativePackager.Universal import com.typesafe.sbt.packager.Keys.{maintainer, packageDescription, packageName, packageSummary} import com.typesafe.sbt.packager.universal.UniversalPlugin -import com.typesafe.sbt.packager.Compat._ +import com.typesafe.sbt.packager.Compat.* +import com.typesafe.sbt.packager.PluginCompat import com.typesafe.sbt.packager.SettingsHelper import com.typesafe.sbt.packager.sourceDateEpoch +import xsbti.FileConverter /** * ==Windows Plugin== @@ -96,6 +98,8 @@ object WindowsPlugin extends AutoPlugin { }, wixFiles := Seq(wixFile.value) ) ++ inConfig(Windows)(Seq(packageBin := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 val wsxSources = wixFiles.value val msi = target.value / (name.value + ".msi") @@ -107,7 +111,7 @@ object WindowsPlugin extends AutoPlugin { src.getAbsolutePath != dest.getAbsolutePath } IO.copy(wsxCopyPairs) - IO.copy(for ((f, to) <- mappings.value) yield (f, target.value / to)) + IO.copy(for ((f, to) <- mappings.value) yield (PluginCompat.toFile(f), target.value / to)) // Now compile WIX val candleCmd = findWixExecutable("candle") +: @@ -137,7 +141,7 @@ object WindowsPlugin extends AutoPlugin { case 0 => () case exitCode => sys.error(s"Unable to run build msi. Exited with ${exitCode}") } - msi + PluginCompat.toFileRef(msi) })) /** @@ -146,7 +150,11 @@ object WindowsPlugin extends AutoPlugin { def mapGenericFilesToWindows: Seq[Setting[_]] = Seq( Windows / mappings := (Universal / mappings).value, - wixFeatures := makeWindowsFeatures((Windows / packageName).value, (Windows / mappings).value) + wixFeatures := { + val conv0 = fileConverter.value + implicit val conv: FileConverter = conv0 + makeWindowsFeatures((Windows / packageName).value, (Windows / mappings).value) + } ) /** @@ -159,12 +167,15 @@ object WindowsPlugin extends AutoPlugin { * @return * windows features */ - def makeWindowsFeatures(name: String, mappings: Seq[(File, String)]): Seq[WindowsFeature] = { + def makeWindowsFeatures(name: String, mappings: Seq[(PluginCompat.FileRef, String)])(implicit + conv: FileConverter + ): Seq[WindowsFeature] = { // TODO select main script! Filter Config links! val files = for { - (file, name) <- mappings + (ref, name) <- mappings + file = PluginCompat.toFile(ref) if !file.isDirectory } yield ComponentFile(name, editable = name startsWith "conf") val corePackage = @@ -185,7 +196,8 @@ object WindowsPlugin extends AutoPlugin { components = Seq(AddDirectoryToPath("bin")) ) val configLinks = for { - (file, name) <- mappings + (ref, name) <- mappings + file = PluginCompat.toFile(ref) if !file.isDirectory if name startsWith "conf/" } yield name.replaceAll("//", "/").stripSuffix("/").stripSuffix("/") diff --git a/src/main/scala/com/typesafe/sbt/packager/windows/WixHelper.scala b/src/main/scala/com/typesafe/sbt/packager/windows/WixHelper.scala index 6af48ad9f..15d67a933 100644 --- a/src/main/scala/com/typesafe/sbt/packager/windows/WixHelper.scala +++ b/src/main/scala/com/typesafe/sbt/packager/windows/WixHelper.scala @@ -6,6 +6,7 @@ import Keys._ import sbt._ import collection.mutable.ArrayBuffer +import scala.annotation.nowarn import scala.collection.mutable case class WindowsProductInfo( @@ -81,6 +82,7 @@ object WixHelper { // so there was a gap and dirXml failed to create some directories def allParentDirs(f: File): Seq[File] = Option(f).toSeq.flatMap(f => f +: allParentDirs(f.getParentFile)) + @nowarn val filenamesPrep = for { f <- features @@ -322,7 +324,7 @@ object WixHelper { // reference: https://github.com/sbt/sbt-native-packager/issues/726 def generateComponentsAndDirectoryXml(dir: File, id_prefix: String = ""): (Seq[String], scala.xml.Node) = { def makeId(f: File) = - cleanStringForId(IO.relativize(dir, f) map (id_prefix +) getOrElse (id_prefix + f.getName)) + cleanStringForId(IO.relativize(dir, f).map(id_prefix + _).getOrElse(id_prefix + f.getName)) def handleFile(f: File): (Seq[String], scala.xml.Node) = { val id = makeId(f) val xml = ( diff --git a/src/sbt-test/jdkpackager/test-package-image/build.sbt b/src/sbt-test/jdkpackager/test-package-image/build.sbt index 0707d0db2..584055a81 100644 --- a/src/sbt-test/jdkpackager/test-package-image/build.sbt +++ b/src/sbt-test/jdkpackager/test-package-image/build.sbt @@ -30,9 +30,9 @@ jdkPackagerAssociations := Seq( ) lazy val iconGlob = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ "*.icns" - case os if os.contains("win") ⇒ "*.ico" - case _ ⇒ "*.png" + case os if os.contains("mac") => "*.icns" + case os if os.contains("win") => "*.ico" + case _ => "*.png" } jdkAppIcon := (baseDirectory.value / ".." / ".." / ".." / ".." / "test-project-jdkpackager" ** iconGlob).getPaths.headOption @@ -40,9 +40,9 @@ jdkAppIcon := (baseDirectory.value / ".." / ".." / ".." / ".." / "test-project-j TaskKey[Unit]("checkImage") := { val (extension, os) = sys.props("os.name").toLowerCase match { - case osys if osys.contains("mac") ⇒ (".app", 'mac) - case osys if osys.contains("win") ⇒ (".exe", 'windows) - case _ ⇒ ("", 'linux) + case osys if osys.contains("mac") => (".app", 'mac) + case osys if osys.contains("win") => (".exe", 'windows) + case _ => ("", 'linux) } val expectedImage = (JDKPackager / target).value / "bundles" / (name.value + extension) println(s"Checking for '${expectedImage.getAbsolutePath}'") diff --git a/src/sbt-test/jdkpackager/test-package-image/src/main/scala/ExampleApp.scala b/src/sbt-test/jdkpackager/test-package-image/src/main/scala/ExampleApp.scala index 35be79af9..05a4ff1e5 100644 --- a/src/sbt-test/jdkpackager/test-package-image/src/main/scala/ExampleApp.scala +++ b/src/sbt-test/jdkpackager/test-package-image/src/main/scala/ExampleApp.scala @@ -26,7 +26,7 @@ class ExampleApp extends Application { win.initOwner(stage) val args = getParameters.getRaw.mkString("\n") - val props = sys.props.toSeq.sortBy(_._1).map(p ⇒ s"${p._1}=${p._2}").mkString("\n") + val props = sys.props.toSeq.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString("\n") val content = new TextArea(Seq("## Application Arguments", args, "## System Properties", props).mkString("\n")) content.setPrefHeight(400) diff --git a/src/sbt-test/jdkpackager/test-package-mappings/build.sbt b/src/sbt-test/jdkpackager/test-package-mappings/build.sbt index 9e184bf2f..d9caeea9f 100644 --- a/src/sbt-test/jdkpackager/test-package-mappings/build.sbt +++ b/src/sbt-test/jdkpackager/test-package-mappings/build.sbt @@ -24,9 +24,9 @@ Universal / mappings ++= { } lazy val iconGlob = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ "*.icns" - case os if os.contains("win") ⇒ "*.ico" - case _ ⇒ "*.png" + case os if os.contains("mac") => "*.icns" + case os if os.contains("win") => "*.ico" + case _ => "*.png" } jdkAppIcon := (baseDirectory.value / ".." / ".." / ".." / ".." / "test-project-jdkpackager" ** iconGlob).getPaths.headOption @@ -34,26 +34,26 @@ jdkAppIcon := (baseDirectory.value / ".." / ".." / ".." / ".." / "test-project-j TaskKey[Unit]("checkImage") := { val (extension, os) = sys.props("os.name").toLowerCase match { - case osys if osys.contains("mac") ⇒ (".app", 'mac) - case osys if osys.contains("win") ⇒ (".exe", 'windows) - case _ ⇒ ("", 'linux) + case osys if osys.contains("mac") => (".app", 'mac) + case osys if osys.contains("win") => (".exe", 'windows) + case _ => ("", 'linux) } val expectedImage = (JDKPackager / target).value / "bundles" / (name.value + extension) println(s"Checking for '${expectedImage.getAbsolutePath}'") assert(expectedImage.exists, s"Expected image file to be found at '$expectedImage'") val files = os match { - case 'mac ⇒ + case 'mac => Seq( expectedImage / "Contents" / "Java" / "README.md", expectedImage / "Contents" / "Java" / "stuff" / "something-1.md", expectedImage / "Contents" / "Java" / "stuff" / "something-2.md" ) - case _ ⇒ + case _ => streams.value.log.warn("Test needs to be implemented for " + sys.props("os.name")) Seq.empty } println(s"Checking for ${files.map(_.getName).mkString(", ")}") - files.foreach(f ⇒ assert(f.exists, "Expected to find " + f)) + files.foreach(f => assert(f.exists, "Expected to find " + f)) } diff --git a/src/sbt-test/jdkpackager/test-package-mappings/src/main/scala/ExampleApp.scala b/src/sbt-test/jdkpackager/test-package-mappings/src/main/scala/ExampleApp.scala index abd7c0eb4..17df4c6bc 100644 --- a/src/sbt-test/jdkpackager/test-package-mappings/src/main/scala/ExampleApp.scala +++ b/src/sbt-test/jdkpackager/test-package-mappings/src/main/scala/ExampleApp.scala @@ -23,7 +23,7 @@ class ExampleApp extends Application { val win = new Stage(StageStyle.UTILITY) win.initModality(Modality.APPLICATION_MODAL) win.initOwner(stage) - val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p ⇒ s"${p._1}=${p._2}").mkString("\n")) + val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString("\n")) content.setPrefHeight(400) win.setScene(new Scene(content)) win.sizeToScene() diff --git a/src/sbt-test/jdkpackager/test-package-minimal/build.sbt b/src/sbt-test/jdkpackager/test-package-minimal/build.sbt index 87c1909d6..f2bb4ea2a 100644 --- a/src/sbt-test/jdkpackager/test-package-minimal/build.sbt +++ b/src/sbt-test/jdkpackager/test-package-minimal/build.sbt @@ -8,9 +8,9 @@ jdkPackagerType := "image" TaskKey[Unit]("checkImage") := { val extension = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ ".app" - case os if os.contains("win") ⇒ ".exe" - case _ ⇒ "" + case os if os.contains("mac") => ".app" + case os if os.contains("win") => ".exe" + case _ => "" } val expectedImage = (JDKPackager / target).value / "bundles" / (name.value + extension) println(s"Checking for '${expectedImage.getAbsolutePath}'") diff --git a/src/sbt-test/jdkpackager/test-package-minimal/src/main/scala/ExampleApp.scala b/src/sbt-test/jdkpackager/test-package-minimal/src/main/scala/ExampleApp.scala index abd7c0eb4..17df4c6bc 100644 --- a/src/sbt-test/jdkpackager/test-package-minimal/src/main/scala/ExampleApp.scala +++ b/src/sbt-test/jdkpackager/test-package-minimal/src/main/scala/ExampleApp.scala @@ -23,7 +23,7 @@ class ExampleApp extends Application { val win = new Stage(StageStyle.UTILITY) win.initModality(Modality.APPLICATION_MODAL) win.initOwner(stage) - val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p ⇒ s"${p._1}=${p._2}").mkString("\n")) + val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString("\n")) content.setPrefHeight(400) win.setScene(new Scene(content)) win.sizeToScene() diff --git a/src/sbt-test/jlink/test-jlink-minimal/build.sbt b/src/sbt-test/jlink/test-jlink-minimal/build.sbt index 7e598800f..d40155302 100644 --- a/src/sbt-test/jlink/test-jlink-minimal/build.sbt +++ b/src/sbt-test/jlink/test-jlink-minimal/build.sbt @@ -18,9 +18,9 @@ TaskKey[Unit]("runChecks") := { } val (extension, os) = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ (".app", 'mac) - case os if os.contains("win") ⇒ (".exe", 'windows) - case _ ⇒ ("", 'linux) + case os if os.contains("mac") => (".app", 'mac) + case os if os.contains("win") => (".exe", 'windows) + case _ => ("", 'linux) } val stageDir = (Universal / stagingDirectory).value diff --git a/src/sphinx/formats/jdkpackager.rst b/src/sphinx/formats/jdkpackager.rst index d6e8a113c..f0bc5e634 100644 --- a/src/sphinx/formats/jdkpackager.rst +++ b/src/sphinx/formats/jdkpackager.rst @@ -170,9 +170,9 @@ Here's what the build file looks like: packageDescription := "A test package using Oracle's JDK bundled javapackager tool." lazy val iconGlob = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ "*.icns" - case os if os.contains("win") ⇒ "*.ico" - case _ ⇒ "*.png" + case os if os.contains("mac") => "*.icns" + case os if os.contains("win") => "*.ico" + case _ => "*.png" } jdkAppIcon := (sourceDirectory.value ** iconGlob).getPaths.headOption.map(file) diff --git a/src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala b/src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala index eb2c9b80a..58991d2ba 100644 --- a/src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala +++ b/src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala @@ -6,7 +6,7 @@ import org.scalatest._ import java.io.File import java.nio.file.{Files, Path, Paths} import java.nio.file.attribute.PosixFilePermission._ -import scala.collection.JavaConversions._ +import scala.collection.JavaConverters._ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec diff --git a/test-project-jdkpackager/build.sbt b/test-project-jdkpackager/build.sbt index 267c09277..6c9de4f9f 100644 --- a/test-project-jdkpackager/build.sbt +++ b/test-project-jdkpackager/build.sbt @@ -18,9 +18,9 @@ packageSummary := "JDKPackagerPlugin example package thingy" packageDescription := "A test package using Oracle's JDK bundled javapackager tool." lazy val iconGlob = sys.props("os.name").toLowerCase match { - case os if os.contains("mac") ⇒ "*.icns" - case os if os.contains("win") ⇒ "*.ico" - case _ ⇒ "*.png" + case os if os.contains("mac") => "*.icns" + case os if os.contains("win") => "*.ico" + case _ => "*.png" } jdkAppIcon := (sourceDirectory.value ** iconGlob).getPaths.headOption.map(file) diff --git a/test-project-jdkpackager/src/main/scala/ExampleApp.scala b/test-project-jdkpackager/src/main/scala/ExampleApp.scala index abd7c0eb4..17df4c6bc 100644 --- a/test-project-jdkpackager/src/main/scala/ExampleApp.scala +++ b/test-project-jdkpackager/src/main/scala/ExampleApp.scala @@ -23,7 +23,7 @@ class ExampleApp extends Application { val win = new Stage(StageStyle.UTILITY) win.initModality(Modality.APPLICATION_MODAL) win.initOwner(stage) - val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p ⇒ s"${p._1}=${p._2}").mkString("\n")) + val content = new TextArea(sys.props.toSeq.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString("\n")) content.setPrefHeight(400) win.setScene(new Scene(content)) win.sizeToScene()