Skip to content

Commit

Permalink
fix support for top-level main methods in Scala 3 (#1592)
Browse files Browse the repository at this point in the history
* correctly escape app_mainclass variable

* add scripted test

* add ash test

* use sbt 1.9.9 for top-level-main test

* actually run command-line-settings test

* don't `eval` everything but only `$residual_args` in ash-template

* correct escaping of scary shell meta characters in ash-template

* check more scary metacharacters, factor escaping out into a function

* test more crazy edge cases

* avoid some backslashes

* more shell nasty!

* improve `checkComplexResidual` test

* fix an expansion that doesn't work in `ash`
  • Loading branch information
mberndt123 authored Apr 11, 2024
1 parent 37fcec3 commit cb29893
Show file tree
Hide file tree
Showing 14 changed files with 67 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ addApp () {
app_commands="$app_commands $1"
}

shellEscape () {
printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/")"
}

addResidual () {
residual_args="$residual_args \"$1\""
residual_args="$residual_args $(shellEscape "$1")"
}

# Allow user to specify java options. These get listed first per bash-template.
Expand Down Expand Up @@ -90,7 +94,7 @@ process_args () {
-java-home) require_arg path "$1" "$2" && jre=`eval echo $2` && java_cmd="$jre/bin/java" && shift 2 ;;

-D*|-agentlib*|-agentpath*|-javaagent*|-XX*) addJava "$1" && shift ;;
-J*) addJava "${1:2}" && shift ;;
-J*) addJava "$(printf %s "$1" | sed s/^..//)" && shift ;;
*) addResidual "$1" && shift ;;
esac
done
Expand Down Expand Up @@ -129,4 +133,5 @@ java_cmd="$(get_java_cmd)"
# If a configuration file exist, read the contents to $opts
[ -f "$script_conf_file" ] && opts=$(loadConfigFile "$script_conf_file")

eval "exec $java_cmd $java_opts -classpath $app_classpath $opts $app_mainclass $app_commands $residual_args"
eval "set -- $residual_args"
exec $java_cmd $java_opts -classpath $app_classpath $opts $app_mainclass $app_commands "$@"
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,19 @@ object BashStartScriptPlugin extends AutoPlugin with ApplicationIniGenerator wit
else
""

private[this] def shellEscape(s: String): String =
if (s.startsWith("-jar "))
s
else
s"'${s.replace("'", "'\\''")}'"

override protected[this] def createReplacementsForMainScript(
mainClass: String,
mainClasses: Seq[String],
config: SpecializedScriptConfig
): Seq[(String, String)] =
Seq(
"app_mainclass" -> mainClass,
"app_mainclass" -> shellEscape(mainClass),
"available_main_classes" -> usageMainClassReplacement(mainClasses)
) ++ config.replacements
}
9 changes: 5 additions & 4 deletions src/sbt-test/ash/command-line-settings/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ TaskKey[Unit]("checkResidual") := {
}

TaskKey[Unit]("checkComplexResidual") := {
val args = """arg1 "arg 2" 'arg "3"'"""
val args = Seq("-J-Dfoo=bar", "arg1", "--", "-J-Dfoo=bar", "arg 2", "--", "\"", "$foo", "'", "%s", "-y", "bla", "\\'", "\\\"")
val cwd = (stagingDirectory in Universal).value
val cmd = Seq((cwd / "bin" / packageName.value).getAbsolutePath, args)
val cmd = Seq((cwd / "bin" / packageName.value).getAbsolutePath) ++ args
val expected = """arg1|-J-Dfoo=bar|arg 2|--|"|$foo|'|%s|-y|bla|\'|\""""

val output = (sys.process.Process(cmd, cwd).!!).replaceAll("\n", "")
assert(output.contains(args), s"Application did not receive residual args '$args'")
val output = (sys.process.Process(cmd, cwd).!!).split("\n").last
assert(output == expected, s"Application did not receive residual args '$expected' (got '$output')")
}
1 change: 1 addition & 0 deletions src/sbt-test/ash/command-line-settings/test
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
$ exists target/universal/stage/bin/command-line-app
> checkSystemProperty
> checkResidual
> checkComplexResidual
16 changes: 16 additions & 0 deletions src/sbt-test/ash/top-level-main/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import com.typesafe.sbt.packager.Compat._

enablePlugins(AshScriptPlugin)

name := "top-level-main"

version := "0.1.0"

scalaVersion := "3.3.3"

TaskKey[Unit]("runCheck") := {
val cwd = (stagingDirectory in Universal).value
val cmd = Seq((cwd / "bin" / packageName.value).getAbsolutePath)
val output = sys.process.Process(cmd, cwd).!!
assert(output contains "SUCCESS!", "Output didn't contain success: " + output)
}
1 change: 1 addition & 0 deletions src/sbt-test/ash/top-level-main/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.9.9
1 change: 1 addition & 0 deletions src/sbt-test/ash/top-level-main/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % sys.props("project.version"))
2 changes: 2 additions & 0 deletions src/sbt-test/ash/top-level-main/src/main/scala/MainApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def main(args: Array[String]): Unit =
println("SUCCESS!")
3 changes: 3 additions & 0 deletions src/sbt-test/ash/top-level-main/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Run the staging and check the script.
> stage
> runCheck
16 changes: 16 additions & 0 deletions src/sbt-test/bash/top-level-main/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import com.typesafe.sbt.packager.Compat._

enablePlugins(JavaAppPackaging)

name := "top-level-main"

version := "0.1.0"

scalaVersion := "3.3.3"

TaskKey[Unit]("runCheck") := {
val cwd = (stagingDirectory in Universal).value
val cmd = Seq((cwd / "bin" / packageName.value).getAbsolutePath)
val output = sys.process.Process(cmd, cwd).!!
assert(output contains "SUCCESS!", "Output didn't contain success: " + output)
}
1 change: 1 addition & 0 deletions src/sbt-test/bash/top-level-main/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.9.9
1 change: 1 addition & 0 deletions src/sbt-test/bash/top-level-main/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % sys.props("project.version"))
2 changes: 2 additions & 0 deletions src/sbt-test/bash/top-level-main/src/main/scala/MainApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def main(args: Array[String]) =
println("SUCCESS!")
3 changes: 3 additions & 0 deletions src/sbt-test/bash/top-level-main/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Run the staging and check the script.
> stage
> runCheck

0 comments on commit cb29893

Please sign in to comment.